From 66ee8158b69525e12060ef558cb5d77feadab1dc Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 7 Dec 2006 00:25:44 +0100 Subject: Imported from util-linux-2.10s tarball. --- HISTORY | 74 + INSTALL | 5 + MAINTAINER | 4 +- MCONFIG | 59 +- Makefile | 4 +- README | 9 + VERSION | 2 +- clock/Makefile | 34 - clock/README.aeb | 9 - clock/README.hwclock | 27 - clock/README.shhopt-1.1 | 155 - clock/adjtime.patch | 302 -- clock/clock-ppc.c | 459 -- clock/clock.h | 34 - clock/cmos.c | 610 --- clock/hwclock.8 | 596 --- clock/hwclock.c | 1431 ------- clock/kd.c | 167 - clock/rtc.c | 389 -- clock/shhopt-1.1.lsm | 17 - clock/shhopt.c | 468 --- clock/shhopt.h | 33 - configure | 326 +- disk-utils/Makefile | 11 +- disk-utils/blockdev.8 | 55 + disk-utils/elvtune.c | 19 +- disk-utils/fdformat.c | 6 +- disk-utils/isosize.8 | 29 + disk-utils/isosize.c | 218 + disk-utils/mkfs.bfs.c | 61 +- disk-utils/mkfs.minix.8 | 3 +- disk-utils/mkfs.minix.c | 10 +- disk-utils/mkswap.c | 9 +- disk-utils/raw.c | 1 + disk-utils/setfdprm.c | 40 +- fdisk/Makefile | 5 +- fdisk/common.h | 1 + fdisk/fdisk.c | 104 +- fdisk/fdiskbsdlabel.h | 2 +- fdisk/fdisksunlabel.c | 6 + fdisk/fdisksunlabel.h | 2 +- fdisk/i386_sys_types.c | 16 +- fdisk/llseek.c | 14 + fdisk/sfdisk.c | 18 +- getopt-1.0.3b/COPYING | 339 -- getopt-1.0.3b/Changelog | 14 - getopt-1.0.3b/Makefile | 53 - getopt-1.0.3b/README | 80 - getopt-1.0.3b/TODO | 6 - getopt-1.0.3b/getopt.1 | 436 -- getopt-1.0.3b/getopt.c | 457 -- getopt-1.0.3b/gnu/getopt.c | 1050 ----- getopt-1.0.3b/gnu/getopt.h | 131 - getopt-1.0.3b/gnu/getopt1.c | 187 - getopt-1.0.3b/parse.bash | 47 - getopt-1.0.3b/parse.tcsh | 77 - getopt-1.0.3b/test.bash | 6 - getopt-1.0.3b/test.tcsh | 7 - getopt-1.1.0a/COPYING | 339 ++ getopt-1.1.0a/Changelog | 24 + getopt-1.1.0a/Makefile | 53 + getopt-1.1.0a/README | 80 + getopt-1.1.0a/TODO | 6 + getopt-1.1.0a/getopt-1.0.6.lsm | 19 + getopt-1.1.0a/getopt.1 | 441 ++ getopt-1.1.0a/getopt.c | 465 +++ getopt-1.1.0a/gnu/getopt.c | 1050 +++++ getopt-1.1.0a/gnu/getopt.h | 131 + getopt-1.1.0a/gnu/getopt1.c | 187 + getopt-1.1.0a/parse.bash | 47 + getopt-1.1.0a/parse.tcsh | 77 + getopt-1.1.0a/test.bash | 6 + getopt-1.1.0a/test.tcsh | 7 + hwclock/Makefile | 35 + hwclock/README.aeb | 9 + hwclock/README.hwclock | 27 + hwclock/README.shhopt-1.1 | 155 + hwclock/adjtime.patch | 302 ++ hwclock/clock-ppc.c | 459 ++ hwclock/clock.h | 35 + hwclock/cmos.c | 612 +++ hwclock/hwclock.8 | 595 +++ hwclock/hwclock.c | 1448 +++++++ hwclock/kd.c | 167 + hwclock/rtc.c | 396 ++ hwclock/shhopt-1.1.lsm | 17 + hwclock/shhopt.c | 468 +++ hwclock/shhopt.h | 33 + kbd/kbdrate.c | 3 +- lib/Makefile | 6 +- lib/carefulputc.c | 26 + lib/carefulputc.h | 1 + lib/nls.h | 1 + lib/pathnames.h | 2 +- lib/widechar.h | 2 + login-utils/Makefile | 54 +- login-utils/agetty.c | 39 +- login-utils/checktty.c | 17 +- login-utils/chfn.c | 31 +- login-utils/chsh.c | 31 +- login-utils/cryptocard.c | 4 +- login-utils/cryptocard.h | 7 + login-utils/initctl.8 | 106 + login-utils/initctl.c | 210 + login-utils/islocal.c | 2 + login-utils/islocal.h | 1 + login-utils/last.c | 54 +- login-utils/login.c | 105 +- login-utils/login.h | 8 + login-utils/need.8 | 85 - login-utils/need.c | 160 - login-utils/newgrp.c | 1 + login-utils/passwd.c | 26 +- login-utils/setpwnam.c | 5 + login-utils/setpwnam.h | 7 +- login-utils/shutdown.c | 191 +- login-utils/simpleinit.8 | 47 +- login-utils/simpleinit.c | 563 ++- login-utils/simpleinit.h | 3 + login-utils/ttymsg.c | 10 +- login-utils/ttymsg.h | 2 + login-utils/vipw.c | 28 +- login-utils/wall.c | 45 +- misc-utils/Makefile | 6 +- misc-utils/cal.1 | 8 +- misc-utils/cal.c | 113 +- misc-utils/ddate.c | 3 +- misc-utils/logger.1 | 7 +- misc-utils/logger.c | 24 +- misc-utils/look.c | 24 +- misc-utils/namei.c | 1 + misc-utils/procs.c | 4 +- misc-utils/script.1 | 14 +- misc-utils/script.c | 74 +- misc-utils/whereis.c | 2 + misc-utils/write.c | 64 +- mount/Makefile | 11 +- mount/README.mount | 2 +- mount/bind.c | 11 + mount/fstab.c | 350 +- mount/fstab.h | 8 +- mount/linux_fs.h | 49 + mount/lomount.c | 51 +- mount/lomount.h | 1 + mount/losetup.8 | 11 +- mount/mount.8 | 11 +- mount/mount.c | 666 +-- mount/mount_by_label.c | 51 +- mount/mount_constants.h | 19 + mount/mount_guess_fstype.c | 170 +- mount/mount_guess_fstype.h | 2 +- mount/mount_guess_rootdev.c | 90 + mount/mount_guess_rootdev.h | 1 + mount/nfs_mount4.h | 1 + mount/nfsmount.c | 20 +- mount/pivot_root.c | 2 +- mount/umount.8 | 7 +- mount/umount.c | 297 +- po/Makefile | 16 +- po/POTFILES.in | 13 +- po/cat-id-tbl.c | 3250 ++++++++------- po/cs.po | 3475 ++++++++-------- po/da.po | 9022 ++++++++++++++++++++++++++++++++++++++++ po/de.po | 3380 ++++++++------- po/es.po | 3358 ++++++++------- po/fr.po | 3507 ++++++++-------- po/it.po | 3360 ++++++++------- po/ja.po | 3865 +++++++++-------- po/nl.po | 3741 +++++++++-------- po/pt_BR.po | 4441 ++++++++++---------- sys-utils/Makefile | 4 +- sys-utils/ctrlaltdel.c | 1 + sys-utils/cytune.c | 18 +- sys-utils/ipcs.c | 76 +- sys-utils/rdev.8 | 16 +- sys-utils/rdev.c | 266 +- sys-utils/readprofile.c | 6 +- sys-utils/renice.c | 1 + sys-utils/tunelp.c | 1 + text-utils/Makefile | 4 +- text-utils/col.c | 24 +- text-utils/colcrt.c | 179 +- text-utils/colrm.c | 37 +- text-utils/column.c | 2 +- text-utils/display.c | 12 +- text-utils/more.c | 261 +- text-utils/more.help.ja | 24 + text-utils/ul.c | 128 +- 188 files changed, 37679 insertions(+), 25291 deletions(-) create mode 100644 README delete mode 100644 clock/Makefile delete mode 100644 clock/README.aeb delete mode 100644 clock/README.hwclock delete mode 100644 clock/README.shhopt-1.1 delete mode 100644 clock/adjtime.patch delete mode 100644 clock/clock-ppc.c delete mode 100644 clock/clock.h delete mode 100644 clock/cmos.c delete mode 100644 clock/hwclock.8 delete mode 100644 clock/hwclock.c delete mode 100644 clock/kd.c delete mode 100644 clock/rtc.c delete mode 100644 clock/shhopt-1.1.lsm delete mode 100644 clock/shhopt.c delete mode 100644 clock/shhopt.h create mode 100644 disk-utils/blockdev.8 create mode 100644 disk-utils/isosize.8 create mode 100644 disk-utils/isosize.c delete mode 100644 getopt-1.0.3b/COPYING delete mode 100644 getopt-1.0.3b/Changelog delete mode 100644 getopt-1.0.3b/Makefile delete mode 100644 getopt-1.0.3b/README delete mode 100644 getopt-1.0.3b/TODO delete mode 100644 getopt-1.0.3b/getopt.1 delete mode 100644 getopt-1.0.3b/getopt.c delete mode 100644 getopt-1.0.3b/gnu/getopt.c delete mode 100644 getopt-1.0.3b/gnu/getopt.h delete mode 100644 getopt-1.0.3b/gnu/getopt1.c delete mode 100644 getopt-1.0.3b/parse.bash delete mode 100644 getopt-1.0.3b/parse.tcsh delete mode 100644 getopt-1.0.3b/test.bash delete mode 100644 getopt-1.0.3b/test.tcsh create mode 100644 getopt-1.1.0a/COPYING create mode 100644 getopt-1.1.0a/Changelog create mode 100644 getopt-1.1.0a/Makefile create mode 100644 getopt-1.1.0a/README create mode 100644 getopt-1.1.0a/TODO create mode 100644 getopt-1.1.0a/getopt-1.0.6.lsm create mode 100644 getopt-1.1.0a/getopt.1 create mode 100644 getopt-1.1.0a/getopt.c create mode 100644 getopt-1.1.0a/gnu/getopt.c create mode 100644 getopt-1.1.0a/gnu/getopt.h create mode 100644 getopt-1.1.0a/gnu/getopt1.c create mode 100644 getopt-1.1.0a/parse.bash create mode 100644 getopt-1.1.0a/parse.tcsh create mode 100644 getopt-1.1.0a/test.bash create mode 100644 getopt-1.1.0a/test.tcsh create mode 100644 hwclock/Makefile create mode 100644 hwclock/README.aeb create mode 100644 hwclock/README.hwclock create mode 100644 hwclock/README.shhopt-1.1 create mode 100644 hwclock/adjtime.patch create mode 100644 hwclock/clock-ppc.c create mode 100644 hwclock/clock.h create mode 100644 hwclock/cmos.c create mode 100644 hwclock/hwclock.8 create mode 100644 hwclock/hwclock.c create mode 100644 hwclock/kd.c create mode 100644 hwclock/rtc.c create mode 100644 hwclock/shhopt-1.1.lsm create mode 100644 hwclock/shhopt.c create mode 100644 hwclock/shhopt.h create mode 100644 lib/carefulputc.c create mode 100644 lib/carefulputc.h create mode 100644 login-utils/cryptocard.h create mode 100644 login-utils/initctl.8 create mode 100644 login-utils/initctl.c create mode 100644 login-utils/islocal.h create mode 100644 login-utils/login.h delete mode 100644 login-utils/need.8 delete mode 100644 login-utils/need.c create mode 100644 login-utils/ttymsg.h create mode 100644 mount/bind.c create mode 100644 mount/mount_guess_rootdev.c create mode 100644 mount/mount_guess_rootdev.h create mode 100644 po/da.po create mode 100644 text-utils/more.help.ja diff --git a/HISTORY b/HISTORY index 9c6099de2..265d02f3e 100644 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,76 @@ +util-linux 2.10s: + +* Danish messages (Claus Hindsgaul) +* fixes to make gcc happy (Joseph S. Myers) +* fix for more on parisc (Richard Hirst) +* change rdev to search subdirectories of /dev (Paul Clements) +* ul fix (Masao Kawamura) - set columns correctly +* cal fix (Brendan Kehoe) - don't overflow weekday array in Gaelic +* fdisk fix (niles@scyld.com) - flush stdout +* fdisk fix - don't forget to write out empty label +* login: make default tty mode 0600 +* script: refuse to write typescript if that is a symlink +* script: accept -V to output version +* whereis: also search /usr/share/man. +* hwclock: improve locale handling +* hwclock: fix for Nautilus (Neoklis Kyriazis) +* isosize: new + +util-linux 2.10r: + +* mount: support mount by uuid or label for xfs (Nathan Scott) +* mount: added probe for minix on bigendian systems (Nathan Scott) +* mount: added probes for cramfs, hfs, hpfs and adfs (Sepp Wijnands) +* mount: change setup; let umount remove at most one line from /etc/mtab +* mount: improve man page +* more, col, colcrt, colrm, column, ul: nls improvements (Masao Kawamura) + +util-linux 2.10q: + +* mount: accept nonnumeric uid= and gid= options +* write and wall: security improvement +* fixed fdformat flaw (Werner Almesberger) +* use right mountport upon umount (Glenn Lingle) +* simpleinit / need / initctl stuff (Richard Gooch) +* Portuguese messages (Rodrigo Stulzer Lopes et al.) + +util-linux 2.10p: + +* mount: don't set up a loop file with -o loop,remount (Marc Mutz) +* fdisk: changes for sectorsize different from 512 +* more: standout fix (Paul Vojta) +* more: improve usage message (Lincoln Myers) +* logger: Added -d option to use datagrams (Gerwin Pfab) +* cal: Added -3 option to also print prev/next month (Michael Charles Pruznick) +* French messages (Christophe Merlet) +* Japanese messages (Daisuke Yamashita) + +util-linux 2.10o: + +* fdformat: fixed to work with kernel 2.4.0test6 (Marek Wojtowicz) +* losetup: also return status when only showing loop device status (ewt) +* mount: do not retry ro if mount was ro; improve error message +* login: not installed suid +* getopt: by default install aux files in /usr/share/misc + +util-linux 2.10n: + +* added blockdev.8 +* change to elvtune (andrea) +* fixed overrun in agetty (vii@penguinpowered.com) +* shutdown: prefer umounting by mount point (rgooch) +* fdisk: added plan9 +* fdisk: remove empty links in chain of extended partitions +* mount: define ALWAYS_STAT +* mount: add replace, after, before, over, bind +* umount: also free loop device when not writing mtab +* lomount: try both /dev/loopN and /dev/loop/N +* hwclock: handle both /dev/rtc and /dev/efirtc (Bill Nottingham) +* script: added -f (flush) option (Ivan Schreter) +* script: added -q (quiet) option (Per Andreas Buer) +* getopt: updated to version 1.1.0 (Frodo Looijaard) +* Czech messages (Jiri Pavlovsky) + util-linux 2.10m: * chfn fix when PAM is used (Martin-D. Lacasse) @@ -6,6 +79,7 @@ util-linux 2.10m: * mount new option -l: also print label when listing mounts * mount add heuristic for xfs (Martin K. Petersen) * mount UUID and label cache (Erik Troan) +* mount improve check for `already mounted' in case of label or uuid * fdisk partition names more devfs-friendly * fdisk bsdlabel large disk support * setterm.1: options documented (Colin Watson) diff --git a/INSTALL b/INSTALL index 2f960b1f0..fe3359fca 100644 --- a/INSTALL +++ b/INSTALL @@ -37,6 +37,10 @@ To install from source: If you have compilation problems: tell util-linux@math.uio.no about it. +Compilation will fail on a minix filesystem with 14-byte filenames +since for example mount_guess_fstype.h, mount_guess_fstype.c and +mount_guess_fstype.o will be the same file. (However, 30 bytes suffice.) + A glibc header bug causes /usr/include/bits/string2.h:419: warning: pointer of type `void *' used in arithmetic @@ -50,6 +54,7 @@ broken. Several old libc have complaints like /usr/include/sys/syslog.h:71: warning: missing braces around initializer + /usr/include/sys/syslog.h:87: warning: aggregate has a partly bracketed initializer /usr/include/rpc/xdr.h:103: warning: function declaration isn't a prototype /usr/include/rpc/auth.h:86: warning: function declaration isn't a prototype /usr/include/rpc/svc.h:79: warning: function declaration isn't a prototype diff --git a/MAINTAINER b/MAINTAINER index 5cd7a84e9..7fdaafc12 100644 --- a/MAINTAINER +++ b/MAINTAINER @@ -1,2 +1,4 @@ -Maintainer: Andries Brouwer (aeb@cwi.nl) +Maintainer: Andries Brouwer Maintainer address: util-linux@math.uio.no + +Maintainer of simpleinit: Richard Gooch diff --git a/MCONFIG b/MCONFIG index f1f0e3d07..a97f259d8 100644 --- a/MCONFIG +++ b/MCONFIG @@ -7,11 +7,11 @@ # - set USE_TTY_GROUP=no # - define DESTDIR -# Select for CPU one of intel, alpha, sparc, arm, m68k, mips -CPU=$(shell uname -m | sed 's/i.86/intel/;s/arm.*/arm/') - -# define where is locale directrory (default /usr/share/locale) -LOCALEDIR=/usr/share/locale +# Select for ARCH one of intel, alpha, sparc, arm, m68k, mips +# Select for CPU i386 if the binaries must be able to run on an intel 386 +# (by default i486 code is generated, see below) +CPU=$(shell uname -m) +ARCH=$(shell echo $(CPU) | sed 's/i.86/intel/;s/arm.*/arm/') # If HAVE_PAM is set to "yes", then login, chfn, chsh, and newgrp # will use PAM for authentication. Additionally, passwd will not be @@ -65,6 +65,12 @@ HAVE_GETTY=no # properly.] USE_TTY_GROUP=yes +# If ALLOW_VCS_USE is set to "yes", then login will chown /dev/vcsN +# to the current user, allowing her to make a screendump and do other +# nifty things on the console, but also allowing him to keep an open +# file descriptor after logging out to trick the next user. +ALLOW_VCS_USE=yes + # If HAVE_RESET is set to "yes", then reset won't be installed. The version # of reset that comes with the ncurses package is less aggressive. HAVE_RESET=yes @@ -81,40 +87,27 @@ HAVE_TSORT=no # If HAVE_FDUTILS is set to "yes", then setfdprm won't be installed. HAVE_FDUTILS=no -# Get CC from environment if defined -ifeq "$(CC)" "" - CC= gcc -endif - # Different optimizations for different cpus. -# Change the -m486 part if you have a 386. -ifeq "$(CPU)" "intel" - OPT= -pipe -O2 -m486 -fomit-frame-pointer +ifeq "$(ARCH)" "intel" + ifeq "$(CPU)" "i386" + OPT= -pipe -O2 -m386 -fomit-frame-pointer + else + OPT= -pipe -O2 -m486 -fomit-frame-pointer + endif else - ifeq "$(CPU)" "arm" + ifeq "$(ARCH)" "arm" OPT= -pipe -O2 -fsigned-char -fomit-frame-pointer else OPT= -O2 -fomit-frame-pointer endif endif -LDFLAGS = -s - WARNFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes LIB=../lib ERR_O=$(LIB)/err.o -CFLAGS = $(OPT) -I. -I$(LIB) $(WARNFLAGS) \ - $(CURSESFLAGS) $(SLANGFLAGS) \ - $(EXTRACFLAGS) \ - -DSBINDIR=\"$(SBINDIR)\" \ - -DUSRSBINDIR=\"$(USRSBINDIR)\" \ - -DLOGDIR=\"$(LOGDIR)\" \ - -DVARPATH=\"$(VARPATH)\" \ - -DLOCALEDIR=\"$(LOCALEDIR)\" - # Set HAVE_SLANG to yes if you have slang (and prefer to use that for cfdisk) # (If neither HAVE_NCURSES nor HAVE_SLANG is defined, cfdisk is not made.) # HAVE_SLANG=yes @@ -125,7 +118,6 @@ CFLAGS = $(OPT) -I. -I$(LIB) $(WARNFLAGS) \ # (no extra definition required). LIBSLANG=-lslang - DEVDIR= $(DESTDIR)/dev ETCDIR= $(DESTDIR)/etc SBINDIR= $(DESTDIR)/sbin @@ -133,6 +125,8 @@ USRSBINDIR= $(DESTDIR)/usr/sbin USRLIBDIR= $(DESTDIR)/usr/lib USRBINDIR= $(DESTDIR)/usr/bin USRGAMESDIR= $(DESTDIR)/usr/games +USRSHAREMISCDIR=$(DESTDIR)/usr/share/misc +LOCALEDIR= $(DESTDIR)/usr/share/locale BINDIR= $(DESTDIR)/bin VARPATH= $(DESTDIR)/var LOGDIR= $(DESTDIR)/var/log @@ -153,8 +147,8 @@ FSCKDIR= $(SBINDIR) # Directory for passwd PASSWDDIR= $(USRBINDIR) -# Directory for help file for more. Some may want /usr/share/misc . -MOREHELPDIR= $(USRLIBDIR) +# Directory for help file for more. Used to be /usr/lib. +MOREHELPDIR= $(USRSHAREMISCDIR) # Modes DIRMODE= 755 @@ -172,6 +166,15 @@ INSTALLMAN= $(INSTALL) -m $(MANMODE) INSTALLDAT= $(INSTALL) -m $(DATMODE) INSTALLSUID= $(INSTALL) -m $(SUIDMODE) -o root +CFLAGS := $(CFLAGS) $(OPT) -I$(LIB) $(WARNFLAGS) \ + $(CURSESFLAGS) $(SLANGFLAGS) \ + -DSBINDIR=\"$(SBINDIR)\" \ + -DUSRSBINDIR=\"$(USRSBINDIR)\" \ + -DLOGDIR=\"$(LOGDIR)\" \ + -DVARPATH=\"$(VARPATH)\" \ + -DLOCALEDIR=\"$(LOCALEDIR)\" + + %.o: %.c $(CC) -c $(CFLAGS) $< -o $@ diff --git a/Makefile b/Makefile index b67fb3d4b..0d68c8333 100644 --- a/Makefile +++ b/Makefile @@ -10,14 +10,14 @@ include ./MCONFIG SUBDIRS=po \ lib \ - getopt-1.0.3b \ + getopt-1.1.0a \ disk-utils \ games \ login-utils \ misc-utils \ mount \ fdisk \ - clock \ + hwclock \ sys-utils \ text-utils \ kbd diff --git a/README b/README new file mode 100644 index 000000000..48a0b13a1 --- /dev/null +++ b/README @@ -0,0 +1,9 @@ +util-linux is a random collection of Linux utilities + +The stuff in the subdirectories mount, fdisk, disk-utils, text-utils, +misc-utils, sys-utils, getopt-* should be rather distribution-neutral, +and installing it does no harm. +On the other hand, the stuff in login-utils defines initial boot-time +stuff, things that are done in different ways by different distributions. +If you install it, your machine may not boot anymore. +No RPMs are provided - get yours from your distributor. diff --git a/VERSION b/VERSION index d877938d2..77744d0d2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.10m +2.10s diff --git a/clock/Makefile b/clock/Makefile deleted file mode 100644 index 10e96051a..000000000 --- a/clock/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# Makefile -- Makefile for util-linux Linux utilities -# -include ../make_include -include ../MCONFIG - -# Where to put man pages? - -MAN8= hwclock.8 - -# Where to put binaries? -# See the "install" rule for the links. . . - -SBIN= hwclock - - -all: $(SBIN) - - -hwclock.o: hwclock.c shhopt.h -hwclock.o cmos.o rtc.o kd.o: clock.h -hwclock: hwclock.o shhopt.o cmos.o rtc.o kd.o - -CWFLAGS := $(subst -Wmissing-prototypes,,$(CFLAGS)) - -cmos.o: cmos.c - $(CC) $(CWFLAGS) -c $< -o $@ - -install: all - $(INSTALLDIR) $(SBINDIR) $(BINDIR) $(USRBINDIR) - $(INSTALLBIN) $(SBIN) $(SBINDIR) - $(INSTALLMAN) $(MAN8) $(MAN8DIR) - -clean: - -rm -f *.o *~ core $(SBIN) diff --git a/clock/README.aeb b/clock/README.aeb deleted file mode 100644 index 3955f9050..000000000 --- a/clock/README.aeb +++ /dev/null @@ -1,9 +0,0 @@ -This directory contains the hwclock stuff as fixed by me. -It should work on all architectures. - -Bryan has backported my changes to his original source, -so the present directory should be superfluous - -however, his code fails on my Sparc. -Will look at it later. - -Andries Brouwer - aeb@cwi.nl diff --git a/clock/README.hwclock b/clock/README.hwclock deleted file mode 100644 index ba8bc44c3..000000000 --- a/clock/README.hwclock +++ /dev/null @@ -1,27 +0,0 @@ -Hwclock is a program that runs under Linux and sets and queries the -Hardware Clock, which is often called the Real Time Clock, RTC, or -CMOS clock. - -Sometimes, you need to install hwclock setuid root. If you want users -other than the superuser to be able to display the clock value using the -direct ISA I/O method, install it setuid root. If you have the /dev/rtc -interface on your system or are on a non-ISA system, there's probably -no need for users to use the direct ISA I/O method, so don't bother. - -To install setuid root, do something like this: - - chmod a=rx,u=s /sbin/hwclock - -In any case, hwclock will not allow you to set anything unless you have -the superuser _real_ uid. (This is restriction is not necessary if you -haven't installed setuid root, but it's there for now). - -You may want to preformat and/or compress the man page before installing. - -If you want to build hwclock, just cd to the source directory and invoke -make with no parameters. - -hwclock calls option processing routines in the libsshopt library, -which is part of Sverre H. Huseby's "shhopt" package. You -can find a more authoritative copy of this package on metalab -(ftp://metalab.unc.edu/pub/Linux/libs/shhopt-X.Y). diff --git a/clock/README.shhopt-1.1 b/clock/README.shhopt-1.1 deleted file mode 100644 index 766d6cbdc..000000000 --- a/clock/README.shhopt-1.1 +++ /dev/null @@ -1,155 +0,0 @@ -shhopt - library for parsing command line options. -================================================== - -This is a set of functions for parsing command line options. Both -traditional one-character options, and GNU-style --long-options are -supported. - - -What separates this from traditional getopt? --------------------------------------------- - -This library does more of the parsing for you. You set up a special -structure describing the names and types of the options you want your -program to support. In the structure you also give addresses of -variables to update or functions to call for the various -options. By calling optParseOptions, all options in argv are parsed -and removed from argv. What is left, are the non-optional arguments to -your program. - -The down-side of this, is that you won't be able to make a program -where the position of the options between the non-options are -significant. - - -Usage ------ - -To see how to use this library, take a look at the sample program -example.c. - -A brief explanation: - -To parse your command line, you need to create and initialize an array -of optStruct's. Each element in the array describes a long and short -version of an option and specifies what type of option it is and how -to handle it. - -The structure fields (see also shhopt.h): - - `shortName' is the short option name without the leading '-'. - - `longName' is the long option name without the leading "--". - - `type' specifies what type of option this is. (Does it expect an - argument? Is it a flag? If it takes an argument,what type should - it be?) - - `arg' is either a function to be called with the argument from - the commandline, or a pointer to a location in which to store - the value. - - `flags' indicates whether `arg' points to a function or a storage - location. - -The different argument types: - - `OPT_END' flags this as the last element in the options array. - - `OPT_FLAG' indicates an option that takes no arguments. If `arg' is - not a function pointer, the value of `arg' will be set to 1 if - this flag is found on the command line. - - `OPT_STRING' expects a string argument. - - `OPT_INT' expects an int argument. - - `OPT_UINT' expects an unsigned int argument. - - `OPT_LONG' expects a long argument. - - `OPT_ULONG' expects an unsigned long argument. - -The different flag types: - - `OPT_CALLFUNC' indicates that `arg' is a function pointer. If this - is not given, `arg' is taken as a pointer to a variable. - - -Notes ------ - -* A dash (`-') by itself is not taken as any kind of an option, as - several programs use this to indicate the special files stdin and - stdout. It is thus left as a normal argument to the program. - -* Two dashes (`--') as an argument, is taken to mean that the rest of - the arguments should not be scanned for options. This simplifies - giving names of files that start with a dash. - -* Short (one-character) options accept parameters in two ways, either - directly following the option in the same argv-entry, or in the next - argv-entry: - - -sPARAMETER - -s PARAMETER - -* Long options accept parameters in two ways: - - --long-option=PARAMETER - --long-option PARAMETER - - To follow the GNU-tradition, your program documentation should use - the first form. - -* Several one-character options may be combined after a single - dash. If any of the options requires a parameter, the rest of the - string is taken as this parameter. If there is no "rest of the - string", the next argument is taken as the parameter. - -* There is no support for floating point (double) arguments to - options. This is to avoid unnecessary linking with the math - library. See example.c for how to get around this by writing a - function converting a string argument to a double. - - -Portability ------------ - -If your libc lacks strtoul, you will need to link with GNU's -liberty, -that may be found by anonymous ftp to prep.ai.mit.edu:/pub/gnu - -The library has (more or less recently) been compiled and `tested' on -the following systems: - - IRIX Release 5.3 IP22 - Linux 1.2.9 - SunOS Release 4.1.3_U1 (-liberty needed) - ULTRIX V4.4 (Rev. 69) - -All compilations were done using GNU's gcc, and GNU's make. - - -Author ------- - -The program is written by - - Sverre H. Huseby - Maridalsvn. 122, leil. 101 - N-0461 Oslo - Norway - - sverrehu@ifi.uio.no - http://www.ifi.uio.no/~sverrehu/ - -You can use and copy this for free. If you decide to use it, please do -me three small favours: - - 1. Tell me! (E-mail, postcard, letter, whatever. If you wish - to give me something, please send a bottle of your - favourite beer (making this BeerWare)) - 2. Let your friends and favourite download site have a copy! - (with all files intact, please..) - 3. Report any bugs you find! - diff --git a/clock/adjtime.patch b/clock/adjtime.patch deleted file mode 100644 index 81d0430fd..000000000 --- a/clock/adjtime.patch +++ /dev/null @@ -1,302 +0,0 @@ -From ao112@rgfn.epcc.edu Fri Mar 19 06:27:26 1999 -Received: from rgfn.epcc.edu (rgfn.epcc.edu [208.136.234.19]) by hera.cwi.nl with ESMTP - id GAA27711 for ; Fri, 19 Mar 1999 06:27:23 +0100 (MET) -Received: (from ao112@localhost) - by rgfn.epcc.edu (8.8.8/8.8.8) id WAA16797; - Thu, 18 Mar 1999 22:27:19 -0700 (MST) -Date: Thu, 18 Mar 1999 22:27:19 -0700 (MST) -Message-Id: <199903190527.WAA16797@rgfn.epcc.edu> -From: ao112@rgfn.epcc.edu (James P. Rutledge) -To: Andries.Brouwer@cwi.nl -Subject: Re: hwclock patch for drift_factor calculation improvement -Reply-To: ao112@rgfn.epcc.edu -Status: R - - - -> ->Could you perhaps make your patch relative to ->util-linux-2.9n (found in ftp.cwi.nl/pub/aeb/util-linux/util-linux-2.9n.tar.gz) ->? -> ->(The hwclock stuff has changed quite a bit since 2.9g.) -> ->Andries -> - -Andries; - -Per your request, the patch has been modified for util-linux version -2.9n, from the version for 2.9g. - -The program "hwclock" (version 2.4c) could give more accurate -values for the drift factor that it places in the file "/etc/adjtime". - -A patch to improve the accuracy is included. - -I have incorporated some error sources which were not compensated -for into the drift factor calculation (performed when the "--set" -or the "--systohc" option is used) to make it more accurate. -In particular, the sync delay between the desired set time and the -start of the hardware clock second, and the expected drift since the -last hardware clock adjustment are now accounted for in the drift -factor calculation. - -With this patch, if at any time an adjust operation is attempted and -the hardware clock is found to be not valid, then the calibration -and adjustment time is set to zero to insure that if the hardware -clock should coincidentally return to validity, a calibration is not -done with bad history data (hardware clock info bad) and an adjust is -not attempted on bad (but now passing validity test) hardware clock -data. (With this patch, a previous calibration time of zero causes -the calibration time to initialize with the current time, when the -hardware clock is set, but no change is made to the drift factor, -so in effect, an initial calibration is started over while the previous -drift factor is retained.) - -Also, the behavior in the case of an initially missing "/etc/adjtime" -file or such a file produced by the predecessor "clock" program has -been slightly improved as follows: - - With this patch, if the file exists but was produced by "clock" - and, thus, is given a zero calibration time, the drift factor is - not updated upon the first calibration by "hwclock", but is left alone - and is only changed by subsequent calibrations. - - With this patch, if the file does not exist and, thus, is given - a zero calibration time, the drift factor is set to zero upon the - first calibration by "hwclock" and is then changed, as appropriate, by - subsequent calibrations. - - Also, with this patch, an "--adjust" operation against a non-existent - "/etc/adjtime" file or one which has zero as the last adjustment - time will not change the hardware clock setting. - -A context diff for a patch to the file "hwclock.c" in the directory -"util-linux-2.9n/clock" is appended. -To use the patch, "cd" to the directory "util-linux-2.9n/clock". -Run "patch < bug-report", where "bug-report" is the file name of -this mail message, to get new file "hwclock.c" which contains the proposed -new version. This patch is, of course, submitted per the GPL and the -appropriate "NO WARRANTY OF ANY KIND" and "USE AT YOUR OWN RISK" -disclaimers apply. - -Note that the patch presumptuously changes the "hwclock.c" version -number from 2.4c to 2.4c1 in "hwclock.c". - -Jim - ------------------- Patch file follows ---------------------------- -*** hwclock.c Thu Mar 18 22:04:01 1999 ---- new-hwclock.c Thu Mar 18 22:03:18 1999 -*************** -*** 76,86 **** - - #include "clock.h" - #include "../version.h" - - #define MYNAME "hwclock" -! #define VERSION "2.4c" - - char *progname = MYNAME; - - /* The struct that holds our hardware access routines */ - struct clock_ops *ur; ---- 76,86 ---- - - #include "clock.h" - #include "../version.h" - - #define MYNAME "hwclock" -! #define VERSION "2.4c1" - - char *progname = MYNAME; - - /* The struct that holds our hardware access routines */ - struct clock_ops *ur; -*************** -*** 581,601 **** - - - static void - adjust_drift_factor(struct adjtime *adjtime_p, - const time_t nowtime, -! const bool hclock_valid, const time_t hclocktime ) { - /*--------------------------------------------------------------------------- - Update the drift factor in <*adjtime_p> to reflect the fact that the - Hardware Clock was calibrated to and before that was set - to . - -- We assume that the user has been doing regular drift adjustments -- using the drift factor in the adjtime file, so if and -- are different, that means the adjustment factor isn't -- quite right. -- - We record in the adjtime file the time at which we last calibrated - the clock so we can compute the drift rate each time we calibrate. - - EXCEPT: if is false, assume Hardware Clock was not set - before to anything meaningful and regular adjustments have not been ---- 581,598 ---- - - - static void - adjust_drift_factor(struct adjtime *adjtime_p, - const time_t nowtime, -! const bool hclock_valid, -! const time_t hclocktime, -! const float sync_delay ) { - /*--------------------------------------------------------------------------- - Update the drift factor in <*adjtime_p> to reflect the fact that the - Hardware Clock was calibrated to and before that was set - to . - - We record in the adjtime file the time at which we last calibrated - the clock so we can compute the drift rate each time we calibrate. - - EXCEPT: if is false, assume Hardware Clock was not set - before to anything meaningful and regular adjustments have not been -*************** -*** 604,629 **** - ----------------------------------------------------------------------------*/ - if (!hclock_valid) { - if (debug) - printf("Not adjusting drift factor because the Hardware Clock " - "previously contained garbage.\n"); - } else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) { - if (debug) - printf("Not adjusting drift factor because it has been less than a " - "day since the last calibration.\n"); - } else { -! const float factor_adjust = -! ((float) (nowtime - hclocktime) -! / (hclocktime - adjtime_p->last_calib_time)) -! * 24 * 60 * 60; - - if (debug) -! printf("Clock drifted %d seconds in the past %d seconds " - "in spite of a drift factor of %f seconds/day.\n" - "Adjusting drift factor by %f seconds/day\n", -! (int) (nowtime - hclocktime), -! (int) (hclocktime - adjtime_p->last_calib_time), - adjtime_p->drift_factor, - factor_adjust ); - - adjtime_p->drift_factor += factor_adjust; - } ---- 601,642 ---- - ----------------------------------------------------------------------------*/ - if (!hclock_valid) { - if (debug) - printf("Not adjusting drift factor because the Hardware Clock " - "previously contained garbage.\n"); -+ } else if (adjtime_p->last_calib_time == 0) { -+ if (debug) -+ printf("Not adjusting drift factor because last calibration " -+ "time is zero,\nso history is bad and calibration startover " -+ "is necessary.\n"); - } else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) { - if (debug) - printf("Not adjusting drift factor because it has been less than a " - "day since the last calibration.\n"); - } else { -! const float sec_per_day = 24.0 * 60.0 * 60.0; -! float atime_per_htime; /* adjusted time units per hardware time unit */ -! float adj_days; /* days since last adjustment (in hardware clock time) */ -! float cal_days; /* days since last calibration (in hardware clock time) */ -! float exp_drift; /* expected drift (sec) since last adjustment */ -! float unc_drift; /* uncorrected drift (sec) since last calibration */ -! float factor_adjust; /* amount to add to previous drift factor */ -! atime_per_htime = 1.0 + adjtime_p->drift_factor / sec_per_day; -! adj_days = (float)(hclocktime - adjtime_p->last_adj_time) / sec_per_day; -! exp_drift = adj_days * adjtime_p->drift_factor + adjtime_p->not_adjusted; -! unc_drift = (float)(nowtime - hclocktime) + sync_delay - exp_drift; -! cal_days = ((float)(adjtime_p->last_adj_time - adjtime_p->last_calib_time) -! + adjtime_p->not_adjusted) / (sec_per_day * atime_per_htime) -! + adj_days; -! factor_adjust = unc_drift / cal_days; - - if (debug) -! printf("Clock drifted %.1f seconds in the past %d seconds " - "in spite of a drift factor of %f seconds/day.\n" - "Adjusting drift factor by %f seconds/day\n", -! unc_drift, -! (int) (nowtime - adjtime_p->last_calib_time), - adjtime_p->drift_factor, - factor_adjust ); - - adjtime_p->drift_factor += factor_adjust; - } -*************** -*** 764,773 **** ---- 777,794 ---- - - ----------------------------------------------------------------------------*/ - if (!hclock_valid) { - fprintf(stderr, "The Hardware Clock does not contain a valid time, " - "so we cannot adjust it.\n"); -+ adjtime_p->last_calib_time = 0; /* calibration startover is required */ -+ adjtime_p->last_adj_time = 0; -+ adjtime_p->not_adjusted = 0; -+ adjtime_p->dirty = TRUE; -+ } else if (adjtime_p->last_adj_time == 0) { -+ if (debug) -+ printf("Not setting clock because last adjustment time is zero, " -+ "so history is bad."); - } else { - int adjustment; - /* Number of seconds we must insert in the Hardware Clock */ - float retro; - /* Fraction of second we have to remove from clock after inserting -*************** -*** 878,888 **** - time_diff(read_time, startup_time)); - *retcode_p = 0; - } else if (set) { - set_hardware_clock_exact(set_time, startup_time, - universal, testing); -! adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime); - *retcode_p = 0; - } else if (adjust) { - do_adjustment(&adjtime, hclock_valid, hclocktime, - read_time, universal, testing); - *retcode_p = 0; ---- 899,910 ---- - time_diff(read_time, startup_time)); - *retcode_p = 0; - } else if (set) { - set_hardware_clock_exact(set_time, startup_time, - universal, testing); -! adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime, -! time_diff(read_time, startup_time)); - *retcode_p = 0; - } else if (adjust) { - do_adjustment(&adjtime, hclock_valid, hclocktime, - read_time, universal, testing); - *retcode_p = 0; -*************** -*** 898,908 **** - - set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, - universal, testing); - *retcode_p = 0; - adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, -! hclocktime); - } else if (hctosys) { - rc = set_system_clock(hclock_valid, hclocktime, testing); - if (rc != 0) { - printf("Unable to set system clock.\n"); - *retcode_p = 1; ---- 920,930 ---- - - set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, - universal, testing); - *retcode_p = 0; - adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, -! hclocktime, (float)(read_time.tv_usec / 1E6)); - } else if (hctosys) { - rc = set_system_clock(hclock_valid, hclocktime, testing); - if (rc != 0) { - printf("Unable to set system clock.\n"); - *retcode_p = 1; - diff --git a/clock/clock-ppc.c b/clock/clock-ppc.c deleted file mode 100644 index 6d8969adb..000000000 --- a/clock/clock-ppc.c +++ /dev/null @@ -1,459 +0,0 @@ -/* -From t-matsuu@protein.osaka-u.ac.jp Sat Jan 22 13:43:20 2000 -Date: Sat, 22 Jan 2000 21:42:54 +0900 (JST) -To: Andries.Brouwer@cwi.nl -Subject: Please merge the source for PPC -From: MATSUURA Takanori - -Even now, it is used clock-1.1 based source on Linux for PowerPC -architecture, attached on this mail. - -Please merge this source in main util-linux source. - -But I'm not an author of this source, but Paul Mackerras. -http://linuxcare.com.au/paulus/ -shows details of him. - -MATSUURA Takanori @ Division of Protein Chemistry, - Institute for Protein Research, Osaka University, Japan -E-Mail: t-matsuu@protein.osaka-u.ac.jp -Web Page: http://www.protein.osaka-u.ac.jp/chemistry/matsuura/ -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -/* - * Adapted for Power Macintosh by Paul Mackerras. - */ - -/* V1.0 - * CMOS clock manipulation - Charles Hedrick, hedrick@cs.rutgers.edu, Apr 1992 - * - * clock [-u] -r - read cmos clock - * clock [-u] -w - write cmos clock from system time - * clock [-u] -s - set system time from cmos clock - * clock [-u] -a - set system time from cmos clock, adjust the time to - * correct for systematic error, and put it back to the cmos. - * -u indicates cmos clock is kept in universal time - * - * The program is designed to run setuid, since we need to be able to - * write to the CUDA. - * - ********************* - * V1.1 - * Modified for clock adjustments - Rob Hooft, hooft@chem.ruu.nl, Nov 1992 - * Also moved error messages to stderr. The program now uses getopt. - * Changed some exit codes. Made 'gcc 2.3 -Wall' happy. - * - * I think a small explanation of the adjustment routine should be given - * here. The problem with my machine is that its CMOS clock is 10 seconds - * per day slow. With this version of clock.c, and my '/etc/rc.local' - * reading '/etc/clock -au' instead of '/etc/clock -u -s', this error - * is automatically corrected at every boot. - * - * To do this job, the program reads and writes the file '/etc/adjtime' - * to determine the correction, and to save its data. In this file are - * three numbers: - * - * 1) the correction in seconds per day (So if your clock runs 5 - * seconds per day fast, the first number should read -5.0) - * 2) the number of seconds since 1/1/1970 the last time the program was - * used. - * 3) the remaining part of a second which was leftover after the last - * adjustment - * - * Installation and use of this program: - * - * a) create a file '/etc/adjtime' containing as the first and only line: - * '0.0 0 0.0' - * b) run 'clock -au' or 'clock -a', depending on whether your cmos is in - * universal or local time. This updates the second number. - * c) set your system time using the 'date' command. - * d) update your cmos time using 'clock -wu' or 'clock -w' - * e) replace the first number in /etc/adjtime by your correction. - * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local' - * - * If the adjustment doesn't work for you, try contacting me by E-mail. - * - ****** - * V1.2 - * - * Applied patches by Harald Koenig (koenig@nova.tat.physik.uni-tuebingen.de) - * Patched and indented by Rob Hooft (hooft@EMBL-Heidelberg.DE) - * - * A free quote from a MAIL-message (with spelling corrections): - * - * "I found the explanation and solution for the CMOS reading 0xff problem - * in the 0.99pl13c (ALPHA) kernel: the RTC goes offline for a small amount - * of time for updating. Solution is included in the kernel source - * (linux/kernel/time.c)." - * - * "I modified clock.c to fix this problem and added an option (now default, - * look for USE_INLINE_ASM_IO) that I/O instructions are used as inline - * code and not via /dev/port (still possible via #undef ...)." - * - * With the new code, which is partially taken from the kernel sources, - * the CMOS clock handling looks much more "official". - * Thanks Harald (and Torsten for the kernel code)! - * - ****** - * V1.3 - * Canges from alan@spri.levels.unisa.edu.au (Alan Modra): - * a) Fix a few typos in comments and remove reference to making - * clock -u a cron job. The kernel adjusts cmos time every 11 - * minutes - see kernel/sched.c and kernel/time.c set_rtc_mmss(). - * This means we should really have a cron job updating - * /etc/adjtime every 11 mins (set last_time to the current time - * and not_adjusted to ???). - * b) Swapped arguments of outb() to agree with asm/io.h macro of the - * same name. Use outb() from asm/io.h as it's slightly better. - * c) Changed CMOS_READ and CMOS_WRITE to inline functions. Inserted - * cli()..sti() pairs in appropriate places to prevent possible - * errors, and changed ioperm() call to iopl() to allow cli. - * d) Moved some variables around to localise them a bit. - * e) Fixed bug with clock -ua or clock -us that cleared environment - * variable TZ. This fix also cured the annoying display of bogus - * day of week on a number of machines. (Use mktime(), ctime() - * rather than asctime() ) - * f) Use settimeofday() rather than stime(). This one is important - * as it sets the kernel's timezone offset, which is returned by - * gettimeofday(), and used for display of MSDOS and OS2 file - * times. - * g) faith@cs.unc.edu added -D flag for debugging - * - * V1.4: alan@SPRI.Levels.UniSA.Edu.Au (Alan Modra) - * Wed Feb 8 12:29:08 1995, fix for years > 2000. - * faith@cs.unc.edu added -v option to print version. - * - * August 1996 Tom Dyas (tdyas@eden.rutgers.edu) - * Converted to be compatible with the SPARC /dev/rtc driver. - * - */ - -#define VERSION "1.4" - -/* Here the information for time adjustments is kept. */ -#define ADJPATH "/etc/adjtime" - -/* Apparently the RTC on PowerMacs stores seconds since 1 Jan 1904 */ -#define RTC_OFFSET 2082844800 - -/* used for debugging the code. */ -/*#define KEEP_OFF */ - -/* Globals */ -int readit = 0; -int adjustit = 0; -int writeit = 0; -int setit = 0; -int universal = 0; -int debug = 0; - -time_t mkgmtime(struct tm *); - -volatile void -usage ( void ) -{ - (void) fprintf (stderr, - "clock [-u] -r|w|s|a|v\n" - " r: read and print CMOS clock\n" - " w: write CMOS clock from system time\n" - " s: set system time from CMOS clock\n" - " a: get system time and adjust CMOS clock\n" - " u: CMOS clock is in universal time\n" - " v: print version (" VERSION ") and exit\n" - ); - exit(EXIT_FAILURE); -} - -int adb_fd; - -void -adb_init ( void ) -{ - adb_fd = open ("/dev/adb", 2); - if (adb_fd < 0) - { - perror ("unable to open /dev/adb read/write : "); - exit(EXIT_FAILURE); - } -} - -unsigned char get_packet[2] = { (unsigned char) CUDA_PACKET, - (unsigned char) CUDA_GET_TIME }; -unsigned char set_packet[6] = { (unsigned char) CUDA_PACKET, - (unsigned char) CUDA_SET_TIME }; - -int -main (int argc, char **argv ) -{ - struct tm tm, *tmp; - time_t systime; - time_t last_time; - time_t clock_time; - int i, arg; - double factor; - double not_adjusted; - int adjustment = 0; - /* unsigned char save_control, save_freq_select; */ - unsigned char reply[16]; - - while ((arg = getopt (argc, argv, "rwsuaDv")) != -1) - { - switch (arg) - { - case 'r': - readit = 1; - break; - case 'w': - writeit = 1; - break; - case 's': - setit = 1; - break; - case 'u': - universal = 1; - break; - case 'a': - adjustit = 1; - break; - case 'D': - debug = 1; - break; - case 'v': - (void) fprintf( stderr, "clock " VERSION "\n" ); - exit(EXIT_SUCCESS); - default: - usage (); - } - } - - /* If we are in MkLinux do not even bother trying to set the clock */ - if(!access("/proc/osfmach3/version", R_OK)) - { // We're running MkLinux - if ( readit | writeit | setit | adjustit ) - printf("You must change the clock setting in MacOS.\n"); - exit(0); - } - - if (readit + writeit + setit + adjustit > 1) - usage (); /* only allow one of these */ - - if (!(readit | writeit | setit | adjustit)) /* default to read */ - readit = 1; - - adb_init (); - - if (adjustit) - { /* Read adjustment parameters first */ - FILE *adj; - if ((adj = fopen (ADJPATH, "r")) == NULL) - { - perror (ADJPATH); - exit(EXIT_FAILURE); - } - if (fscanf (adj, "%lf %d %lf", &factor, (int *) (&last_time), - ¬_adjusted) < 0) - { - perror (ADJPATH); - exit(EXIT_FAILURE); - } - (void) fclose (adj); - if (debug) (void) printf( - "Last adjustment done at %d seconds after 1/1/1970\n", - (int) last_time); - } - - if (readit || setit || adjustit) - { - int ii; - - if (write(adb_fd, get_packet, sizeof(get_packet)) < 0) { - perror("write adb"); - exit(EXIT_FAILURE); - } - ii = (int) read(adb_fd, reply, sizeof(reply)); - if (ii < 0) { - perror("read adb"); - exit(EXIT_FAILURE); - } - if (ii != 7) - (void) fprintf(stderr, - "Warning: bad reply length from CUDA (%d)\n", ii); - clock_time = (time_t) ((reply[3] << 24) + (reply[4] << 16) - + (reply[5] << 8)) + (time_t) reply[6]; - clock_time -= RTC_OFFSET; - - if (universal) { - systime = clock_time; - } else { - tm = *gmtime(&clock_time); - (void) printf("time in rtc is %s", asctime(&tm)); - tm.tm_isdst = -1; /* don't know whether it's DST */ - systime = mktime(&tm); - } - } - - if (readit) - { - (void) printf ("%s", ctime (&systime )); - } - - if (setit || adjustit) - { - struct timeval tv; - struct timezone tz; - -/* program is designed to run setuid, be secure! */ - - if (getuid () != 0) - { - (void) fprintf (stderr, - "Sorry, must be root to set or adjust time\n"); - exit(EXIT_FAILURE); - } - - if (adjustit) - { /* the actual adjustment */ - double exact_adjustment; - - exact_adjustment = ((double) (systime - last_time)) - * factor / (24 * 60 * 60) - + not_adjusted; - if (exact_adjustment > 0.) - adjustment = (int) (exact_adjustment + 0.5); - else - adjustment = (int) (exact_adjustment - 0.5); - not_adjusted = exact_adjustment - (double) adjustment; - systime += adjustment; - if (debug) { - (void) printf ("Time since last adjustment is %d seconds\n", - (int) (systime - last_time)); - (void) printf ("Adjusting time by %d seconds\n", - adjustment); - (void) printf ("remaining adjustment is %.3f seconds\n", - not_adjusted); - } - } -#ifndef KEEP_OFF - tv.tv_sec = systime; - tv.tv_usec = 0; - tz.tz_minuteswest = timezone / 60; - tz.tz_dsttime = daylight; - - if (settimeofday (&tv, &tz) != 0) - { - (void) fprintf (stderr, - "Unable to set time -- probably you are not root\n"); - exit(EXIT_FAILURE); - } - - if (debug) { - (void) printf( "Called settimeofday:\n" ); - (void) printf( "\ttv.tv_sec = %ld, tv.tv_usec = %ld\n", - tv.tv_sec, tv.tv_usec ); - (void) printf( "\ttz.tz_minuteswest = %d, tz.tz_dsttime = %d\n", - tz.tz_minuteswest, tz.tz_dsttime ); - } -#endif - } - - if (writeit || (adjustit && adjustment != 0)) - { - systime = time (NULL); - - if (universal) { - clock_time = systime; - - } else { - tmp = localtime(&systime); - clock_time = mkgmtime(tmp); - } - - clock_time += RTC_OFFSET; - set_packet[2] = clock_time >> 24; - set_packet[3] = clock_time >> 16; - set_packet[4] = clock_time >> 8; - set_packet[5] = (unsigned char) clock_time; - - if (write(adb_fd, set_packet, sizeof(set_packet)) < 0) { - perror("write adb (set)"); - exit(EXIT_FAILURE); - } - i = (int) read(adb_fd, reply, sizeof(reply)); - if (debug) { - int j; - (void) printf("set reply %d bytes:", i); - for (j = 0; j < i; ++j) - (void) printf(" %.2x", (unsigned int) reply[j]); - (void) printf("\n"); - } - if (i != 3 || reply[1] != (unsigned char) 0) - (void) fprintf(stderr, "Warning: error %d setting RTC\n", - (int) reply[1]); - - if (debug) { - clock_time -= RTC_OFFSET; - (void) printf("set RTC to %s", asctime(gmtime(&clock_time))); - } - } - else - if (debug) (void) printf ("CMOS clock unchanged.\n"); - /* Save data for next 'adjustit' call */ - if (adjustit) - { - FILE *adj; - if ((adj = fopen (ADJPATH, "w")) == NULL) - { - perror (ADJPATH); - exit(EXIT_FAILURE); - } - (void) fprintf (adj, "%f %d %f\n", factor, (int) systime, not_adjusted); - (void) fclose (adj); - } - exit(EXIT_SUCCESS); -} - -/* Stolen from linux/arch/i386/kernel/time.c. */ -/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. - * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 - * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. - * - * [For the Julian calendar (which was used in Russia before 1917, - * Britain & colonies before 1752, anywhere else before 1582, - * and is still in use by some communities) leave out the - * -year/100+year/400 terms, and add 10.] - * - * This algorithm was first published by Gauss (I think). - * - * WARNING: this function will overflow on 2106-02-07 06:28:16 on - * machines were long is 32-bit! (However, as time_t is signed, we - * will already get problems at other places on 2038-01-19 03:14:08) - */ -time_t mkgmtime(struct tm *tm) -{ - int mon = tm->tm_mon + 1; - int year = tm->tm_year + 1900; - - if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ - mon += 12; /* Puts Feb last since it has leap day */ - year -= 1; - } - return ((( - (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12) + - tm->tm_mday + year*365 - 719499 - )*24 + tm->tm_hour /* now have hours */ - )*60 + tm->tm_min /* now have minutes */ - )*60 + tm->tm_sec; /* finally seconds */ -} diff --git a/clock/clock.h b/clock/clock.h deleted file mode 100644 index fc91826ce..000000000 --- a/clock/clock.h +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include /* for errno, EPERM, EINVAL, ENOENT */ -#include - -struct clock_ops { - char *interface_name; - int (*get_permissions)(void); - int (*read_hardware_clock)(struct tm *tm); - int (*set_hardware_clock)(const struct tm *tm); - int (*synchronize_to_clock_tick)(void); -}; - -extern struct clock_ops *probe_for_cmos_clock(void); -extern struct clock_ops *probe_for_rtc_clock(void); -extern struct clock_ops *probe_for_kd_clock(void); - -typedef int bool; -#define TRUE 1 -#define FALSE 0 - -/* hwclock.c */ -extern char *progname; -extern int debug; -extern int epoch_option; -extern void outsyserr(char *msg); - -/* cmos.c */ -extern void set_cmos_epoch(int ARCconsole, int SRM); -extern void set_cmos_access(int Jensen, int funky_toy); - -/* rtc.c */ -extern int get_epoch_rtc(unsigned long *epoch, int silent); -extern int set_epoch_rtc(unsigned long epoch); diff --git a/clock/cmos.c b/clock/cmos.c deleted file mode 100644 index 16705bf7f..000000000 --- a/clock/cmos.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * i386 CMOS starts out with 14 bytes clock data - * alpha has something similar, but with details - * depending on the machine type. - * - * byte 0: seconds (0-59) - * byte 2: minutes (0-59) - * byte 4: hours (0-23 in 24hr mode, - * 1-12 in 12hr mode, with high bit unset/set if am/pm) - * byte 6: weekday (1-7, Sunday=1) - * byte 7: day of the month (1-31) - * byte 8: month (1-12) - * byte 9: year (0-99) - * Numbers are stored in BCD/binary if bit 2 of byte 11 is unset/set - * The clock is in 12hr/24hr mode if bit 1 of byte 11 is unset/set - * The clock is undefined (being updated) if bit 7 of byte 10 is set. - * The clock is frozen (to be updated) by setting bit 7 of byte 11 - * Bit 7 of byte 14 indicates whether the CMOS clock is reliable: - * it is 1 if RTC power has been good since this bit was last read; - * it is 0 when the battery is dead and system power has been off. - * - * Avoid setting the RTC clock within 2 seconds of the day rollover - * that starts a new month or enters daylight saving time. - * - * The century situation is messy: - * Usually byte 50 (0x32) gives the century (in BCD, so 19 or 20 hex), - * but IBM PS/2 has (part of) a checksum there and uses byte 55 (0x37). - * Sometimes byte 127 (0x7f) or Bank 1, byte 0x48 gives the century. - * The original RTC will not access any century byte; some modern - * versions will. If a modern RTC or BIOS increments the century byte - * it may go from 0x19 to 0x20, but in some buggy cases 0x1a is produced. - */ - -/* - * A struct tm has int fields - * tm_sec (0-59, 60 or 61 only for leap seconds) - * tm_min (0-59) - * tm_hour (0-23) - * tm_mday (1-31) - * tm_mon (0-11) - * tm_year (number of years since 1900) - * tm_wday (0-6, 0=Sunday) - * tm_yday (0-365) - * tm_isdst (>0: yes, 0: no, <0: unknown) - */ - -#include /* for geteuid() */ -#include /* for O_RDWR */ - -#include "nls.h" - -#if defined(__i386__) || defined(__alpha__) -#include /* for inb, outb */ -#else -void outb(int a, int b){} -int inb(int c){ return 0; } -#endif - -#include "clock.h" - -#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) -#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) - -#define TM_EPOCH 1900 -int cmos_epoch = 1900; /* 1980 for an alpha in ARC console time */ - /* One also sees 1952 (Digital Unix) - and 1958 (ALPHA_PRE_V1_2_SRM_CONSOLE) */ - -/* Martin Ostermann writes: -The problem with the Jensen is twofold: First, it has the clock at a -different address. Secondly, it has a distinction beween "local" and -normal bus addresses. The local ones pertain to the hardware integrated -into the chipset, like serial/parallel ports and of course, the RTC. -Those need to be addressed differently. This is handled fine in the kernel, -and it's not a problem, since this usually gets totally optimized by the -compile. But the i/o routines of (g)libc lack this support so far. -The result of this is, that the old clock program worked only on the -Jensen when USE_DEV_PORT was defined, but not with the normal inb/outb -functions. - */ -int use_dev_port = 0; /* 1 for Jensen */ -int dev_port_fd; -unsigned short clock_ctl_addr = 0x70; /* 0x170 for Jensen */ -unsigned short clock_data_addr = 0x71; /* 0x171 for Jensen */ - - -int century_byte = 0; /* 0: don't access a century byte - 50 (0x32): usual PC value - 55 (0x37): PS/2 */ - -#ifdef __alpha__ -int funkyTOY = 0; /* 1 for PC164/LX164/SX164 type alpha */ -#endif - -#ifdef __alpha - -static int -is_in_cpuinfo(char *fmt, char *str) -{ - FILE *cpuinfo; - char field[256]; - char format[256]; - int found = 0; - - sprintf(format, "%s : %s", fmt, "%255s"); - - if ((cpuinfo = fopen ("/proc/cpuinfo", "r")) != NULL) { - while (!feof(cpuinfo)) { - if (fscanf (cpuinfo, format, field) == 1) { - if (strncmp(field, str, strlen(str)) == 0) - found = 1; - break; - } - fgets (field, 256, cpuinfo); - } - fclose(cpuinfo); - } - return found; -} - -/* Set cmos_epoch, either from user options, or by asking the kernel, - or by looking at /proc/cpu_info */ -void -set_cmos_epoch(int ARCconsole, int SRM) { - unsigned long epoch; - - /* Believe the user */ - if (epoch_option != -1) { - cmos_epoch = epoch_option; - return; - } - - if (ARCconsole) - cmos_epoch = 1980; - - if (ARCconsole || SRM) - return; - - - /* If we can ask the kernel, we don't need guessing from /proc/cpuinfo */ - if (get_epoch_rtc(&epoch, 1) == 0) { - cmos_epoch = epoch; - return; - } - - /* The kernel source today says: read the year. If it is - in 11-43 then the epoch is 1980 (this covers 1991-2023). - Otherwise, if it is less than 96 then the epoch is 1952 - (this covers 1952-1962 and 1996-2047). Otherwise, the epoch - is 1900 (this covers 1996-1999, or rather 1996-2155). */ - - - /* See whether we are dealing with SRM or MILO, as they have - different "epoch" ideas. */ - if (is_in_cpuinfo("system serial number", "MILO")) { - ARCconsole = 1; - if (debug) printf (_("booted from MILO\n")); - } - - /* See whether we are dealing with a RUFFIAN aka Alpha PC-164 UX (or BX), - as they have REALLY different TOY (TimeOfYear) format: BCD, and not - an ARC-style epoch. - BCD is detected dynamically, but we must NOT adjust like ARC. */ - if (ARCconsole && is_in_cpuinfo("system type", "Ruffian")) { - ARCconsole = 0; - if (debug) printf (_("Ruffian BCD clock\n")); - } - - if (ARCconsole) - cmos_epoch = 1980; -} - -void -set_cmos_access(int Jensen, int funky_toy) { - - /* See whether we're dealing with a Jensen---it has a weird I/O - system. DEC was just learning how to build Alpha PCs. */ - if (Jensen || is_in_cpuinfo("system type", "Jensen")) { - use_dev_port = 1; - clock_ctl_addr = 0x170; - clock_data_addr = 0x171; - if (debug) printf (_("clockport adjusted to 0x%x\n"), clock_ctl_addr); - } - - /* see whether we are dealing with PC164/LX164/SX164, as they have a TOY - that must be accessed differently to work correctly. */ - if (funky_toy || - is_in_cpuinfo("system variation", "PC164") || - is_in_cpuinfo("system variation", "LX164") || - is_in_cpuinfo("system variation", "SX164")) { - funkyTOY = 1; - if (debug) printf (_("funky TOY!\n")); - } -} -#endif - - - - -#ifdef __i386__ - -/* - * Try to do CMOS access atomically, so that no other processes - * can get a time slice while we are reading or setting the clock. - * (Also, if the kernel time is synchronized with an external source, - * the kernel itself will fiddle with the RTC every 11 minutes.) - */ - -static unsigned long -atomic(const char *name, unsigned long (*op)(unsigned long), - unsigned long arg) -{ - unsigned long v; - __asm__ volatile ("cli"); - v = (*op)(arg); - __asm__ volatile ("sti"); - return v; -} - -#elif __alpha__ - -/* - * The Alpha doesn't allow user-level code to disable interrupts (for - * good reasons). Instead, we ensure atomic operation by performing - * the operation and checking whether the high 32 bits of the cycle - * counter changed. If they did, a context switch must have occurred - * and we redo the operation. As long as the operation is reasonably - * short, it will complete atomically, eventually. - */ - -static unsigned long -atomic(const char *name, unsigned long (*op)(unsigned long), - unsigned long arg) -{ - unsigned long ts1, ts2, n, v; - - for (n = 0; n < 1000; ++n) { - asm volatile ("rpcc %0" : "r="(ts1)); - v = (*op)(arg); - asm volatile ("rpcc %0" : "r="(ts2)); - - if ((ts1 ^ ts2) >> 32 == 0) { - return v; - } - } - fprintf(stderr, _("%s: atomic %s failed for 1000 iterations!"), progname, name); - exit(1); -} - -#else - -/* - * Hmmh, this isn't very atomic. Maybe we should force an error - * instead? - */ -static unsigned long -atomic(const char *name, unsigned long (*op)(unsigned long), - unsigned long arg) -{ - return (*op)(arg); -} - -#endif - - -static inline -unsigned long cmos_read(unsigned long reg) -{ - if (use_dev_port) { - unsigned char v = reg | 0x80; - lseek(dev_port_fd, clock_ctl_addr, 0); - write(dev_port_fd, &v, 1); - lseek(dev_port_fd, clock_data_addr, 0); - read(dev_port_fd, &v, 1); - return v; - } else { - /* We only want to read CMOS data, but unfortunately - writing to bit 7 disables (1) or enables (0) NMI; - since this bit is read-only we have to guess the old status. - Various docs suggest that one should disable NMI while - reading/writing CMOS data, and enable it again afterwards. - This would yield the sequence - outb (reg | 0x80, 0x70); - val = inb(0x71); - outb (0x0d, 0x70); // 0x0d: random read-only location - Other docs state that "any write to 0x70 should be followed - by an action to 0x71 or the RTC wil be left in an unknown state". - Most docs say that it doesnt matter at all what one does. - */ - /* bit 0x80: disable NMI while reading - should we? - Let us follow the kernel and not disable. - Called only with 0 <= reg < 128 */ - outb (reg, clock_ctl_addr); - return inb (clock_data_addr); - } -} - -static inline -unsigned long cmos_write(unsigned long reg, unsigned long val) -{ - if (use_dev_port) { - unsigned char v = reg | 0x80; - lseek(dev_port_fd, clock_ctl_addr, 0); - write(dev_port_fd, &v, 1); - v = (val & 0xff); - lseek(dev_port_fd, clock_data_addr, 0); - write(dev_port_fd, &v, 1); - } else { - outb (reg, clock_ctl_addr); - outb (val, clock_data_addr); - } - return 0; -} - -unsigned long cmos_set_time(unsigned long arg) -{ - unsigned char save_control, save_freq_select, pmbit = 0; - struct tm tm = *(struct tm *) arg; - unsigned int century; - -/* - * CMOS byte 10 (clock status register A) has 3 bitfields: - * bit 7: 1 if data invalid, update in progress (read-only bit) - * (this is raised 224 us before the actual update starts) - * 6-4 select base frequency - * 010: 32768 Hz time base (default) - * 111: reset - * all other combinations are manufacturer-dependent - * (e.g.: DS1287: 010 = start oscillator, anything else = stop) - * 3-0 rate selection bits for interrupt - * 0000 none (may stop RTC) - * 0001, 0010 give same frequency as 1000, 1001 - * 0011 122 microseconds (minimum, 8192 Hz) - * .... each increase by 1 halves the frequency, doubles the period - * 1111 500 milliseconds (maximum, 2 Hz) - * 0110 976.562 microseconds (default 1024 Hz) - */ - - save_control = cmos_read (11); /* tell the clock it's being set */ - cmos_write (11, (save_control | 0x80)); - save_freq_select = cmos_read (10); /* stop and reset prescaler */ - cmos_write (10, (save_freq_select | 0x70)); - - tm.tm_year += TM_EPOCH; - century = tm.tm_year/100; - tm.tm_year -= cmos_epoch; - tm.tm_year %= 100; - tm.tm_mon += 1; - tm.tm_wday += 1; - - if (!(save_control & 0x02)) { /* 12hr mode; the default is 24hr mode */ - if (tm.tm_hour == 0) - tm.tm_hour = 24; - if (tm.tm_hour > 12) { - tm.tm_hour -= 12; - pmbit = 0x80; - } - } - - if (!(save_control & 0x04)) { /* BCD mode - the default */ - BIN_TO_BCD(tm.tm_sec); - BIN_TO_BCD(tm.tm_min); - BIN_TO_BCD(tm.tm_hour); - BIN_TO_BCD(tm.tm_wday); - BIN_TO_BCD(tm.tm_mday); - BIN_TO_BCD(tm.tm_mon); - BIN_TO_BCD(tm.tm_year); - BIN_TO_BCD(century); - } - - cmos_write (0, tm.tm_sec); - cmos_write (2, tm.tm_min); - cmos_write (4, tm.tm_hour | pmbit); - cmos_write (6, tm.tm_wday); - cmos_write (7, tm.tm_mday); - cmos_write (8, tm.tm_mon); - cmos_write (9, tm.tm_year); - if (century_byte) - cmos_write (century_byte, century); - - - /* The kernel sources, linux/arch/i386/kernel/time.c, have the - following comment: - - The following flags have to be released exactly in this order, - otherwise the DS12887 (popular MC146818A clone with integrated - battery and quartz) will not reset the oscillator and will not - update precisely 500 ms later. You won't find this mentioned - in the Dallas Semiconductor data sheets, but who believes data - sheets anyway ... -- Markus Kuhn - */ - - cmos_write (11, save_control); - cmos_write (10, save_freq_select); - return 0; -} - -static int -hclock_read(unsigned long reg) { - return atomic("clock read", cmos_read, (reg)); -} - -static void -hclock_set_time(const struct tm *tm) { - atomic("set time", cmos_set_time, (unsigned long)(tm)); -} - -static inline int -cmos_clock_busy(void) { - return -#ifdef __alpha__ - /* poll bit 4 (UF) of Control Register C */ - funkyTOY ? (hclock_read(12) & 0x10) : -#endif - /* poll bit 7 (UIP) of Control Register A */ - (hclock_read(10) & 0x80); -} - - -static int -synchronize_to_clock_tick_cmos(void) { - int i; - - /* Wait for rise. Should be within a second, but in case something - weird happens, we have a limit on this loop to reduce the impact - of this failure. - */ - for (i = 0; !cmos_clock_busy(); i++) - if (i >= 10000000) - return 1; - - /* Wait for fall. Should be within 2.228 ms. */ - for (i = 0; cmos_clock_busy(); i++) - if (i >= 1000000) - return 1; - return 0; -} - - - -static int -read_hardware_clock_cmos(struct tm *tm) { -/*---------------------------------------------------------------------------- - Read the hardware clock and return the current time via argument. - Assume we have an ISA machine and read the clock directly with CPU I/O - instructions. - - This function is not totally reliable. It takes a finite and - unpredictable amount of time to execute the code below. During that - time, the clock may change and we may even read an invalid value in - the middle of an update. We do a few checks to minimize this - possibility, but only the kernel can actually read the clock - properly, since it can execute code in a short and predictable - amount of time (by turning of interrupts). - - In practice, the chance of this function returning the wrong time is - extremely remote. - ------------------------------------------------------------------------------*/ - bool got_time = FALSE; - unsigned char status, pmbit; - - status = pmbit = 0; /* just for gcc */ - - while (!got_time) { - /* Bit 7 of Byte 10 of the Hardware Clock value is the Update In Progress - (UIP) bit, which is on while and 244 uS before the Hardware Clock - updates itself. It updates the counters individually, so reading - them during an update would produce garbage. The update takes 2mS, - so we could be spinning here that long waiting for this bit to turn - off. - - Furthermore, it is pathologically possible for us to be in this - code so long that even if the UIP bit is not on at first, the - clock has changed while we were running. We check for that too, - and if it happens, we start over. - */ - - if (!cmos_clock_busy()) { - /* No clock update in progress, go ahead and read */ - tm->tm_sec = hclock_read(0); - tm->tm_min = hclock_read(2); - tm->tm_hour = hclock_read(4); - tm->tm_wday = hclock_read(6); - tm->tm_mday = hclock_read(7); - tm->tm_mon = hclock_read(8); - tm->tm_year = hclock_read(9); - status = hclock_read(11); -#if 0 - if (century_byte) - century = hclock_read(century_byte); -#endif - - /* Unless the clock changed while we were reading, consider this - a good clock read . - */ - if (tm->tm_sec == hclock_read (0)) - got_time = TRUE; - } - /* Yes, in theory we could have been running for 60 seconds and - the above test wouldn't work! - */ - } - - if (!(status & 0x04)) { /* BCD mode - the default */ - BCD_TO_BIN(tm->tm_sec); - BCD_TO_BIN(tm->tm_min); - pmbit = (tm->tm_hour & 0x80); - tm->tm_hour &= 0x7f; - BCD_TO_BIN(tm->tm_hour); - BCD_TO_BIN(tm->tm_wday); - BCD_TO_BIN(tm->tm_mday); - BCD_TO_BIN(tm->tm_mon); - BCD_TO_BIN(tm->tm_year); -#if 0 - BCD_TO_BIN(century); -#endif - } - - /* We don't use the century byte of the Hardware Clock - since we don't know its address (usually 50 or 55). - Here, we follow the advice of the X/Open Base Working Group: - "if century is not specified, then values in the range [69-99] - refer to years in the twentieth century (1969 to 1999 inclusive), - and values in the range [00-68] refer to years in the twenty-first - century (2000 to 2068 inclusive)." - */ - - tm->tm_wday -= 1; - tm->tm_mon -= 1; - tm->tm_year += (cmos_epoch - TM_EPOCH); - if (tm->tm_year < 69) - tm->tm_year += 100; - if (pmbit) { - tm->tm_hour += 12; - if (tm->tm_hour == 24) - tm->tm_hour = 0; - } - - tm->tm_isdst = -1; /* don't know whether it's daylight */ - return 0; -} - - - -static int -set_hardware_clock_cmos(const struct tm *new_broken_time) { - - hclock_set_time(new_broken_time); - return 0; -} - -static int -i386_iopl(const int level) { -#if defined(__i386__) || defined(__alpha__) - extern int iopl(const int level); - return iopl(level); -#else - return -2; -#endif -} - -static int -get_permissions_cmos(void) { - int rc; - - if (use_dev_port) { - if ((dev_port_fd = open("/dev/port", O_RDWR)) < 0) { - int errsv = errno; - fprintf(stderr, _("Cannot open /dev/port: %s"), strerror(errsv)); - rc = 1; - } else - rc = 0; - } else { - rc = i386_iopl(3); - if (rc == -2) { - fprintf(stderr, _("I failed to get permission because I didnt try.\n")); - } else if (rc != 0) { - rc = errno; - fprintf(stderr, _("%s is unable to get I/O port access: " - "the iopl(3) call failed.\n"), progname); - if(rc == EPERM && geteuid()) - fprintf(stderr, _("Probably you need root privileges.\n")); - } - } - return rc ? 1 : 0; -} - -static struct clock_ops cmos = { - "direct I/O instructions to ISA clock", - get_permissions_cmos, - read_hardware_clock_cmos, - set_hardware_clock_cmos, - synchronize_to_clock_tick_cmos, -}; - - -/* return &cmos if cmos clock present, NULL otherwise */ -/* choose this construction to avoid gcc messages about unused variables */ - -struct clock_ops * -probe_for_cmos_clock(void){ - int have_cmos = -#if defined(__i386__) || defined(__alpha__) - TRUE; -#else - FALSE; -#endif - return have_cmos ? &cmos : NULL; -} diff --git a/clock/hwclock.8 b/clock/hwclock.8 deleted file mode 100644 index f34bfac00..000000000 --- a/clock/hwclock.8 +++ /dev/null @@ -1,596 +0,0 @@ -.TH HWCLOCK 8 "02 March 1998" -.SH NAME -hwclock \- query and set the hardware clock (RTC) -.SH SYNOPSIS -.BR "hwclock \-r" " or " "hwclock \-\-show" -.br -.BR "hwclock \-w" " or " "hwclock \-\-systohc" -.br -.BR "hwclock \-s" " or " "hwclock \-\-hctosys" -.br -.BR "hwclock \-a" " or " "hwclock \-\-adjust" -.br -.BR "hwclock \-v" " or " "hwclock \-\-version" -.br -.B "hwclock \-\-set \-\-date=newdate" -.br -.B "hwclock \-\-getepoch" -.br -.B "hwclock \-\-setepoch \-\-epoch=year" -.PP -other options: -.PP -.B "[\-u|\-\-utc] \-\-localtime \-\-directisa \-\-test \-\-debug" -.PP -and arcane options for DEC Alpha: -.PP -.B "[\-A|\-\-arc] [\-J|\-\-jensen] [\-S|\-\-srm] [\-F|\-\-funky-toy]" -.PP -Minimum unique abbreviations of all options are acceptable. -.PP -Also, equivalent options \-r, \-w, \-s, \-a, \-v, \-u, -\-D, \-A, \-J, \-S, and \-F are accepted for compatibility -with the program "clock", while \-h asks for a help message. - -.SH DESCRIPTION -.I hwclock -is a tool for accessing the Hardware Clock. You can display the -current time, set the Hardware Clock to a specified time, set the -Hardware Clock to the System Time, and set the System Time from the -Hardware Clock. -.PP -You can also run -.I hwclock -periodically to insert or remove time from the Hardware Clock to -compensate for systematic drift (where the clock consistently gains or -loses time at a certain rate if left to run). - -.SH OPTIONS -You need exactly one of the following options to tell -.I hwclock -what function to perform: -.PP -.TP -.B \-\-show -Read the Hardware Clock and print the time on Standard Output. -The time is always in local time, even if you keep your Hardware Clock -in Coordinated Universal Time. See the -.B \-\-utc -option. - -.TP -.B \-\-set -Set the Hardware Clock to the time given by the -.B \-\-date -option. -.TP -.B \-\-hctosys -Set the System Time from the Hardware Clock. - -Also set the kernel's timezone value to the local timezone -as indicated by the TZ environment variable and/or -.IR /usr/lib/zoneinfo , -as -.BR tzset (3) -would interpret them. -The obsolete tz_dsttime field of the kernel's timezone value is set -to DST_NONE. (For details on what this field used to mean, see -.BR settimeofday (2).) - -This is a good option to use in one of the system startup scripts. -.TP -.B \-\-systohc -Set the Hardware Clock to the current System Time. -.TP -.B \-\-adjust -Add or subtract time from the Hardware Clock to account for systematic -drift since the last time the clock was set or adjusted. See discussion -below. -.TP -.B \-\-getepoch -Print out standard output the kernel's Hardware Clock epoch value. -This is the number of years into AD to which a zero year value in the -Hardware Clock refers. For example, if you are using the convention -that the year counter in your Hardware Clock contains the number of -full years since 1952, then the kernel's Hardware Counter epoch value -must be 1952. - -This epoch value is used whenever hwclock reads or sets the Hardware Clock. -.TP -.B \-\-setepoch -Set the kernel's Hardware Clock epoch value to the value specified by the -.B \-\-epoch -option. See the -.B \-\-getepoch -option for details. -.TP -.B \-\-version -Print the version of -.I hwclock -on Standard Output. -.br -You need the following option if you specify -.B \-\-set -option. Otherwise, it is ignored. -.TP -.B \-\-date=date_string -Specifies the time to which to set the Hardware Clock. The value of this -option is an argument to the -.I date(1) -program. For example, -.sp -.I hwclock --set --date="9/22/96 16:45:05" -.sp -The argument is in local time, even if you keep your Hardware Clock in -Coordinated Universal time. See the -.I \-\-utc -option. - -.TP -.B \-\-epoch=year -Specifies the year which is the beginning of the Hardware Clock's -epoch. I.e. the number of years into AD to which a zero value in the -Hardware Clock's year counter refers. - -For example, -.sp -.I hwclock --setepoch --epoch=1952 - -.PP -The following options apply to most functions. -.TP -.B \-\-utc -.TP -.B \-\-localtime -Indicates that the Hardware Clock is kept in Coordinated Universal -Time or local time, respectively. It is your choice whether to keep -your clock in UTC or local time, but nothing in the clock tells which -you've chosen. So this option is how you give that information to -.IR hwclock . - -If you specify the wrong one of these options (or specify neither and -take a wrong default), both setting and querying of the Hardware Clock -will be messed up. - -If you specify neither -.B \-\-utc -nor -.B \-\-localtime -, the default is whichever was specified the last time -.I hwclock -was used to set the clock (i.e. hwclock was successfully run with the -.B \-\-set -, -.B \-\-systohc -, -or -.B \-\-adjust -options), as recorded in the adjtime file. If the adjtime file doesn't -exist, the default is local time. - -.TP -.B \-\-directisa -is meaningful only on an ISA machine or an Alpha (which implements enough -of ISA to be, roughly speaking, an ISA machine for -.IR hwclock 's -purposes). For other machines, it has no effect. This option tells -.I hwclock -to use explicit I/O instructions to access the Hardware Clock. -Without this option, -.I hwclock -will try to use the /dev/rtc device (which it assumes to be driven by the -rtc device driver). If it is unable to open the device (for read), it will -use the explicit I/O instructions anyway. - -The rtc device driver was new in Linux Release 2. -.TP -.B \-\-badyear -Indicates that the Hardware Clock is incapable of storing years outside -the range 1994-1999. There is a problem in some BIOSes (almost all -Award BIOSes made between 4/26/94 and 5/31/95) wherein they are unable -to deal with years after 1999. If one attempts to set the year-of-century -value to something less than 94 (or 95 in some cases), the value that -actually gets set is 94 (or 95). Thus, if you have one of these machines, -.I hwclock -cannot set the year after 1999 and cannot use the value of the clock as -the true time in the normal way. - -To compensate for this (without your getting a BIOS update, which would -definitely be preferable), always use -.B \-\-badyear -if you have one of these machines. When -.I hwclock -knows it's working with a brain-damaged clock, it ignores the year part of -the Hardware Clock value and instead tries to guess the year based on the -last calibrated date in the adjtime file, by assuming that that date is -within the past year. For this to work, you had better do a -.I hwclock \-\-set -or -.I hwclock \-\-systohc -at least once a year! - -Though -.I hwclock -ignores the year value when it reads the Hardware Clock, it sets the -year value when it sets the clock. It sets it to 1995, 1996, 1997, or -1998, whichever one has the same position in the leap year cycle as -the true year. That way, the Hardware Clock inserts leap days where -they belong. Again, if you let the Hardware Clock run for more than a -year without setting it, this scheme could be defeated and you could -end up losing a day. - -.I hwclock -warns you that you probably need -.B \-\-badyear -whenever it finds your Hardware Clock set to 1994 or 1995. - -.TP -.B \-\-srm -.TP -.B \-\-arc -.TP -.B \-\-jensen -.TP -.B \-\-funky\-toy -These options all tell -.I hwclock -what kind of Alpha machine you have. They -are invalid if you don't have an Alpha and shouldn't be necessary if you -do, because -.I hwclock -should be able to determine by itself what it's -running on, at least when -.I /proc -is mounted. These options make it possible for -.I hwclock -to work even when -its environment does not conform to its expectations and thus it cannot -accurately determine what sort of system it is running on. If you think -hwclock is incorrectly determining the system's characteristics, try -running with the -.B \-\-debug -option to see what conclusions the program is -reaching and how. If you find you need one of these options to make -.I hwclock -work, contact the -.I hwclock -maintainer to see if the program can be improved to detect your system -automatically. - -.B \-\-jensen -means you are running on a Jensen model. - -.B \-\-arc -means your machine uses epoch 1980 in its hardware clock, as is commonly -the case for machines on ARC console (but Ruffians have epoch 1900). - -.B \-\-srm -means your machine uses epoch 1900 in its hardware clock, as is commonly -the case for machines on SRM console. - -.B \-\-funky\-toy -means that on your machine, one has to use the UF bit instead -of the UIP bit in the Hardware Clock to detect a time transition. "Toy" -in the option name refers to the Time Of Year facility of the machine. - - -.TP -.B \-\-test -Do everything except actually updating the Hardware Clock or anything -else. This is useful, especially in conjunction with -.B \-\-debug, -in learning about -.I hwclock. -.TP -.B \-\-debug -Display a lot of information about what -.I hwclock -is doing internally. Some of its function is complex and this output -can help you understand how the program works. - - -.SH NOTES - - -.SH Clocks in a Linux System -.PP -There are two main clocks in a Linux system: -.PP -.B The Hardware Clock: -This is a clock that runs independently of any control program running -in the CPU and even when the machine is powered off. - -On an ISA system, this clock is specified as part of the ISA standard. -The control program can read or set this clock to a whole second, but -the control program can also detect the edges of the 1 second clock -ticks, so the clock actually has virtually infinite precision. -.PP -This clock is commonly called the hardware clock, the real time clock, -the RTC, the BIOS clock, and the CMOS clock. Hardware Clock, in its -capitalized form, was coined for use by -.I hwclock -because all of the other names are inappropriate to the point of being -misleading. -.PP -.B The System Time: -This is the time kept by a clock inside the Linux kernel and driven by -a timer interrupt. (On an ISA machine, the timer interrupt is part of -the ISA standard). It has meaning only while Linux is running on the -machine. The System Time is the number of seconds since 00:00:00 -January 1, 1970 UTC (or more succinctly, the number of seconds since -1969). The System Time is not an integer, though. It has virtually -infinite precision. -.PP -The System Time is the time that matters. The Hardware Clock's basic -purpose in a Linux system is to keep time when Linux is not running. You -initialize the System Time to the time from the Hardware Clock when Linux -starts up, and then never use the Hardware Clock again. Note that in DOS, -for which ISA was designed, the Hardware Clock is the only real time clock. -.PP -It is important that the System Time not have any discontinuities such as -would happen if you used the -.BR date (1L) -program to set it while the system is running. You can, however, do whatever -you want to the Hardware Clock while the system is running, and the next -time Linux starts up, it will do so with the adjusted time from the Hardware -Clock. You can also use the program -.BR adjtimex (8) -to smoothly adjust the System Time while the system runs. -.PP -A Linux kernel maintains a concept of a local timezone for the system. -But don't be misled -- almost nobody cares what timezone the kernel -thinks it is in. Instead, programs that care about the timezone -(perhaps because they want to display a local time for you) almost -always use a more traditional method of determining the timezone: They -use the TZ environment variable and/or the /usr/local/timezone -directory, as explained in the man page for tzset(3). However, some -programs and fringe parts of the Linux kernel such as filesystems use -the kernel timezone value. An example is the vfat filesystem. If the -kernel timezone value is wrong, the vfat filesystem will report and -set the wrong timestamps on files. -.PP -.I hwclock -sets the kernel timezone to the value indicated by TZ and/or -/usr/local/timezone when you set the System Time using the -.B \-\-hctosys -option. -.PP -The timezone value actually consists of two parts: 1) a field -tz_minuteswest indicating how many minutes local time (not adjusted -for DST) lags behind UTC, and 2) a field tz_dsttime indicating -the type of Daylight Savings Time (DST) convention that is in effect -in the locality at the present time. -This second field is not used under Linux and is always zero. -(See also -.BR settimeofday (2).) - -.SH How hwclock Accesses the Hardware Clock -.PP -.I hwclock -Uses many different ways to get and set Hardware Clock values. -The most normal way is to do I/O to the device special file /dev/rtc, -which is presumed to be driven by the rtc device driver. However, -this method is not always available. For one thing, the rtc driver is -a relatively recent addition to Linux. Older systems don't have it. -Also, though there are versions of the rtc driver that work on DEC -Alphas, there appear to be plenty of Alphas on which the rtc driver -does not work (a common symptom is hwclock hanging). -.PP -On older systems, the method of accessing the Hardware Clock depends on -the system hardware. -.PP -On an ISA system, -.I hwclock -can directly access the "CMOS memory" registers that -constitute the clock, by doing I/O to Ports 0x70 and 0x71. It does -this with actual I/O instructions and consequently can only do it if -running with superuser effective userid. (In the case of a Jensen -Alpha, there is no way for -.I hwclock -to execute those I/O instructions, and so it uses instead the -/dev/port device special file, which provides almost as low-level an -interface to the I/O subsystem). - -This is a really poor method of accessing the clock, for all the -reasons that user space programs are generally not supposed to do -direct I/O and disable interrupts. Hwclock provides it because it is -the only method available on ISA and Alpha systems which don't have -working rtc device drivers available. - -.PP -On an m68k system, -.I hwclock -can access the clock via the console driver, via the device special -file /dev/tty1. -.PP -.I hwclock -tries to use /dev/rtc. If it is compiled for a kernel that doesn't have -that function or it is unable to open /dev/rtc, -.I hwclock -will fall back to another method, if available. On an ISA or Alpha -machine, you can force -.I hwclock -to use the direct manipulation of the CMOS registers without even trying -.I /dev/rtc -by specifying the \-\-directisa option. - - -.SH The Adjust Function -.PP -The Hardware Clock is usually not very accurate. However, much of its -inaccuracy is completely predictable - it gains or loses the same amount -of time every day. This is called systematic drift. -.IR hwclock 's -"adjust" function lets you make systematic corrections to correct the -systematic drift. -.PP -It works like this: -.I hwclock -keeps a file, -.I /etc/adjtime, -that keeps some historical information. This is called the adjtime file. -.PP -Suppose you start with no adjtime file. You issue a -.I hwclock \-\-set -command to set the Hardware Clock to the true current time. -.I Hwclock -creates the adjtime file and records in it the current time as the -last time the clock was calibrated. -5 days -later, the clock has gained 10 seconds, so you issue another -.I hwclock \-\-set -command to set it back 10 seconds. -.I Hwclock -updates the adjtime file to show the current time as the last time the -clock was calibrated, and records 2 seconds per day as the systematic -drift rate. 24 hours go by, and then you issue a -.I hwclock \-\-adjust -command. -.I Hwclock -consults the adjtime file and sees that the clock gains 2 seconds per -day when left alone and that it has been left alone for exactly one -day. So it subtracts 2 seconds from the Hardware Clock. It then -records the current time as the last time the clock was adjusted. -Another 24 hours goes by and you issue another -.I hwclock \-\-adjust. -.I Hwclock -does the same thing: subtracts 2 seconds and updates the adjtime file -with the current time as the last time the clock was adjusted. -.PP -Every time you calibrate (set) the clock (using -.I \-\-set -or -.I \-\-systohc -), -.I hwclock -recalculates the systematic drift rate based on how long it has been -since the last calibration, how long it has been since the last -adjustment, what drift rate was assumed in any intervening -adjustments, and the amount by which the clock is presently off. -.PP -A small amount of error creeps in any time -.I hwclock -sets the clock, so it refrains from making an adjustment that would be -less than 1 second. Later on, when you request an adjustment again, -the accumulated drift will be more than a second and -.I hwclock -will do the adjustment then. -.PP -It is good to do a -.I hwclock \-\-adjust -just before the -.I hwclock \-\-hctosys -at system startup time, and maybe periodically while the system is -running via cron. -.PP -The adjtime file, while named for its historical purpose of controlling -adjustments only, actually contains other information for use by hwclock -in remembering information from one invocation to the next. -.PP -The format of the adjtime file is, in ASCII: -.PP -Line 1: 3 numbers, separated by blanks: 1) systematic drift rate in -seconds per day, floating point decimal; 2) Resulting number of -seconds since 1969 UTC of most recent adjustment or calibration, -decimal integer; 3) zero (for compatibility with -.IR clock ) -as a decimal integer. -.PP -Line 2: 1 number: Resulting number of seconds since 1969 UTC of most -recent calibration. Zero if there has been no calibration yet or it -is known that any previous calibration is moot (for example, because -the Hardware Clock has been found, since that calibration, not to -contain a valid time). This is a decimal integer. -.PP -Line 3: "UTC" or "LOCAL". Tells whether the Hardware Clock is set to -Coordinated Universal Time or local time. You can always override this -value with options on the -.I hwclock -command line. -.PP -You can use an adjtime file that was previously used with the -.I clock -program with -.I hwclock. - - -.SH "Automatic Hardware Clock Synchronization By the Kernel" - -You should be aware of another way that the Hardware Clock is kept -synchronized in some systems. The Linux kernel has a mode wherein it -copies the System Time to the Hardware Clock every 11 minutes. -This is a good mode to use when you are using something sophisticated -like ntp to keep your System Time synchronized. (ntp is a way to keep -your System Time synchronized either to a time server somewhere on the -network or to a radio clock hooked up to your system. See RFC 1305). - -This mode (we'll call it "11 minute mode") is off until something -turns it on. The ntp daemon xntpd is one thing that turns it on. You -can turn it off by running anything, including -.IR "hwclock \-\-hctosys" , -that sets the System Time the old fashioned way. - -To see if it is on or -off, use the command -.I adjtimex \-\-print -and look at the value of "status". If the "64" bit of this number -(expressed in binary) equal to 0, 11 minute mode is on. Otherwise, it -is off. - -If your system runs with 11 minute mode on, don't use -.I hwclock \-\-adjust -or -.IR "hwclock \-\-hctosys" . -You'll just make a mess. It is acceptable to use a -.I hwclock \-\-hctosys -at startup time to get a reasonable System Time until your system is -able to set the System Time from the external source and start 11 -minute mode. - - -.SH ISA Hardware Clock Century value - -There is some sort of standard that defines CMOS memory Byte 50 on an ISA -machine as an indicator of what century it is. -.I hwclock -does not use or set that byte because there are some machines that -don't define the byte that way, and it really isn't necessary anyway, -since the year-of-century does a good job of implying which century it -is. - -If you have a bona fide use for a CMOS century byte, contact the -.I hwclock -maintainer; an option may be appropriate. - -Note that this section is only relevant when you are using the "direct -ISA" method of accessing the Hardware Clock. - - - -.SH "ENVIRONMENT VARIABLES" -.I TZ - -.SH FILES -.I /etc/adjtime -.I /usr/lib/zoneinfo/ -.I /dev/rtc -.I /dev/port -.I /dev/tty1 -.I /proc/cpuinfo - -.SH "SEE ALSO" -.BR adjtimex (8), -.BR date (1), -.BR gettimeofday (2), -.BR settimeofday (2), -.BR crontab (1), -.BR tzset (3) - -.SH AUTHORS -Written By Bryan Henderson, September 1996 (bryanh@giraffe-data.com), -based on work done on the -.I clock -program by Charles Hedrick, Rob Hooft, and Harald Koenig. -See the source code for complete history and credits. - - diff --git a/clock/hwclock.c b/clock/hwclock.c deleted file mode 100644 index d45516b4b..000000000 --- a/clock/hwclock.c +++ /dev/null @@ -1,1431 +0,0 @@ -/* - * hwclock.c - * - * clock.c was written by Charles Hedrick, hedrick@cs.rutgers.edu, Apr 1992 - * Modified for clock adjustments - Rob Hooft , Nov 1992 - * Improvements by Harald Koenig - * and Alan Modra . - * - * Major rewrite by Bryan Henderson , 96.09.19. - * The new program is called hwclock. New features: - * - You can set the hardware clock without also modifying the system clock. - * - You can read and set the clock with finer than 1 second precision. - * - When you set the clock, hwclock automatically refigures the drift - * rate, based on how far off the clock was before you set it. - * - * Reshuffled things, added sparc code, and re-added alpha stuff - * by David Mosberger - * and Jay Estabrook - * and Martin Ostermann , aeb@cwi.nl, 990212. - * - * Fix for Award 2094 bug, Dave Coffin (dcoffin@shore.net) 11/12/98 - * Change of local time handling, Stefan Ring - */ - -/* - * clock [-u] -r - read hardware clock - * clock [-u] -w - write hardware clock from system time - * clock [-u] -s - set system time from hardware clock - * clock [-u] -a - set system time from hardware clock, adjust the time - * to correct for systematic error, and write it back to - * the hardware clock - * -u indicates cmos clock is kept in universal time - * -A indicates cmos clock is kept in Alpha ARC console time (0 == 1980) - * -J indicates we're dealing with a Jensen (early DEC Alpha PC) - */ - -/* - * Explanation of `adjusting' (Rob Hooft): - * - * The problem with my machine is that its CMOS clock is 10 seconds - * per day slow. With this version of clock.c, and my '/etc/rc.local' - * reading '/etc/clock -au' instead of '/etc/clock -u -s', this error - * is automatically corrected at every boot. - * - * To do this job, the program reads and writes the file '/etc/adjtime' - * to determine the correction, and to save its data. In this file are - * three numbers: - * - * 1) the correction in seconds per day. (So if your clock runs 5 - * seconds per day fast, the first number should read -5.0) - * 2) the number of seconds since 1/1/1970 the last time the program - * was used - * 3) the remaining part of a second which was leftover after the last - * adjustment - * - * Installation and use of this program: - * - * a) create a file '/etc/adjtime' containing as the first and only line: - * '0.0 0 0.0' - * b) run 'clock -au' or 'clock -a', depending on whether your cmos is in - * universal or local time. This updates the second number. - * c) set your system time using the 'date' command. - * d) update your cmos time using 'clock -wu' or 'clock -w' - * e) replace the first number in /etc/adjtime by your correction. - * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local' - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "clock.h" -#include "nls.h" - -#define MYNAME "hwclock" -#define VERSION "2.4c" - -char *progname = MYNAME; - -/* The struct that holds our hardware access routines */ -struct clock_ops *ur; - -#define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1)); - -/* Here the information for time adjustments is kept. */ -#define ADJPATH "/etc/adjtime" - -/* Store the date here when "badyear" flag is set. */ -#define LASTDATE "/var/lib/lastdate" - -struct adjtime { - /* This is information we keep in the adjtime file that tells us how - to do drift corrections. Elements are all straight from the - adjtime file, so see documentation of that file for details. - Exception is , which is an indication that what's in this - structure is not what's in the disk file (because it has been - updated since read from the disk file). - */ - bool dirty; - /* line 1 */ - float drift_factor; - time_t last_adj_time; - float not_adjusted; - /* line 2 */ - time_t last_calib_time; - /* The most recent time that we set the clock from an external - authority (as opposed to just doing a drift adjustment) */ - /* line 3 */ - enum a_local_utc {LOCAL, UTC, UNKNOWN} local_utc; - /* To which time zone, local or UTC, we most recently set the - hardware clock. */ -}; - -bool debug; - /* We are running in debug mode, wherein we put a lot of information about - what we're doing to standard output. */ - -bool badyear; - /* Workaround for Award 4.50g BIOS bug: keep the year in a file. */ - -int epoch_option = -1; - /* User-specified epoch, used when rtc fails to return epoch. */ - -/* - * Almost all Award BIOS's made between 04/26/94 and 05/31/95 - * have a nasty bug limiting the RTC year byte to the range 94-99. - * Any year between 2000 and 2093 gets changed to 2094, every time - * you start the system. - * With the --badyear option, we write the date to file and hope - * that the file is updated at least once a year. - * I recommend putting this command "hwclock --badyear" in the monthly - * crontab, just to be safe. -- Dave Coffin 11/12/98 - */ -static void -write_date_to_file (struct tm *tm) { - FILE *fp; - - if ((fp = fopen(LASTDATE,"w"))) { - fprintf(fp,"%02d.%02d.%04d\n", tm->tm_mday, tm->tm_mon+1, - tm->tm_year+1900); - fclose(fp); - } else - perror(LASTDATE); -} - -static void -read_date_from_file (struct tm *tm) { - int last_mday, last_mon, last_year; - FILE *fp; - - if ((fp = fopen(LASTDATE,"r"))) { - if (fscanf (fp,"%d.%d.%d\n", &last_mday, &last_mon, &last_year) == 3) { - tm->tm_year = last_year-1900; - if ((tm->tm_mon << 5) + tm->tm_mday < ((last_mon-1) << 5) + last_mday) - tm->tm_year ++; - } - fclose(fp); - } - write_date_to_file (tm); -} - -static float -time_diff(struct timeval subtrahend, struct timeval subtractor) { -/*--------------------------------------------------------------------------- - The difference in seconds between two times in "timeval" format. -----------------------------------------------------------------------------*/ - return( (subtrahend.tv_sec - subtractor.tv_sec) - + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6 ); -} - - -static struct timeval -time_inc(struct timeval addend, float increment) { -/*---------------------------------------------------------------------------- - The time, in "timeval" format, which is seconds after - the time . Of course, may be negative. ------------------------------------------------------------------------------*/ - struct timeval newtime; - - newtime.tv_sec = addend.tv_sec + (int) increment; - newtime.tv_usec = addend.tv_usec + (increment - (int) increment) * 1E6; - - /* Now adjust it so that the microsecond value is between 0 and 1 million */ - if (newtime.tv_usec < 0) { - newtime.tv_usec += 1E6; - newtime.tv_sec -= 1; - } else if (newtime.tv_usec >= 1E6) { - newtime.tv_usec -= 1E6; - newtime.tv_sec += 1; - } - return(newtime); -} - - -static bool -hw_clock_is_utc(const bool utc, const bool local_opt, - const struct adjtime adjtime) { - bool ret; - - if (utc) - ret = TRUE; /* --utc explicitly given on command line */ - else if (local_opt) - ret = FALSE; /* --localtime explicitly given */ - else - /* get info from adjtime file - default is local */ - ret = (adjtime.local_utc == UTC); - if (debug) - printf(_("Assuming hardware clock is kept in %s time.\n"), - ret ? _("UTC") : _("local")); - return ret; -} - - - -static void -read_adjtime(struct adjtime *adjtime_p, int *rc_p) { -/*---------------------------------------------------------------------------- - Read the adjustment parameters out of the /etc/adjtime file. - - Return them as the adjtime structure <*adjtime_p>. - - If there is no /etc/adjtime file, return defaults. - If values are missing from the file, return defaults for them. - - return *rc_p = 0 if all OK, !=0 otherwise. - ------------------------------------------------------------------------------*/ - FILE *adjfile; - int rc; /* local return code */ - struct stat statbuf; /* We don't even use the contents of this. */ - - rc = stat(ADJPATH, &statbuf); - if (rc < 0 && errno == ENOENT) { - /* He doesn't have a adjtime file, so we'll use defaults. */ - adjtime_p->drift_factor = 0; - adjtime_p->last_adj_time = 0; - adjtime_p->not_adjusted = 0; - adjtime_p->last_calib_time = 0; - adjtime_p->local_utc = UNKNOWN; - - *rc_p = 0; - } else { - adjfile = fopen(ADJPATH, "r"); /* open file for reading */ - if (adjfile == NULL) { - outsyserr("cannot open file " ADJPATH); - *rc_p = 2; - } else { - char line1[81]; /* String: first line of adjtime file */ - char line2[81]; /* String: second line of adjtime file */ - char line3[81]; /* String: third line of adjtime file */ - - line1[0] = '\0'; /* In case fgets fails */ - fgets(line1, sizeof(line1), adjfile); - line2[0] = '\0'; /* In case fgets fails */ - fgets(line2, sizeof(line2), adjfile); - line3[0] = '\0'; /* In case fgets fails */ - fgets(line3, sizeof(line3), adjfile); - - fclose(adjfile); - - /* Set defaults in case values are missing from file */ - adjtime_p->drift_factor = 0; - adjtime_p->last_adj_time = 0; - adjtime_p->not_adjusted = 0; - adjtime_p->last_calib_time = 0; - - sscanf(line1, "%f %d %f", - &adjtime_p->drift_factor, - (int *) &adjtime_p->last_adj_time, - &adjtime_p->not_adjusted); - - sscanf(line2, "%d", (int *) &adjtime_p->last_calib_time); - - if (!strcmp(line3, "UTC\n")) - adjtime_p->local_utc = UTC; - else if (!strcmp(line3, "LOCAL\n")) - adjtime_p->local_utc = LOCAL; - else { - adjtime_p->local_utc = UNKNOWN; - if (line3[0]) { - fprintf(stderr, _("%s: Warning: unrecognized third line in adjtime file\n"), - MYNAME); - fprintf(stderr, _("(Expected: `UTC' or `LOCAL' or nothing.)\n")); - } - } - - *rc_p = 0; - } - adjtime_p->dirty = FALSE; - - if (debug) { - printf(_("Last drift adjustment done at %d seconds after 1969\n"), - (int) adjtime_p->last_adj_time); - printf(_("Last calibration done at %d seconds after 1969\n"), - (int) adjtime_p->last_calib_time); - printf(_("Hardware clock is on %s time\n"), - (adjtime_p->local_utc == LOCAL) ? _("local") : - (adjtime_p->local_utc == UTC) ? _("UTC") : _("unknown")); - } - } -} - - -static void -synchronize_to_clock_tick(int *retcode_p) { -/*----------------------------------------------------------------------------- - Wait until the falling edge of the Hardware Clock's update flag so - that any time that is read from the clock immediately after we - return will be exact. - - The clock only has 1 second precision, so it gives the exact time only - once per second, right on the falling edge of the update flag. - - We wait (up to one second) either blocked waiting for an rtc device - or in a CPU spin loop. The former is probably not very accurate. - - Return *retcode_p == 0 if it worked, nonzero if it didn't. - ------------------------------------------------------------------------------*/ - if (debug) printf(_("Waiting for clock tick...\n")); - - *retcode_p = ur->synchronize_to_clock_tick(); - - if (debug) printf(_("...got clock tick\n")); -} - - - -static void -mktime_tz(struct tm tm, const bool universal, - bool *valid_p, time_t *systime_p) { -/*----------------------------------------------------------------------------- - Convert a time in broken down format (hours, minutes, etc.) into standard - unix time (seconds into epoch). Return it as *systime_p. - - The broken down time is argument . This broken down time is either in - local time zone or UTC, depending on value of logical argument "universal". - True means it is in UTC. - - If the argument contains values that do not constitute a valid time, - and mktime() recognizes this, return *valid_p == false and - *systime_p undefined. However, mktime() sometimes goes ahead and - computes a fictional time "as if" the input values were valid, - e.g. if they indicate the 31st day of April, mktime() may compute - the time of May 1. In such a case, we return the same fictional - value mktime() does as *systime_p and return *valid_p == true. - ------------------------------------------------------------------------------*/ - time_t mktime_result; /* The value returned by our mktime() call */ - char *zone; /* Local time zone name */ - - /* We use the C library function mktime(), but since it only works on - local time zone input, we may have to fake it out by temporarily - changing the local time zone to UTC. - */ - zone = (char *) getenv("TZ"); /* remember original time zone */ - if (universal) { - /* Set timezone to UTC */ - setenv("TZ", "", TRUE); - /* Note: tzset() gets called implicitly by the time code, but only the - first time. When changing the environment variable, better call - tzset() explicitly. - */ - tzset(); - } - mktime_result = mktime(&tm); - if (mktime_result == -1) { - /* This apparently (not specified in mktime() documentation) means - the 'tm' structure does not contain valid values (however, not - containing valid values does _not_ imply mktime() returns -1). - */ - *valid_p = FALSE; - *systime_p = 0; - if (debug) - printf(_("Invalid values in hardware clock: " - "%4d/%.2d/%.2d %.2d:%.2d:%.2d\n"), - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - } else { - *valid_p = TRUE; - *systime_p = mktime_result; - if (debug) - printf(_("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = " - "%ld seconds since 1969\n"), - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, (long) *systime_p); - } - /* now put back the original zone. */ - if (zone) setenv("TZ", zone, TRUE); - else unsetenv("TZ"); - tzset(); -} - - -static void -read_hardware_clock(const bool universal, bool *valid_p, time_t *systime_p){ -/*---------------------------------------------------------------------------- - Read the hardware clock and return the current time via argument. - - Use the method indicated by argument to access the hardware clock. ------------------------------------------------------------------------------*/ - struct tm tm; - int err; - - err = ur->read_hardware_clock(&tm); - - if (badyear) - read_date_from_file(&tm); - - if (debug) - printf (_("Time read from Hardware Clock: %4d/%.2d/%.2d %02d:%02d:%02d\n"), - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - mktime_tz(tm, universal, valid_p, systime_p); -} - - -static void -set_hardware_clock(const time_t newtime, - const bool universal, - const bool testing) { -/*---------------------------------------------------------------------------- - Set the Hardware Clock to the time , in local time zone or UTC, - according to . -----------------------------------------------------------------------------*/ - int err; - struct tm new_broken_time; - /* Time to which we will set Hardware Clock, in broken down format, in - the time zone of caller's choice - */ - - if (universal) - new_broken_time = *gmtime(&newtime); - else - new_broken_time = *localtime(&newtime); - - if (debug) - printf(_("Setting Hardware Clock to %.2d:%.2d:%.2d " - "= %d seconds since 1969\n"), - new_broken_time.tm_hour, new_broken_time.tm_min, - new_broken_time.tm_sec, (int) newtime); - - if (testing) - printf(_("Clock not changed - testing only.\n")); - else { - if (badyear) { - /* - * Write the real year to a file, then write a fake year - * between 1995 and 1998 to the RTC. This way, Award BIOS boots - * on 29 Feb 2000 thinking that it's 29 Feb 1996. - */ - write_date_to_file (&new_broken_time); - new_broken_time.tm_year = 95 + ((new_broken_time.tm_year+1) & 3); - } - err = ur->set_hardware_clock(&new_broken_time); - } -} - - - -static void -set_hardware_clock_exact(const time_t settime, - const struct timeval ref_time, - const bool universal, - const bool testing) { -/*---------------------------------------------------------------------------- - Set the Hardware Clock to the time "settime", in local time zone or UTC, - according to "universal". - - But correct "settime" and wait for a fraction of a second so that - "settime" is the value of the Hardware Clock as of system time - "ref_time", which is in the past. For example, if "settime" is - 14:03:05 and "ref_time" is 12:10:04.5 and the current system - time is 12:10:06.0: Wait .5 seconds (to make exactly 2 seconds since - "ref_time") and then set the Hardware Clock to 14:03:07, thus - getting a precise and retroactive setting of the clock. - - (Don't be confused by the fact that the system clock and the Hardware - Clock differ by two hours in the above example. That's just to remind - you that there are two independent time scales here). - - This function ought to be able to accept set times as fractional times. - Idea for future enhancement. - ------------------------------------------------------------------------------*/ - time_t newtime; /* Time to which we will set Hardware Clock */ - struct timeval now_time; /* locally used time */ - - gettimeofday(&now_time, NULL); - newtime = settime + (int) time_diff(now_time, ref_time) + 1; - if (debug) - printf(_("Time elapsed since reference time has been %.6f seconds.\n" - "Delaying further to reach the next full second.\n"), - time_diff(now_time, ref_time)); - - /* Now delay some more until Hardware Clock time newtime arrives */ - do gettimeofday(&now_time, NULL); - while (time_diff(now_time, ref_time) < newtime - settime); - - set_hardware_clock(newtime, universal, testing); -} - - - -static void -display_time(const bool hclock_valid, const time_t systime, - const float sync_duration) { -/*---------------------------------------------------------------------------- - Put the time "systime" on standard output in display format. - Except if hclock_valid == false, just tell standard output that we don't - know what time it is. - - Include in the output the adjustment "sync_duration". ------------------------------------------------------------------------------*/ - if (!hclock_valid) - fprintf(stderr, _("The Hardware Clock registers contain values that are " - "either invalid (e.g. 50th day of month) or beyond the range " - "we can handle (e.g. Year 2095).\n")); - else { - char *ctime_now; /* Address of static storage containing time string */ - - /* For some strange reason, ctime() is designed to include a newline - character at the end. We have to remove that. - */ - ctime_now = ctime(&systime); /* Compute display value for time */ - *(ctime_now+strlen(ctime_now)-1) = '\0'; /* Cut off trailing newline */ - - printf(_("%s %.6f seconds\n"), ctime_now, -(sync_duration)); - } -} - - - -static int -interpret_date_string(const char *date_opt, time_t * const time_p) { -/*---------------------------------------------------------------------------- - Interpret the value of the --date option, which is something like - "13:05:01". In fact, it can be any of the myriad ASCII strings that specify - a time which the "date" program can understand. The date option value in - question is our "dateopt" argument. - - The specified time is in the local time zone. - - Our output, "*time_p", is a seconds-into-epoch time. - - We use the "date" program to interpret the date string. "date" must be - runnable by issuing the command "date" to the /bin/sh shell. That means - in must be in the current PATH. - - If anything goes wrong (and many things can), we return return code - 10 and arbitrary *time_p. Otherwise, return code is 0 and *time_p - is valid. -----------------------------------------------------------------------------*/ - FILE *date_child_fp; - char date_resp[100]; - const char magic[]="seconds-into-epoch="; - char date_command[100]; - int retcode; /* our eventual return code */ - int rc; /* local return code */ - - if (date_opt == NULL) { - fprintf(stderr, _("No --date option specified.\n")); - retcode = 14; - } else if (strchr(date_opt, '"') != NULL) { - /* Quotation marks in date_opt would ruin the date command we construct. - */ - fprintf(stderr, _("The value of the --date option is not a valid date.\n" - "In particular, it contains quotation marks.\n")); - retcode = 12; - } else { - sprintf(date_command, "date --date=\"%s\" +seconds-into-epoch=%%s", - date_opt); - if (debug) printf(_("Issuing date command: %s\n"), date_command); - - date_child_fp = popen(date_command, "r"); - if (date_child_fp == NULL) { - outsyserr(_("Unable to run 'date' program in /bin/sh shell. " - "popen() failed")); - retcode = 10; - } else { - date_resp[0] = '\0'; /* in case fgets fails */ - fgets(date_resp, sizeof(date_resp), date_child_fp); - if (debug) printf(_("response from date command = %s\n"), date_resp); - if (strncmp(date_resp, magic, sizeof(magic)-1) != 0) { - fprintf(stderr, _("The date command issued by %s returned " - "unexpected results.\n" - "The command was:\n %s\nThe response was:\n %s\n"), - MYNAME, date_command, date_resp); - retcode = 8; - } else { - int seconds_since_epoch; - rc = sscanf(date_resp + sizeof(magic)-1, "%d", &seconds_since_epoch); - if (rc < 1) { - fprintf(stderr, _("The date command issued by %s returned " - "something other than an integer where the converted " - "time value was expected.\n" - "The command was:\n %s\nThe response was:\n %s\n"), - MYNAME, date_command, date_resp); - retcode = 6; - } else { - retcode = 0; - *time_p = seconds_since_epoch; - if (debug) - printf(_("date string %s equates to %d seconds since 1969.\n"), - date_opt, (int) *time_p); - } - } - fclose(date_child_fp); - } - } - return(retcode); -} - - - -static int -set_system_clock(const bool hclock_valid, const time_t newtime, - const bool testing) { -/*---------------------------------------------------------------------------- - Set the System Clock to time 'newtime'. - - Also set the kernel time zone value to the value indicated by the - TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as - tzset() would interpret them. - - EXCEPT: if hclock_valid is false, just issue an error message - saying there is no valid time in the Hardware Clock to which to set - the system time. - - If 'testing' is true, don't actually update anything -- just say we - would have. ------------------------------------------------------------------------------*/ - int retcode; - - if (!hclock_valid) { - fprintf(stderr,_("The Hardware Clock does not contain a valid time, so " - "we cannot set the System Time from it.\n")); - retcode = 1; - } else { - struct timeval tv; - struct tm *broken; - int minuteswest; - int rc; - - tv.tv_sec = newtime; - tv.tv_usec = 0; - - broken = localtime(&newtime); -#ifdef HAVE_tm_gmtoff - minuteswest = -broken->tm_gmtoff/60; /* GNU extension */ -#else - minuteswest = timezone/60; - if (broken->tm_isdst) - minuteswest -= 60; -#endif - - if (debug) { - printf( _("Calling settimeofday:\n") ); - printf( _("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"), - (long) tv.tv_sec, (long) tv.tv_usec ); - printf( _("\ttz.tz_minuteswest = %d\n"), minuteswest); - } - if (testing) { - printf(_("Not setting system clock because running in test mode.\n")); - retcode = 0; - } else { - const struct timezone tz = { minuteswest, 0 }; - - rc = settimeofday(&tv, &tz); - if (rc != 0) { - if (errno == EPERM) - fprintf(stderr, _("Must be superuser to set system clock.\n")); - else - outsyserr(_("settimeofday() failed")); - retcode = 1; - } else retcode = 0; - } - } - return(retcode); -} - - -static void -adjust_drift_factor(struct adjtime *adjtime_p, - const time_t nowtime, - const bool hclock_valid, const time_t hclocktime ) { -/*--------------------------------------------------------------------------- - Update the drift factor in <*adjtime_p> to reflect the fact that the - Hardware Clock was calibrated to and before that was set - to . - - We assume that the user has been doing regular drift adjustments - using the drift factor in the adjtime file, so if and - are different, that means the adjustment factor isn't - quite right. - - We record in the adjtime file the time at which we last calibrated - the clock so we can compute the drift rate each time we calibrate. - - EXCEPT: if is false, assume Hardware Clock was not set - before to anything meaningful and regular adjustments have not been - done, so don't adjust the drift factor. - -----------------------------------------------------------------------------*/ - if (!hclock_valid) { - if (debug) - printf(_("Not adjusting drift factor because the Hardware Clock " - "previously contained garbage.\n")); - } else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) { - if (debug) - printf(_("Not adjusting drift factor because it has been less than a " - "day since the last calibration.\n")); - } else { - const float factor_adjust = - ((float) (nowtime - hclocktime) - / (hclocktime - adjtime_p->last_calib_time)) - * 24 * 60 * 60; - - if (debug) - printf(_("Clock drifted %d seconds in the past %d seconds " - "in spite of a drift factor of %f seconds/day.\n" - "Adjusting drift factor by %f seconds/day\n"), - (int) (nowtime - hclocktime), - (int) (hclocktime - adjtime_p->last_calib_time), - adjtime_p->drift_factor, - factor_adjust ); - - adjtime_p->drift_factor += factor_adjust; - } - adjtime_p->last_calib_time = nowtime; - - adjtime_p->last_adj_time = nowtime; - - adjtime_p->not_adjusted = 0; - - adjtime_p->dirty = TRUE; -} - - - -static void -calculate_adjustment( - const float factor, - const time_t last_time, - const float not_adjusted, - const time_t systime, - int *adjustment_p, - float *retro_p, - const int debug ) { -/*---------------------------------------------------------------------------- - Do the drift adjustment calculation. - - The way we have to set the clock, we need the adjustment in two parts: - - 1) an integer number of seconds (return as *adjustment_p) - - 2) a positive fraction of a second (less than 1) (return as *retro_p) - - The sum of these two values is the adjustment needed. Positive means to - advance the clock or insert seconds. Negative means to retard the clock - or remove seconds. -----------------------------------------------------------------------------*/ - float exact_adjustment; - - exact_adjustment = ((float) (systime - last_time)) * factor / (24 * 60 * 60) - + not_adjusted; - *adjustment_p = FLOOR(exact_adjustment); - - *retro_p = exact_adjustment - (float) *adjustment_p; - if (debug) { - printf (_("Time since last adjustment is %d seconds\n"), - (int) (systime - last_time)); - printf (_("Need to insert %d seconds and refer time back " - "%.6f seconds ago\n"), - *adjustment_p, *retro_p); - } -} - - - -static void -save_adjtime(const struct adjtime adjtime, const bool testing) { -/*----------------------------------------------------------------------------- - Write the contents of the structure to its disk file. - - But if the contents are clean (unchanged since read from disk), don't - bother. ------------------------------------------------------------------------------*/ - char newfile[412]; /* Stuff to write to disk file */ - - if (adjtime.dirty) { - /* snprintf is not always available, but this is safe - as long as libc does not use more than 100 positions for %ld or %f */ - sprintf(newfile, "%f %ld %f\n%ld\n%s\n", - adjtime.drift_factor, - (long) adjtime.last_adj_time, - adjtime.not_adjusted, - (long) adjtime.last_calib_time, - (adjtime.local_utc == UTC) ? "UTC" : "LOCAL"); - - if (testing) { - printf(_("Not updating adjtime file because of testing mode.\n")); - printf(_("Would have written the following to %s:\n%s"), - ADJPATH, newfile); - } else { - FILE *adjfile; - int err = 0; - - adjfile = fopen(ADJPATH, "w"); - if (adjfile == NULL) { - outsyserr("Could not open file with the clock adjustment parameters " - "in it (" ADJPATH ") for writing"); - err = 1; - } else { - if (fprintf(adjfile, newfile) < 0) { - outsyserr("Could not update file with the clock adjustment " - "parameters (" ADJPATH ") in it"); - err = 1; - } - if (fclose(adjfile) < 0) { - outsyserr("Could not update file with the clock adjustment " - "parameters (" ADJPATH ") in it"); - err = 1; - } - } - if (err) - fprintf(stderr, _("Drift adjustment parameters not updated.\n")); - } - } -} - - - -static void -do_adjustment(struct adjtime *adjtime_p, - const bool hclock_valid, const time_t hclocktime, - const struct timeval read_time, - const bool universal, const bool testing) { -/*--------------------------------------------------------------------------- - Do the adjustment requested, by 1) setting the Hardware Clock (if - necessary), and 2) updating the last-adjusted time in the adjtime - structure. - - Do not update anything if the Hardware Clock does not currently present - a valid time. - - arguments and are current values from the adjtime - file. - - means the Hardware Clock contains a valid time, and that - time is . - - is the current system time (to be precise, it is the system - time at the time was read, which due to computational delay - could be a short time ago). - - : the Hardware Clock is kept in UTC. - - : We are running in test mode (no updating of clock). - - We do not bother to update the clock if the adjustment would be less than - one second. This is to avoid cumulative error and needless CPU hogging - (remember we use an infinite loop for some timing) if the user runs us - frequently. - -----------------------------------------------------------------------------*/ - if (!hclock_valid) { - fprintf(stderr, _("The Hardware Clock does not contain a valid time, " - "so we cannot adjust it.\n")); - } else { - int adjustment; - /* Number of seconds we must insert in the Hardware Clock */ - float retro; - /* Fraction of second we have to remove from clock after inserting - whole seconds. - */ - calculate_adjustment(adjtime_p->drift_factor, - adjtime_p->last_adj_time, - adjtime_p->not_adjusted, - hclocktime, - &adjustment, &retro, - debug ); - if (adjustment > 0 || adjustment < -1) { - set_hardware_clock_exact(hclocktime + adjustment, - time_inc(read_time, -retro), - universal, testing); - adjtime_p->last_adj_time = hclocktime + adjustment; - adjtime_p->not_adjusted = 0; - adjtime_p->dirty = TRUE; - } else - if (debug) - printf(_("Needed adjustment is less than one second, " - "so not setting clock.\n")); - } -} - - - -static void -determine_clock_access_method(const bool user_requests_ISA) { - - ur = NULL; - - if (user_requests_ISA) - ur = probe_for_cmos_clock(); - - if (!ur) - ur = probe_for_rtc_clock(); - - if (!ur) - ur = probe_for_kd_clock(); - - if (!ur && !user_requests_ISA) - ur = probe_for_cmos_clock(); - - if (debug) { - if (ur) - printf(_("Using %s.\n"), ur->interface_name); - else - printf(_("No usable clock interface found.\n")); - } -} - -static void -manipulate_clock(const bool show, const bool adjust, - const bool set, const time_t set_time, - const bool hctosys, const bool systohc, - const struct timeval startup_time, - const bool utc, const bool local_opt, - const bool testing, int *retcode_p) { -/*--------------------------------------------------------------------------- - Do all the normal work of hwclock - read, set clock, etc. - - Issue output to stdout and error message to stderr where appropriate. - - Return rc == 0 if everything went OK, rc != 0 if not. -----------------------------------------------------------------------------*/ - struct adjtime adjtime; - /* Contents of the adjtime file, or what they should be. */ - int rc; /* local return code */ - bool no_auth; /* User lacks necessary authorization to access the clock */ - - no_auth = ur->get_permissions(); - - if (no_auth) *retcode_p = 1; - else { - if (adjust || set || systohc || (!utc && !local_opt)) - read_adjtime(&adjtime, &rc); - else { - /* A little trick to avoid reading the file if we don't have to */ - adjtime.dirty = FALSE; - rc = 0; - } - if (rc != 0) *retcode_p = 2; - else { - const bool universal = hw_clock_is_utc(utc, local_opt, adjtime); - - if ((set || systohc || adjust) && - (adjtime.local_utc == UTC) != universal) { - adjtime.local_utc = universal ? UTC : LOCAL; - adjtime.dirty = TRUE; - } - - synchronize_to_clock_tick(retcode_p); - /* this takes up to 1 second */ - if (*retcode_p == 0) { - struct timeval read_time; - /* The time at which we read the Hardware Clock */ - - bool hclock_valid; - /* The Hardware Clock gives us a valid time, or at least something - close enough to fool mktime(). - */ - - time_t hclocktime; - /* The time the hardware clock had just after we - synchronized to its next clock tick when we started up. - Defined only if hclock_valid is true. - */ - - gettimeofday(&read_time, NULL); - read_hardware_clock(universal, &hclock_valid, &hclocktime); - - if (show) { - display_time(hclock_valid, hclocktime, - time_diff(read_time, startup_time)); - *retcode_p = 0; - } else if (set) { - set_hardware_clock_exact(set_time, startup_time, - universal, testing); - adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime); - *retcode_p = 0; - } else if (adjust) { - do_adjustment(&adjtime, hclock_valid, hclocktime, - read_time, universal, testing); - *retcode_p = 0; - } else if (systohc) { - struct timeval nowtime, reftime; - /* We can only set_hardware_clock_exact to a whole seconds - time, so we set it with reference to the most recent - whole seconds time. - */ - gettimeofday(&nowtime, NULL); - reftime.tv_sec = nowtime.tv_sec; - reftime.tv_usec = 0; - - set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, - universal, testing); - *retcode_p = 0; - adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, - hclocktime); - } else if (hctosys) { - rc = set_system_clock(hclock_valid, hclocktime, testing); - if (rc != 0) { - printf(_("Unable to set system clock.\n")); - *retcode_p = 1; - } else *retcode_p = 0; - } - save_adjtime(adjtime, testing); - } - } - } -} - - -static void -manipulate_epoch(const bool getepoch, const bool setepoch, - const int epoch_opt, const bool testing) { -/*---------------------------------------------------------------------------- - Get or set the Hardware Clock epoch value in the kernel, as appropriate. - , , and are hwclock invocation options. - - == -1 if the user did not specify an "epoch" option. - ------------------------------------------------------------------------------*/ - /* - Maintenance note: This should work on non-Alpha machines, but the - evidence today (98.03.04) indicates that the kernel only keeps the - epoch value on Alphas. If that is ever fixed, this function should be - changed. - */ - -#ifndef __alpha__ - fprintf(stderr, _("The kernel keeps an epoch value for the Hardware Clock " - "only on an Alpha machine.\nThis copy of hwclock was built for " - "a machine other than Alpha\n(and thus is presumably not running " - "on an Alpha now). No action taken.\n")); -#else - if (getepoch) { - unsigned long epoch; - - if (get_epoch_rtc(&epoch, 0)) - fprintf(stderr, _("Unable to get the epoch value from the kernel.\n")); - else - printf(_("Kernel is assuming an epoch value of %lu\n"), epoch); - } else if (setepoch) { - if (epoch_opt == -1) - fprintf(stderr, _("To set the epoch value, you must use the 'epoch' " - "option to tell to what value to set it.\n")); - else if (testing) - printf(_("Not setting the epoch to %d - testing only.\n"), - epoch_opt); - else if (set_epoch_rtc(epoch_opt)) - printf(_("Unable to set the epoch value in the kernel.\n")); - } -#endif -} - -/* - usage - Output (error and) usage information - - This function is called both directly from main to show usage - information and as fatal function from shhopt if some argument is - not understood. In case of normal usage info FMT should be NULL. - In that case the info is printed to stdout. If FMT is given - usage will act like fprintf( stderr, fmt, ... ), show a usage - information and terminate the program afterwards. -*/ -static void -usage( const char *fmt, ... ) { - FILE *usageto; - va_list ap; - - usageto = fmt ? stderr : stdout; - - fprintf( usageto, _( - "hwclock - query and set the hardware clock (RTC)\n\n" - "Usage: hwclock [function] [options...]\n\n" - "Functions:\n" - " --help show this help\n" - " --show read hardware clock and print result\n" - " --set set the rtc to the time given with --date\n" - " --hctosys set the system time from the hardware clock\n" - " --systohc set the hardware clock to the current system time\n" - " --adjust adjust the rtc to account for systematic drift since \n" - " the clock was last set or adjusted\n" - " --getepoch print out the kernel's hardware clock epoch value\n" - " --setepoch set the kernel's hardware clock epoch value to the \n" - " value given with --epoch\n" - " --version print out the version of hwclock to stdout\n" - "\nOptions: \n" - " --utc the hardware clock is kept in coordinated universal time\n" - " --localtime the hardware clock is kept in local time\n" - " --directisa access the ISA bus directly instead of /dev/rtc\n" - " --badyear ignore rtc's year because the bios is broken\n" - " --date specifies the time to which to set the hardware clock\n" - " --epoch=year specifies the year which is the beginning of the \n" - " hardware clock's epoch value\n" - )); -#ifdef __alpha__ - fprintf( usageto, _( - " --jensen, --arc, --srm, --funky-toy\n" - " tell hwclock the type of alpha you have (see hwclock(8))\n" - ) ); -#endif - - - fflush(stdout); - if( fmt ) { - usageto = stderr; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - } - - exit( fmt ? 99 : 0 ); -} - -int -main(int argc, char **argv, char **envp) { - - struct timeval startup_time; - /* The time we started up, in seconds into the epoch, including fractions. - */ - time_t set_time; /* Time to which user said to set Hardware Clock */ - - bool permitted; /* User is permitted to do the function */ - int retcode; /* Our eventual return code */ - - int rc; /* local return code */ - - /* option_def is the control table for the option parser. These other - variables are the results of parsing the options and their meanings - are given by the option_def. The only exception is , which - may be modified after parsing is complete to effect an implied option. - */ - bool help, show, set, systohc, hctosys, adjust, getepoch, setepoch, version; - bool ARCconsole, utc, testing, directisa, Jensen, SRM, funky_toy; - bool local_opt; - char *date_opt; - - const optStruct option_def[] = { - { 'h', (char *) "help", OPT_FLAG, &help, 0 }, - { 'r', (char *) "show", OPT_FLAG, &show, 0 }, - { 0, (char *) "set", OPT_FLAG, &set, 0 }, - { 'w', (char *) "systohc", OPT_FLAG, &systohc, 0 }, - { 's', (char *) "hctosys", OPT_FLAG, &hctosys, 0 }, - { 0, (char *) "getepoch", OPT_FLAG, &getepoch, 0 }, - { 0, (char *) "setepoch", OPT_FLAG, &setepoch, 0 }, - { 'a', (char *) "adjust", OPT_FLAG, &adjust, 0 }, - { 'v', (char *) "version", OPT_FLAG, &version, 0 }, - { 'V', (char *) "version", OPT_FLAG, &version, 0 }, - { 0, (char *) "date", OPT_STRING, &date_opt, 0 }, - { 0, (char *) "epoch", OPT_UINT, &epoch_option,0 }, - { 'u', (char *) "utc", OPT_FLAG, &utc, 0 }, - { 0, (char *) "localtime", OPT_FLAG, &local_opt, 0 }, - { 0, (char *) "badyear", OPT_FLAG, &badyear, 0 }, - { 0, (char *) "directisa", OPT_FLAG, &directisa, 0 }, - { 0, (char *) "test", OPT_FLAG, &testing, 0 }, - { 'D', (char *) "debug", OPT_FLAG, &debug, 0 }, -#ifdef __alpha__ - { 'A', (char *) "ARC", OPT_FLAG, &ARCconsole,0 }, - { 'J', (char *) "Jensen", OPT_FLAG, &Jensen, 0 }, - { 'S', (char *) "SRM", OPT_FLAG, &SRM, 0 }, - { 'F', (char *) "funky-toy", OPT_FLAG, &funky_toy, 0 }, -#endif - { 0, (char *) NULL, OPT_END, NULL, 0 } - }; - int argc_parse; /* argc, except we modify it as we parse */ - char **argv_parse; /* argv, except we modify it as we parse */ - - gettimeofday(&startup_time, NULL); /* Remember what time we were invoked */ - - /* not LC_ALL - the LC_NUMERIC part gives problems when - writing to /etc/adjtime - gqueri@mail.dotcom.fr */ - setlocale(LC_MESSAGES, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - /* set option defaults */ - help = show = set = systohc = hctosys = adjust = getepoch = setepoch = - version = utc = local_opt = ARCconsole = SRM = funky_toy = - directisa = badyear = Jensen = testing = debug = FALSE; - date_opt = NULL; - - argc_parse = argc; argv_parse = argv; - optParseOptions(&argc_parse, argv_parse, option_def, 0); - /* Uses and sets argc_parse, argv_parse. - Sets show, systohc, hctosys, adjust, utc, local_opt, version, - testing, debug, set, date_opt, getepoch, setepoch, epoch_option - */ - /* This is an ugly routine - for example, if I give an incorrect - option, it only says "unrecognized option" without telling - me what options are recognized. Rewrite with standard - getopt() and usage() and throw shhopt out. */ - - if (argc_parse - 1 > 0) { - usage( _("%s takes no non-option arguments. " - "You supplied %d.\n"), - MYNAME, argc_parse - 1); - } - - if (help) - usage( NULL ); - - if (show + set + systohc + hctosys + adjust + - getepoch + setepoch + version > 1) { - fprintf(stderr, _("You have specified multiple function options.\n" - "You can only perform one function at a time.\n")); - exit(100); - } - - if (utc && local_opt) { - fprintf(stderr, _("%s: The --utc and --localtime options are mutually " - "exclusive. You specified both.\n"), MYNAME); - exit(100); - } - -#ifdef __alpha__ - set_cmos_epoch(ARCconsole, SRM); - set_cmos_access(Jensen, funky_toy); -#endif - - if (set) { - rc = interpret_date_string(date_opt, &set_time); /* (time-consuming) */ - if (rc != 0) { - fprintf(stderr, _("No usable set-to time. Cannot set clock.\n")); - exit(100); - } - } - - if (!(show | set | systohc | hctosys | adjust | getepoch | setepoch | - version)) - show = 1; /* default to show */ - - - if (getuid() == 0) permitted = TRUE; - else { - /* program is designed to run setuid (in some situations) -- be secure! */ - if (set || hctosys || systohc || adjust) { - fprintf(stderr, - _("Sorry, only the superuser can change the Hardware Clock.\n")); - permitted = FALSE; - } else if (hctosys) { - fprintf(stderr, - _("Sorry, only the superuser can change the System Clock.\n")); - permitted = FALSE; - } else if (setepoch) { - fprintf(stderr, - _("Sorry, only the superuser can change " - "the Hardware Clock epoch in the kernel.\n")); - permitted = FALSE; - } else - permitted = TRUE; - } - - if (!permitted) retcode = 2; - else { - retcode = 0; - if (version) { - printf(MYNAME " " VERSION "/%s\n",util_linux_version); - } else if (getepoch || setepoch) { - manipulate_epoch(getepoch, setepoch, epoch_option, testing); - } else { - if (debug) - printf(MYNAME " " VERSION "/%s\n",util_linux_version); - determine_clock_access_method(directisa); - if (!ur) { - fprintf(stderr, - _("Cannot access the Hardware Clock via any known method.\n")); - if (!debug) - fprintf(stderr, - _("Use the --debug option to see the details of our " - "search for an access method.\n")); - } else - manipulate_clock(show, adjust, set, set_time, hctosys, systohc, - startup_time, utc, local_opt, testing, &rc); - } - } - exit(retcode); -} - -/* A single routine for greater uniformity */ -void -outsyserr(char *msg) { - fprintf(stderr, "%s: %s, errno=%d: %s.\n", - progname, msg, errno, strerror(errno)); -} - -/**************************************************************************** - - History of this program: - - 98.08.12 BJH Version 2.4 - - Don't use century byte from Hardware Clock. Add comments telling why. - - - 98.06.20 BJH Version 2.3. - - Make --hctosys set the kernel timezone from TZ environment variable - and/or /usr/lib/zoneinfo. From Klaus Ripke (klaus@ripke.com). - - 98.03.05 BJH. Version 2.2. - - Add --getepoch and --setepoch. - - Fix some word length things so it works on Alpha. - - Make it work when /dev/rtc doesn't have the interrupt functions. - In this case, busywait for the top of a second instead of blocking and - waiting for the update complete interrupt. - - Fix a bunch of bugs too numerous to mention. - - 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte - 50) of the ISA Hardware Clock when using direct ISA I/O. Problem - discovered by job (jei@iclnl.icl.nl). - - Use the rtc clock access method in preference to the KDGHWCLK method. - Problem discovered by Andreas Schwab . - - November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt - (janl@math.uio.no) to make it compile on linux 1.2 machines as well - as more recent versions of the kernel. Introduced the NO_CLOCK - access method and wrote feature test code to detect absense of rtc - headers. - - -************************************************************************** - Maintenance notes - - To compile this, you must use GNU compiler optimization (-O option) - in order to make the "extern inline" functions from asm/io.h (inb(), - etc.) compile. If you don't optimize, which means the compiler - will generate no inline functions, the references to these functions - in this program will be compiled as external references. Since you - probably won't be linking with any functions by these names, you will - have unresolved external references when you link. - - The program is designed to run setuid superuser, since we need to be - able to do direct I/O. (More to the point: we need permission to - execute the iopl() system call). (However, if you use one of the - methods other than direct ISA I/O to access the clock, no setuid is - required). - - Here's some info on how we must deal with the time that elapses while - this program runs: There are two major delays as we run: - - 1) Waiting up to 1 second for a transition of the Hardware Clock so - we are synchronized to the Hardware Clock. - - 2) Running the "date" program to interpret the value of our --date - option. - - Reading the /etc/adjtime file is the next biggest source of delay and - uncertainty. - - The user wants to know what time it was at the moment he invoked us, - not some arbitrary time later. And in setting the clock, he is - giving us the time at the moment we are invoked, so if we set the - clock some time later, we have to add some time to that. - - So we check the system time as soon as we start up, then run "date" - and do file I/O if necessary, then wait to synchronize with a - Hardware Clock edge, then check the system time again to see how - much time we spent. We immediately read the clock then and (if - appropriate) report that time, and additionally, the delay we measured. - - If we're setting the clock to a time given by the user, we wait some - more so that the total delay is an integral number of seconds, then - set the Hardware Clock to the time the user requested plus that - integral number of seconds. N.B. The Hardware Clock can only be set - in integral seconds. - - If we're setting the clock to the system clock value, we wait for - the system clock to reach the top of a second, and then set the - Hardware Clock to the system clock's value. - - Here's an interesting point about setting the Hardware Clock: On my - machine, when you set it, it sets to that precise time. But one can - imagine another clock whose update oscillator marches on a steady one - second period, so updating the clock between any two oscillator ticks - is the same as updating it right at the earlier tick. To avoid any - complications that might cause, we set the clock as soon as possible - after an oscillator tick. - - - About synchronizing to the Hardware Clock when reading the time: The - precision of the Hardware Clock counters themselves is one second. - You can't read the counters and find out that is 12:01:02.5. But if - you consider the location in time of the counter's ticks as part of - its value, then its precision is as infinite as time is continuous! - What I'm saying is this: To find out the _exact_ time in the - hardware clock, we wait until the next clock tick (the next time the - second counter changes) and measure how long we had to wait. We - then read the value of the clock counters and subtract the wait time - and we know precisely what time it was when we set out to query the - time. - - hwclock uses this method, and considers the Hardware Clock to have - infinite precision. - - - Enhancements needed: - - - When waiting for whole second boundary in set_hardware_clock_exact, - fail if we miss the goal by more than .1 second, as could happen if - we get pre-empted (by the kernel dispatcher). - -****************************************************************************/ - diff --git a/clock/kd.c b/clock/kd.c deleted file mode 100644 index 8fab619ff..000000000 --- a/clock/kd.c +++ /dev/null @@ -1,167 +0,0 @@ -/* kd.c - KDGHWCLK stuff, possibly m68k only */ -#include /* for close() */ -#include /* for O_RDONLY */ -#include - -#include "../defines.h" /* for HAVE_nanosleep */ -#include "clock.h" -#include "nls.h" - -static int con_fd = -1; /* opened by probe_for_kd_clock() */ - /* never closed */ - -/* Get defines for KDGHWCLK and KDSHWCLK (m68k) */ -#include -#ifndef KDGHWCLK -#define KDGHWCLK 0x4B50 /* get hardware clock */ -#define KDSHWCLK 0x4B51 /* set hardware clock */ -struct hwclk_time { - unsigned sec; /* 0..59 */ - unsigned min; /* 0..59 */ - unsigned hour; /* 0..23 */ - unsigned day; /* 1..31 */ - unsigned mon; /* 0..11 */ - unsigned year; /* 70... */ - int wday; /* 0..6, 0 is Sunday, -1 means unknown/don't set */ -}; -#endif - -static int -synchronize_to_clock_tick_kd(void) { -/*---------------------------------------------------------------------------- - Wait for the top of a clock tick by calling KDGHWCLK in a busy loop until - we see it. ------------------------------------------------------------------------------*/ - int i; - - /* The time when we were called (and started waiting) */ - struct hwclk_time start_time, nowtime; - - if (debug) - printf(_("Waiting in loop for time from KDGHWCLK to change\n")); - - if (ioctl(con_fd, KDGHWCLK, &start_time) == -1) { - outsyserr(_("KDGHWCLK ioctl to read time failed")); - return 3; - } - - i = 0; - do { - /* Added by Roman Hodek */ - /* "The culprit is the fast loop with KDGHWCLK ioctls. It seems - the kernel gets confused by those on Amigas with A2000 RTCs - and simply hangs after some time. Inserting a nanosleep helps." */ - /* Christian T. Steigies: 1 instead of 1000000 is still sufficient - to keep the machine from freezing. */ - -#ifdef HAVE_nanosleep - struct timespec sleep = { 0, 1 }; - nanosleep( &sleep, NULL ); -#else - usleep(1); -#endif - - if (i++ >= 1000000) { - fprintf(stderr, _("Timed out waiting for time change.\n")); - return 2; - } - if (ioctl(con_fd, KDGHWCLK, &nowtime) == -1) { - outsyserr(_("KDGHWCLK ioctl to read time failed in loop")); - return 3; - } - } while (start_time.sec == nowtime.sec); - - return 0; -} - - -static int -read_hardware_clock_kd(struct tm *tm) { -/*---------------------------------------------------------------------------- - Read the hardware clock and return the current time via - argument. Use ioctls to /dev/tty1 on what we assume is an m68k - machine. - - Note that we don't use /dev/console here. That might be a serial - console. ------------------------------------------------------------------------------*/ - struct hwclk_time t; - - if (ioctl(con_fd, KDGHWCLK, &t) == -1) { - outsyserr(_("ioctl() failed to read time from /dev/tty1")); - exit(5); - } - - tm->tm_sec = t.sec; - tm->tm_min = t.min; - tm->tm_hour = t.hour; - tm->tm_mday = t.day; - tm->tm_mon = t.mon; - tm->tm_year = t.year; - tm->tm_wday = t.wday; - tm->tm_isdst = -1; /* Don't know if it's Daylight Savings Time */ - - return 0; -} - - -static int -set_hardware_clock_kd(const struct tm *new_broken_time) { -/*---------------------------------------------------------------------------- - Set the Hardware Clock to the time . Use ioctls to - /dev/tty1 on what we assume is an m68k machine. - - Note that we don't use /dev/console here. That might be a serial console. -----------------------------------------------------------------------------*/ - struct hwclk_time t; - - t.sec = new_broken_time->tm_sec; - t.min = new_broken_time->tm_min; - t.hour = new_broken_time->tm_hour; - t.day = new_broken_time->tm_mday; - t.mon = new_broken_time->tm_mon; - t.year = new_broken_time->tm_year; - t.wday = new_broken_time->tm_wday; - - if (ioctl(con_fd, KDSHWCLK, &t ) == -1) { - outsyserr(_("ioctl() to open /dev/tty1 failed")); - exit(1); - } - return 0; -} - -static int -get_permissions_kd(void) { - return 0; -} - -static struct clock_ops kd = { - "KDGHWCLK interface to m68k clock", - get_permissions_kd, - read_hardware_clock_kd, - set_hardware_clock_kd, - synchronize_to_clock_tick_kd, -}; - -/* return &kd if KDGHWCLK works, NULL otherwise */ -struct clock_ops * -probe_for_kd_clock() { - struct clock_ops *ret = NULL; - struct hwclk_time t; - - if (con_fd < 0) - con_fd = open("/dev/tty1", O_RDONLY); - if (con_fd >= 0) { - if (ioctl( con_fd, KDGHWCLK, &t ) == -1) { - if (errno != EINVAL) - outsyserr(_("KDGHWCLK ioctl failed")); - } else - ret = &kd; - } else { - /* probably KDGHWCLK exists on m68k only */ -#ifdef __m68k__ - outsyserr(_("Can't open /dev/tty1")); -#endif - } - return ret; -} diff --git a/clock/rtc.c b/clock/rtc.c deleted file mode 100644 index 652388430..000000000 --- a/clock/rtc.c +++ /dev/null @@ -1,389 +0,0 @@ -/* rtc.c - Use /dev/rtc for clock access */ -#include /* for close() */ -#include /* for O_RDONLY */ -#include - -#include "clock.h" -#include "nls.h" - -/* - * Get defines for rtc stuff. - * - * Getting the rtc defines is nontrivial. - * The obvious way is by including - * but that again includes which again includes ... - * and on sparc and alpha this gives compilation errors for - * many kernel versions. So, we give the defines ourselves here. - * Moreover, some Sparc person decided to be incompatible, and - * used a struct rtc_time different from that used in mc146818rtc.h. - */ - -/* On Sparcs, there is a that defines different ioctls - (that are required on my machine). However, this include file - does not exist on other architectures. */ -/* One might do: -#ifdef __sparc__ -#include -#endif - */ -/* The following is roughly equivalent */ -struct sparc_rtc_time -{ - int sec; /* Seconds (0-59) */ - int min; /* Minutes (0-59) */ - int hour; /* Hour (0-23) */ - int dow; /* Day of the week (1-7) */ - int dom; /* Day of the month (1-31) */ - int month; /* Month of year (1-12) */ - int year; /* Year (0-99) */ -}; - -#define RTCGET _IOR('p', 20, struct sparc_rtc_time) -#define RTCSET _IOW('p', 21, struct sparc_rtc_time) - - -/* non-sparc stuff */ -#if 0 -#include -/* Check if the /dev/rtc interface is available in this version of - the system headers. 131072 is linux 2.0.0. */ -#if LINUX_VERSION_CODE >= 131072 -#include -#endif -#endif - -/* struct rtc_time is present since 1.3.99 */ -/* Earlier (since 1.3.89), a struct tm was used. */ -struct linux_rtc_time { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; -}; - -/* RTC_RD_TIME etc have this definition since 1.99.9 (pre2.0-9) */ -#ifndef RTC_RD_TIME -#define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time) -#define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time) -#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */ -#define RTC_UIE_OFF _IO('p', 0x04) /* Update int. enable off */ -#endif -/* RTC_EPOCH_READ and RTC_EPOCH_SET are present since 2.0.34 and 2.1.89 */ -#ifndef RTC_EPOCH_READ -#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ -#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ -#endif - - -static int -do_rtc_read_ioctl(int rtc_fd, struct tm *tm) { - int rc; - char *ioctlname; -#ifdef __sparc__ - struct sparc_rtc_time stm; - - ioctlname = "RTCGET"; - rc = ioctl(rtc_fd, RTCGET, &stm); -#else - ioctlname = "RTC_RD_TIME"; - rc = ioctl(rtc_fd, RTC_RD_TIME, tm); -#endif - if (rc == -1) { - perror(ioctlname); - fprintf(stderr, _("ioctl() to /dev/rtc to read the time failed.\n")); - exit(5); - } -#ifdef __sparc__ - tm->tm_sec = stm.sec; - tm->tm_min = stm.min; - tm->tm_hour = stm.hour; - tm->tm_mday = stm.dom; - tm->tm_mon = stm.month - 1; - tm->tm_year = stm.year - 1900; - tm->tm_wday = stm.dow - 1; - tm->tm_yday = -1; /* day in the year */ -#endif - tm->tm_isdst = -1; /* don't know whether it's daylight */ - return 0; -} - - -static int -busywait_for_rtc_clock_tick(const int rtc_fd) { -/*---------------------------------------------------------------------------- - Wait for the top of a clock tick by reading /dev/rtc in a busy loop until - we see it. ------------------------------------------------------------------------------*/ - struct tm start_time; - /* The time when we were called (and started waiting) */ - struct tm nowtime; - int i; /* local loop index */ - int rc; - - if (debug) - printf(_("Waiting in loop for time from /dev/rtc to change\n")); - - rc = do_rtc_read_ioctl(rtc_fd, &start_time); - if (rc) - return 1; - - /* Wait for change. Should be within a second, but in case something - weird happens, we have a limit on this loop to reduce the impact - of this failure. - */ - for (i = 0; - (rc = do_rtc_read_ioctl(rtc_fd, &nowtime)) == 0 - && start_time.tm_sec == nowtime.tm_sec; - i++) - if (i >= 1000000) { - fprintf(stderr, _("Timed out waiting for time change.\n")); - return 2; - } - - if (rc) - return 3; - return 0; -} - - - -static int -synchronize_to_clock_tick_rtc(void) { -/*---------------------------------------------------------------------------- - Same as synchronize_to_clock_tick(), but just for /dev/rtc. ------------------------------------------------------------------------------*/ -int rtc_fd; /* File descriptor of /dev/rtc */ -int ret; - - rtc_fd = open("/dev/rtc",O_RDONLY); - if (rtc_fd == -1) { - outsyserr(_("open() of /dev/rtc failed")); - ret = 1; - } else { - int rc; /* Return code from ioctl */ - /* Turn on update interrupts (one per second) */ -#if defined(__alpha__) || defined(__sparc__) - /* Not all alpha kernels reject RTC_UIE_ON, but probably they should. */ - rc = -1; - errno = EINVAL; -#else - rc = ioctl(rtc_fd, RTC_UIE_ON, 0); -#endif - if (rc == -1 && errno == EINVAL) { - /* This rtc device doesn't have interrupt functions. This is typical - on an Alpha, where the Hardware Clock interrupts are used by the - kernel for the system clock, so aren't at the user's disposal. - */ - if (debug) printf(_("/dev/rtc does not have interrupt functions. ")); - ret = busywait_for_rtc_clock_tick(rtc_fd); - } else if (rc != -1) { - int rc; /* return code from ioctl */ - unsigned long dummy; - - /* this blocks until the next update interrupt */ - rc = read(rtc_fd, &dummy, sizeof(dummy)); - if (rc == -1) { - outsyserr(_("read() to /dev/rtc to wait for clock tick failed")); - ret = 1; - } else { - ret = 0; - } - /* Turn off update interrupts */ - rc = ioctl(rtc_fd, RTC_UIE_OFF, 0); - if (rc == -1) - outsyserr(_("ioctl() to /dev/rtc to turn off update interrupts " - "failed")); - } else { - outsyserr(_("ioctl() to /dev/rtc to turn on update interrupts " - "failed unexpectedly")); - ret = 1; - } - close(rtc_fd); - } - return ret; -} - - -static int -read_hardware_clock_rtc(struct tm *tm) { -/*---------------------------------------------------------------------------- - Read the hardware clock and return the current time via - argument. Use ioctls to "rtc" device /dev/rtc. ------------------------------------------------------------------------------*/ - int rtc_fd; /* File descriptor of /dev/rtc */ - - rtc_fd = open("/dev/rtc",O_RDONLY); - if (rtc_fd == -1) { - outsyserr(_("open() of /dev/rtc failed")); - exit(5); - } - - /* Read the RTC time/date */ - do_rtc_read_ioctl(rtc_fd, tm); - - close(rtc_fd); - return 0; -} - - -static int -set_hardware_clock_rtc(const struct tm *new_broken_time) { -/*---------------------------------------------------------------------------- - Set the Hardware Clock to the broken down time . - Use ioctls to "rtc" device /dev/rtc. -----------------------------------------------------------------------------*/ - int rc; - int rtc_fd; - - rtc_fd = open("/dev/rtc", O_RDONLY); - if (rtc_fd < 0) { - outsyserr(_("Unable to open /dev/rtc")); - exit(5); - } else { - char *ioctlname; -#ifdef __sparc__ - struct sparc_rtc_time stm; - - stm.sec = new_broken_time->tm_sec; - stm.min = new_broken_time->tm_min; - stm.hour = new_broken_time->tm_hour; - stm.dom = new_broken_time->tm_mday; - stm.month = new_broken_time->tm_mon + 1; - stm.year = new_broken_time->tm_year + 1900; - stm.dow = new_broken_time->tm_wday + 1; - - ioctlname = "RTCSET"; - rc = ioctl(rtc_fd, RTCSET, &stm); -#else - ioctlname = "RTC_SET_TIME"; - rc = ioctl(rtc_fd, RTC_SET_TIME, new_broken_time); -#endif - if (rc == -1) { - perror(ioctlname); - fprintf(stderr, _("ioctl() to /dev/rtc to set the time failed.\n")); - exit(5); - } else { - if (debug) - printf(_("ioctl(%s) was successful.\n"), ioctlname); - } - close(rtc_fd); - } - return 0; -} - - -static int -get_permissions_rtc(void) { - return 0; -} - -static struct clock_ops rtc = { - "/dev/rtc interface to clock", - get_permissions_rtc, - read_hardware_clock_rtc, - set_hardware_clock_rtc, - synchronize_to_clock_tick_rtc, -}; - -/* return &rtc if /dev/rtc can be opened, NULL otherwise */ -struct clock_ops * -probe_for_rtc_clock(){ - int rtc_fd = open("/dev/rtc", O_RDONLY); - if (rtc_fd > 0) { - close(rtc_fd); - return &rtc; - } - if (debug) - outsyserr(_("Open of /dev/rtc failed")); - return NULL; -} - - - -int -get_epoch_rtc(unsigned long *epoch_p, int silent) { -/*---------------------------------------------------------------------------- - Get the Hardware Clock epoch setting from the kernel. -----------------------------------------------------------------------------*/ - int rtc_fd; - - rtc_fd = open("/dev/rtc", O_RDONLY); - if (rtc_fd < 0) { - if (!silent) { - if (errno == ENOENT) - fprintf(stderr, _( - "To manipulate the epoch value in the kernel, we must " - "access the Linux 'rtc' device driver via the device special " - "file /dev/rtc. This file does not exist on this system.\n")); - else - outsyserr(_("Unable to open /dev/rtc")); - } - return 1; - } - - if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) { - if (!silent) - outsyserr(_("ioctl(RTC_EPOCH_READ) to /dev/rtc failed")); - close(rtc_fd); - return 1; - } - - if (debug) - printf(_("we have read epoch %ld from /dev/rtc " - "with RTC_EPOCH_READ ioctl.\n"), *epoch_p); - - close(rtc_fd); - return 0; -} - - - -int -set_epoch_rtc(unsigned long epoch) { -/*---------------------------------------------------------------------------- - Set the Hardware Clock epoch in the kernel. -----------------------------------------------------------------------------*/ - int rtc_fd; - - if (epoch < 1900) { - /* kernel would not accept this epoch value */ - /* Hmm - bad habit, deciding not to do what the user asks - just because one believes that the kernel might not like it. */ - fprintf(stderr, _("The epoch value may not be less than 1900. " - "You requested %ld\n"), epoch); - return 1; - } - - rtc_fd = open("/dev/rtc", O_RDONLY); - if (rtc_fd < 0) { - if (errno == ENOENT) - fprintf(stderr, _("To manipulate the epoch value in the kernel, we must " - "access the Linux 'rtc' device driver via the device special " - "file /dev/rtc. This file does not exist on this system.\n")); - else - outsyserr(_("Unable to open /dev/rtc")); - return 1; - } - - if (debug) - printf(_("setting epoch to %ld " - "with RTC_EPOCH_SET ioctl to /dev/rtc.\n"), epoch); - - if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) { - if (errno == EINVAL) - fprintf(stderr, _("The kernel device driver for /dev/rtc " - "does not have the RTC_EPOCH_SET ioctl.\n")); - else - outsyserr(_("ioctl(RTC_EPOCH_SET) to /dev/rtc failed")); - close(rtc_fd); - return 1; - } - - close(rtc_fd); - return 0; -} diff --git a/clock/shhopt-1.1.lsm b/clock/shhopt-1.1.lsm deleted file mode 100644 index a61a26969..000000000 --- a/clock/shhopt-1.1.lsm +++ /dev/null @@ -1,17 +0,0 @@ -Begin3 -Title: shhopt - library for parsing command line options. -Version: 1.1 -Entered-date: 06JUN96 -Description: C-functions for parsing command line options, both - traditional one-character options, and GNU'ish - --long-options. -Keywords: programming, library, lib, commandline -Author: sverrehu@ifi.uio.no (Sverre H. Huseby) -Primary-site: sunsite.unc.edu /pub/Linux/libs - shhopt-1.1.tar.gz -Platforms: Requires ANSI C-compiler. -Copying-policy: BeerWare: If you have the time and money, send me a bottle - of your favourite beer. If not, just send me a mail or - something. Copy and use as you wish; just leave the - author's name where you find it. -End diff --git a/clock/shhopt.c b/clock/shhopt.c deleted file mode 100644 index ac3412829..000000000 --- a/clock/shhopt.c +++ /dev/null @@ -1,468 +0,0 @@ -/* $Id: shhopt.c,v 2.2 1997/07/06 23:11:55 aebr Exp $ */ -/************************************************************************** - * - * FILE shhopt.c - * - * DESCRIPTION Functions for parsing command line arguments. Values - * of miscellaneous types may be stored in variables, - * or passed to functions as specified. - * - * REQUIREMENTS Some systems lack the ANSI C -function strtoul. If your - * system is one of those, you'll ned to write one yourself, - * or get the GNU liberty-library (from prep.ai.mit.edu). - * - * WRITTEN BY Sverre H. Huseby - * - **************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#include "shhopt.h" -#include "nls.h" - -/************************************************************************** - * * - * P R I V A T E D A T A * - * * - **************************************************************************/ - -static void optFatalFunc(const char *, ...); -static void (*optFatal)(const char *format, ...) = optFatalFunc; - - - -/************************************************************************** - * * - * P R I V A T E F U N C T I O N S * - * * - **************************************************************************/ - -/*------------------------------------------------------------------------- - * - * NAME optFatalFunc - * - * FUNCTION Show given message and abort the program. - * - * INPUT format, ... - * Arguments used as with printf(). - * - * RETURNS Never returns. The program is aborted. - * - */ -void optFatalFunc(const char *format, ...) -{ - va_list ap; - - fflush(stdout); - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); - exit(99); -} - - - -/*------------------------------------------------------------------------- - * - * NAME optStructCount - * - * FUNCTION Get number of options in a optStruct. - * - * INPUT opt array of possible options. - * - * RETURNS Number of options in the given array. - * - * DESCRIPTION Count elements in an optStruct-array. The strcture must - * be ended using an element of type OPT_END. - * - */ -static int optStructCount(const optStruct opt[]) -{ - int ret = 0; - - while (opt[ret].type != OPT_END) - ++ret; - return ret; -} - - - -/*------------------------------------------------------------------------- - * - * NAME optMatch - * - * FUNCTION Find a matching option. - * - * INPUT opt array of possible options. - * s string to match, without `-' or `--'. - * lng match long option, otherwise short. - * - * RETURNS Index to the option if found, -1 if not found. - * - * DESCRIPTION Short options are matched from the first character in - * the given string. - * - */ -static int optMatch(const optStruct opt[], const char *s, int lng) -{ - int nopt, q, matchlen = 0; - char *p; - - nopt = optStructCount(opt); - if (lng) { - if ((p = strchr(s, '=')) != NULL) - matchlen = p - s; - else - matchlen = strlen(s); - } - for (q = 0; q < nopt; q++) { - if (lng) { - if (!opt[q].longName) - continue; - if (strncmp(s, opt[q].longName, matchlen) == 0) - return q; - } else { - if (!opt[q].shortName) - continue; - if (*s == opt[q].shortName) - return q; - } - } - return -1; -} - - - -/*------------------------------------------------------------------------- - * - * NAME optString - * - * FUNCTION Return a (static) string with the option name. - * - * INPUT opt the option to stringify. - * lng is it a long option? - * - * RETURNS Pointer to static string. - * - */ -static char *optString(const optStruct *opt, int lng) -{ - static char ret[31]; - - if (lng) { - strcpy(ret, "--"); - strncpy(ret + 2, opt->longName, 28); - } else { - ret[0] = '-'; - ret[1] = opt->shortName; - ret[2] = '\0'; - } - return ret; -} - - - -/*------------------------------------------------------------------------- - * - * NAME optNeedsArgument - * - * FUNCTION Check if an option requires an argument. - * - * INPUT opt the option to check. - * - * RETURNS Boolean value. - * - */ -static int optNeedsArgument(const optStruct *opt) -{ - return opt->type == OPT_STRING - || opt->type == OPT_INT - || opt->type == OPT_UINT - || opt->type == OPT_LONG - || opt->type == OPT_ULONG; -} - - - -/*------------------------------------------------------------------------- - * - * NAME argvRemove - * - * FUNCTION Remove an entry from an argv-array. - * - * INPUT argc pointer to number of options. - * argv array of option-/argument-strings. - * i index of option to remove. - * - * OUTPUT argc new argument count. - * argv array with given argument removed. - * - */ -static void argvRemove(int *argc, char *argv[], int i) -{ - if (i >= *argc) - return; - while (i++ < *argc) - argv[i - 1] = argv[i]; - --*argc; -} - - - -/*------------------------------------------------------------------------- - * - * NAME optExecute - * - * FUNCTION Perform the action of an option. - * - * INPUT opt array of possible options. - * arg argument to option, if it applies. - * lng was the option given as a long option? - * - * RETURNS Nothing. Aborts in case of error. - * - */ -static void optExecute(const optStruct *opt, char *arg, int lng) -{ - switch (opt->type) { - case OPT_FLAG: - if (opt->flags & OPT_CALLFUNC) - ((void (*)(void)) opt->arg)(); - else - *((int *) opt->arg) = 1; - break; - - case OPT_STRING: - if (opt->flags & OPT_CALLFUNC) - ((void (*)(char *)) opt->arg)(arg); - else - *((char **) opt->arg) = arg; - break; - - case OPT_INT: - case OPT_LONG: { - long tmp; - char *e; - - tmp = strtol(arg, &e, 10); - if (*e) - optFatal(_("invalid number `%s'\n"), arg); - if (errno == ERANGE - || (opt->type == OPT_INT && (tmp > INT_MAX || tmp < INT_MIN))) - optFatal(_("number `%s' to `%s' out of range\n"), - arg, optString(opt, lng)); - if (opt->type == OPT_INT) { - if (opt->flags & OPT_CALLFUNC) - ((void (*)(int)) opt->arg)((int) tmp); - else - *((int *) opt->arg) = (int) tmp; - } else /* OPT_LONG */ { - if (opt->flags & OPT_CALLFUNC) - ((void (*)(long)) opt->arg)(tmp); - else - *((long *) opt->arg) = tmp; - } - break; - } - - case OPT_UINT: - case OPT_ULONG: { - unsigned long tmp; - char *e; - - tmp = strtoul(arg, &e, 10); - if (*e) - optFatal(_("invalid number `%s'\n"), arg); - if (errno == ERANGE - || (opt->type == OPT_UINT && tmp > UINT_MAX)) - optFatal(_("number `%s' to `%s' out of range\n"), - arg, optString(opt, lng)); - if (opt->type == OPT_UINT) { - if (opt->flags & OPT_CALLFUNC) - ((void (*)(unsigned)) opt->arg)((unsigned) tmp); - else - *((unsigned *) opt->arg) = (unsigned) tmp; - } else /* OPT_ULONG */ { - if (opt->flags & OPT_CALLFUNC) - ((void (*)(unsigned long)) opt->arg)(tmp); - else - *((unsigned long *) opt->arg) = tmp; - } - break; - } - - default: - break; - } -} - - - -/************************************************************************** - * * - * P U B L I C F U N C T I O N S * - * * - **************************************************************************/ - -/*------------------------------------------------------------------------- - * - * NAME optSetFatalFunc - * - * FUNCTION Set function used to display error message and exit. - * - * SYNOPSIS #include "shhmsg.h" - * void optSetFatalFunc(void (*f)(const char *, ...)); - * - * INPUT f function accepting printf()'like parameters, - * that _must_ abort the program. - * - */ -void optSetFatalFunc(void (*f)(const char *, ...)) -{ - optFatal = f; -} - - - -/*------------------------------------------------------------------------- - * - * NAME optParseOptions - * - * FUNCTION Parse commandline options. - * - * SYNOPSIS #include "shhopt.h" - * void optParseOptions(int *argc, char *argv[], - * const optStruct opt[], int allowNegNum); - * - * INPUT argc Pointer to number of options. - * argv Array of option-/argument-strings. - * opt Array of possible options. - * allowNegNum - * a negative number is not to be taken as - * an option. - * - * OUTPUT argc new argument count. - * argv array with arguments removed. - * - * RETURNS Nothing. Aborts in case of error. - * - * DESCRIPTION This function checks each option in the argv-array - * against strings in the opt-array, and `executes' any - * matching action. Any arguments to the options are - * extracted and stored in the variables or passed to - * functions pointed to by entries in opt. - * - * Options and arguments used are removed from the argv- - * array, and argc is decreased accordingly. - * - * Any error leads to program abortion. - * - */ -void optParseOptions(int *argc, char *argv[], - const optStruct opt[], int allowNegNum) -{ - int ai, /* argv index. */ - optarg, /* argv index of option argument, or -1 if none. */ - mi, /* Match index in opt. */ - done; - char *arg, /* Pointer to argument to an option. */ - *o, /* pointer to an option character */ - *p; - - /* - * Loop through all arguments. - */ - for (ai = 0; ai < *argc; ) { - /* - * "--" indicates that the rest of the argv-array does not - * contain options. - */ - if (strcmp(argv[ai], "--") == 0) { - argvRemove(argc, argv, ai); - break; - } - - if (allowNegNum && argv[ai][0] == '-' && isdigit(argv[ai][1])) { - ++ai; - continue; - } else if (strncmp(argv[ai], "--", 2) == 0) { - /* long option */ - /* find matching option */ - if ((mi = optMatch(opt, argv[ai] + 2, 1)) < 0) - optFatal(_("unrecognized option `%s'\n"), argv[ai]); - - /* possibly locate the argument to this option. */ - arg = NULL; - if ((p = strchr(argv[ai], '=')) != NULL) - arg = p + 1; - - /* does this option take an argument? */ - optarg = -1; - if (optNeedsArgument(&opt[mi])) { - /* option needs an argument. find it. */ - if (!arg) { - if ((optarg = ai + 1) == *argc) - optFatal(_("option `%s' requires an argument\n"), - optString(&opt[mi], 1)); - arg = argv[optarg]; - } - } else { - if (arg) - optFatal(_("option `%s' doesn't allow an argument\n"), - optString(&opt[mi], 1)); - } - /* perform the action of this option. */ - optExecute(&opt[mi], arg, 1); - /* remove option and any argument from the argv-array. */ - if (optarg >= 0) - argvRemove(argc, argv, ai); - argvRemove(argc, argv, ai); - } else if (*argv[ai] == '-') { - /* A dash by itself is not considered an option. */ - if (argv[ai][1] == '\0') { - ++ai; - continue; - } - /* Short option(s) following */ - o = argv[ai] + 1; - done = 0; - optarg = -1; - while (*o && !done) { - /* find matching option */ - if ((mi = optMatch(opt, o, 0)) < 0) - optFatal(_("unrecognized option `-%c'\n"), *o); - - /* does this option take an argument? */ - optarg = -1; - arg = NULL; - if (optNeedsArgument(&opt[mi])) { - /* option needs an argument. find it. */ - arg = o + 1; - if (!*arg) { - if ((optarg = ai + 1) == *argc) - optFatal(_("option `%s' requires an argument\n"), - optString(&opt[mi], 0)); - arg = argv[optarg]; - } - done = 1; - } - /* perform the action of this option. */ - optExecute(&opt[mi], arg, 0); - ++o; - } - /* remove option and any argument from the argv-array. */ - if (optarg >= 0) - argvRemove(argc, argv, ai); - argvRemove(argc, argv, ai); - } else { - /* a non-option argument */ - ++ai; - } - } -} diff --git a/clock/shhopt.h b/clock/shhopt.h deleted file mode 100644 index ca8501ef5..000000000 --- a/clock/shhopt.h +++ /dev/null @@ -1,33 +0,0 @@ -/* $Id: shhopt.h,v 2.2 1997/07/06 23:11:58 aebr Exp $ */ -#ifndef SHHOPT_H -#define SHHOPT_H - -/* constants for recognized option types. */ -typedef enum { - OPT_END, /* nothing. used as ending element. */ - OPT_FLAG, /* no argument following. sets variable to 1. */ - OPT_STRING, /* string argument. */ - OPT_INT, /* signed integer argument. */ - OPT_UINT, /* unsigned integer argument. */ - OPT_LONG, /* signed long integer argument. */ - OPT_ULONG, /* unsigned long integer argument. */ -} optArgType; - -/* flags modifying the default way options are handeled. */ -#define OPT_CALLFUNC 1 /* pass argument to a function. */ - -typedef struct { - char shortName; /* Short option name. */ - char *longName; /* Long option name, no including '--'. */ - optArgType type; /* Option type. */ - void *arg; /* Pointer to variable to fill with argument, - * or pointer to function if Type == OPT_FUNC. */ - int flags; /* Modifier flags. */ -} optStruct; - - -void optSetFatalFunc(void (*f)(const char *, ...)); -void optParseOptions(int *argc, char *argv[], - const optStruct opt[], int allowNegNum); - -#endif diff --git a/configure b/configure index 4ac10b046..fd5ab6422 100755 --- a/configure +++ b/configure @@ -3,27 +3,35 @@ # # We need to find out the following things: # -# 1. For mount/nfsmount.c: is inet_aton() available? -# 2. For fdisk/fdisksunlabel.c: is there a ? -# For fdisk/fdisk.c: is there a ? -# 4. For sys-utils/cytune.c: do we need ? -# 5. For sys-utils/kbd_rate.c: does exist? -# 6. For cfdisk, setterm, more, ul: do we have ncurses? How installed? -# For more: do we have libtermcap? -# 7. For chfn, chsh, login, newgrp, passwd: do we need -lcrypt? -# 8. For sln: does static compilation work? -# 9. For lib/nls.h: do we have ? -# 10. For lib/nls.h: do we have and gettext()? -# 11. For xgettext: does it take the option --foreign-user? -# 12. For cal.c: do we have ? -# 13. For err.c: do we have __progname? -# 14. For script.c: do we have and openpty()? -# 15. For lib/widechar.h: do we have wide character support? -# 16. For clock/kd.c: do we have nanosleep()? -# 17. For mkswap: do we have personality()? -# 18. For pivot_root.c: does define __NR_pivot_root? -# 19. For hwclock.c: does struct tm have a field tm_gmtoff? -# 20. For nfsmount: does the output of rpcgen compile? +# Existence of header files: +# H1. For fdisksunlabel.c: is there a ? +# H2. For fdisk.c: is there a ? +# H3. For kbd_rate.c: does exist? +# H4. For nls.h: do we have ? +# H5. For cal.c: do we have ? +# H6. For mkswap.c: do we have ? +# H7. For nfsmount.h (nfsmount_xdr.c: int32_t): do we have ? +# +# Existence of functions: +# F1. For nfsmount.c: is inet_aton() available? +# F2. For mkswap.c: is fsync() available? +# F3. For agetty.c: is getdomainname() available? +# F4. For hwclock/kd.c: do we have nanosleep()? +# F5. For mkswap.c: do we have personality()? +# +# 1. For sys-utils/cytune.c: do we need ? +# 2. For cfdisk, setterm, more, ul: do we have ncurses? How installed? +# 3. For more: do we have libtermcap? +# 4. For chfn, chsh, login, newgrp, passwd: do we need -lcrypt? +# 5. For sln: does static compilation work? +# 6. For lib/nls.h: do we have and gettext()? +# 7. For xgettext: does it take the option --foreign-user? +# 8. For err.c: do we have __progname? +# 9. For script.c: do we have and openpty()? +# 10. For lib/widechar.h: do we have wide character support? +# 11. For pivot_root.c: does define __NR_pivot_root? +# 12. For hwclock.c: does struct tm have a field tm_gmtoff? +# 13. For nfsmount: does the output of rpcgen compile? rm -f make_include defines.h @@ -36,24 +44,13 @@ echo '#define UTIL_LINUX_VERSION "'$VERSION'"' > defines.h echo '#define util_linux_version "util-linux-'$VERSION'"' >> defines.h echo >> defines.h -if test -z "$CC" -then - if test "$RANDOM" = "$RANDOM"; then - # Plain old Bourne shell. - echo checking for gcc - test -z "$CC" -a -n "`gcc 2>&1`" && CC="gcc -O" - else - # ksh, bash or zsh. ksh and zsh write "command not found" to stderr. - echo checking for gcc - test -z "$CC" && type gcc && CC="gcc -O" - fi -else - echo "Using CC=\"$CC\"" - echo -fi - CC=${CC-cc} CFLAGS=${CFLAGS-"-O"} +LDFLAGS=${LDFLAGS-"-s"} +echo CC=$CC >> make_include +echo CFLAGS=$CFLAGS >> make_include +echo LDFLAGS=$LDFLAGS >> make_include + DEFS= LIBS= compile='$CC $CFLAGS $DEFS conftest.c -o conftest $LIBS >/dev/null 2>&1' @@ -63,8 +60,80 @@ export COMPILE rm -f conftest.c conftest + +# +# Find out about the existence of header files +# + # -# 1. For mount/nfsmount.c: is inet_aton() available? +# H1. For fdisk/fdisksunlabel.c: is available? +# Some kernels have that uses u_char +# But maybe there is already a typedef. Let us use a #define +# +echo " +#define u_char unsigned char +#include +#undef u_char +main(){ exit(0); } +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_scsi_h" >> defines.h + echo "You have " +else + echo "You don't have " +fi +rm -f conftest conftest.c + +# +# H2. For fdisk/fdisk.c: is available? +# +if ./testincl "linux/blkpg.h"; then + echo "#define HAVE_blkpg_h" >> defines.h +fi + +# +# H3. Does exist? +# +if ./testincl "linux/kd.h"; then + echo "#define HAVE_kd_h" >> defines.h +fi + +# +# H4. For lib/nls.h: do we have ? +# +if ./testincl "locale.h"; then + echo "#define HAVE_locale_h" >> defines.h +fi + +# +# H5. For cal.c: do we have ? +# +if ./testincl "langinfo.h"; then + echo "#define HAVE_langinfo_h" >> defines.h +fi + +# +# H6. For mkswap.c: do we have ? +# +if ./testincl "asm/page.h"; then + echo "#define HAVE_asm_page_h" >> defines.h +fi + +# +# H7. For nfsmount.h: do we have ? +# +if ./testincl "asm/types.h"; then + echo "#define HAVE_asm_types_h" >> defines.h +fi + + +# +# Find out about the existence of functions +# + +# +# F1. For mount/nfsmount.c: is inet_aton() available? # echo " #include @@ -86,34 +155,88 @@ fi rm -f conftest conftest.c # -# 2. For fdisk/fdisksunlabel.c: is available? -# Some kernels have that uses u_char -# But maybe there is already a typedef. Let us use a #define +# F2. For mkswap.c: is fsync() available? # echo " -#define u_char unsigned char -#include -#undef u_char -main(){ exit(0); } +#include +main(int a, char **v){ + if (a == -1) /* false */ + fsync(0); + exit(0); +} " > conftest.c eval $compile if test -s conftest && ./conftest 2>/dev/null; then - echo "#define HAVE_scsi_h" >> defines.h - echo "You have " + echo "#define HAVE_fsync" >> defines.h + echo "You have fsync()" else - echo "You don't have " + echo "You don't have fsync()" fi rm -f conftest conftest.c # -# 2A. For fdisk/fdisk.c: is available? +# F3. For agetty.c: is getdomainname() available? # -if ./testincl "linux/blkpg.h"; then - echo "#define HAVE_blkpg_h" >> defines.h +echo " +#include +main(int a, char **v){ + char buf[1]; + if (a == -1) /* false */ + getdomainname(buf, sizeof buf); + exit(0); +} +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_getdomainname" >> defines.h + echo "You have getdomainname()" +else + echo "You don't have getdomainname()" fi +rm -f conftest conftest.c # -# 4. cytune.c may need struct tq_struct +# F4. For hwclock/kd.c: do we have nanosleep? +# +echo " +#include +int main () { + struct timespec sleep = { 0, 1 }; + nanosleep( &sleep, NULL ); + exit(0); +} +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_nanosleep" >> defines.h + echo "You have nanosleep()" +else + echo "You don't have nanosleep()" +fi +rm -f conftest conftest.c + +# +# F5. For mkswap.c: do we have personality()? +# +echo " +int main () { + extern int personality(unsigned long); + personality(0); + exit(0); +} +" > conftest.c +eval $compile +if test -s conftest && ./conftest 2>/dev/null; then + echo "#define HAVE_personality" >> defines.h + echo "You have personality()" +else + echo "You don't have personality()" +fi +rm -f conftest conftest.c + + +# +# 1. cytune.c may need struct tq_struct # echo " #include @@ -130,14 +253,7 @@ fi rm -f conftest conftest.c # -# 5. Does exist? -# -if ./testincl "linux/kd.h"; then - echo "#define HAVE_kd_h" >> defines.h -fi - -# -# 6. How is [n]curses installed? +# 2. How is [n]curses installed? # test_curses_h=0 have_ncurses=1 @@ -214,7 +330,7 @@ fi rm -f conftest conftest.c # -# 7. Do we need -lcrypt? +# 4. Do we need -lcrypt? # echo ' #define _XOPEN_SOURCE @@ -232,7 +348,7 @@ fi rm -f conftest conftest.c # -# 8. Does static compilation work? +# 5. Does static compilation work? # echo " main(){ return 0; } @@ -244,17 +360,10 @@ else echo "CAN_DO_STATIC=no" >> make_include echo "Strange... Static compilation fails here." fi +rm -f conftest.c conftest # -# 9. For lib/nls.h: do we have ? -# -if ./testincl "locale.h"; then - echo "#define HAVE_locale_h" >> defines.h -fi - - -# -# 10. For lib/nls.h: do we have and gettext() ? +# 6. For lib/nls.h: do we have and gettext() ? # echo ' #include @@ -280,7 +389,7 @@ rm -f conftest conftest.c # -# 11. Does xgettext exist and take the option --foreign-user? +# 7. Does xgettext exist and take the option --foreign-user? # if (test $ENABLE_NLS = yes && type xgettext > /dev/null 2>&1); then msg=`xgettext --foreign-user 2>&1 | grep unrecognized` @@ -294,16 +403,9 @@ else echo "HAVE_XGETTEXT=no" >> make_include fi -# -# 12. For cal.c: do we have ? -# -if ./testincl "langinfo.h"; then - echo "#define HAVE_langinfo_h" >> defines.h -fi - # -# 13. For err.c: do we have __progname? +# 8. For err.c: do we have __progname? # [make sure gcc -O does not optimize the access away] # echo " @@ -321,7 +423,7 @@ fi rm -f conftest conftest.c # -# 14. For script.c: do we have and openpty()? +# 9. For script.c: do we have and openpty()? # echo " #include @@ -340,7 +442,7 @@ fi rm -f conftest conftest.c # -# 15. For lib/widechar.h: do we have wide character support? +# 10. For lib/widechar.h: do we have wide character support? # [Do we have the headers , , the types wchar_t, wint_t # and the fgetwc, fputwc, WEOF functions/macros?] # @@ -368,46 +470,7 @@ fi rm -f conftest conftest.c # -# 16. For clock/kd.c: do we have nanosleep? -# -echo " -#include -int main () { - struct timespec sleep = { 0, 1 }; - nanosleep( &sleep, NULL ); - exit(0); -} -" > conftest.c -eval $compile -if test -s conftest && ./conftest 2>/dev/null; then - echo "#define HAVE_nanosleep" >> defines.h - echo "You have nanosleep()" -else - echo "You don't have nanosleep()" -fi -rm -f conftest conftest.c - -# -# 17. For mkswap.c: do we have personality()? -# -echo " -int main () { - extern int personality(unsigned long); - personality(0); - exit(0); -} -" > conftest.c -eval $compile -if test -s conftest && ./conftest 2>/dev/null; then - echo "#define HAVE_personality" >> defines.h - echo "You have personality()" -else - echo "You don't have personality()" -fi -rm -f conftest conftest.c - -# -# 18. For pivot_root.c: does define __NR_pivot_root? +# 11. For pivot_root.c: does define __NR_pivot_root? # echo " #include @@ -426,7 +489,7 @@ fi rm -f conftest conftest.c # -# 19. For hwclock.c: does struct tm have a field tm_gmtoff? +# 12. For hwclock.c: does struct tm have a field tm_gmtoff? # echo " #include @@ -449,9 +512,15 @@ fi rm -f conftest conftest.c # -# 20. For nfsmount: does the output of rpcgen compile? +# 13. For nfsmount: does the output of rpcgen compile? +# +# On some systems the output of rpcgen compiles with warnings +# Here we conclude "Your rpcgen output does not compile" +# and use pregenerated files. If one wishes to use rpcgen anyway, +# just add the line "HAVE_GOOD_RPC=yes" to make_include. # rm -f conftest conftestx.c conftestl.c conftest.h conftest.x +rm -f conftestx.o conftestl.o echo " #ifdef RPC_CLNT %#include /* for memset() */ @@ -476,10 +545,10 @@ program MOUNTPROG { } = 2; } = 100005; " > conftest.x -if rpcgen -h -o conftest.h conftest.x && \ - rpcgen -c -o conftestx.c conftest.x && \ - rpcgen -l -o conftestl.c conftest.x && \ - cc -c conftestx.c 2> conferrs && cc -c conftestl.c 2>> conferrs && \ +if rpcgen -h -o conftest.h conftest.x 2> conferrs && \ + rpcgen -c -o conftestx.c conftest.x 2>> conferrs && \ + rpcgen -l -o conftestl.c conftest.x 2>> conferrs && \ + cc -c conftestx.c 2>> conferrs && cc -c conftestl.c 2>> conferrs && \ test ! -s conferrs then echo "HAVE_GOOD_RPC=yes" >> make_include @@ -488,3 +557,4 @@ else echo "Your rpcgen output does not compile" fi rm -f conftest conftestx.c conftestl.c conftest.h conftest.x conferrs +rm -f conftestx.o conftestl.o diff --git a/disk-utils/Makefile b/disk-utils/Makefile index ab9237c88..af15ee410 100644 --- a/disk-utils/Makefile +++ b/disk-utils/Makefile @@ -8,16 +8,17 @@ include ../MCONFIG # Where to put man pages? -MAN8= fdformat.8 mkfs.8 mkswap.8 elvtune.8 fsck.minix.8 mkfs.minix.8 mkfs.bfs.8 +MAN8= blockdev.8 fdformat.8 isosize.8 mkfs.8 mkswap.8 elvtune.8 \ + fsck.minix.8 mkfs.minix.8 mkfs.bfs.8 # Where to put binaries? # See the "install" rule for the links. . . -SBIN= mkfs mkswap blockdev elvtune fsck.minix mkfs.minix mkfs.bfs +SBIN= mkfs mkswap blockdev elvtune fsck.minix mkfs.minix mkfs.bfs -USRBIN= fdformat +USRBIN= fdformat isosize -ETC= fdprm +ETC= fdprm ifneq "$(HAVE_FDUTILS)" "yes" USRBIN:=$(USRBIN) setfdprm @@ -47,4 +48,4 @@ endif .PHONY: clean clean: - -rm -f *.o *~ core $(SBIN) $(USRBIN) + -rm -f *.o *~ core $(SBIN) $(USRBIN) raw diff --git a/disk-utils/blockdev.8 b/disk-utils/blockdev.8 new file mode 100644 index 000000000..bde64265f --- /dev/null +++ b/disk-utils/blockdev.8 @@ -0,0 +1,55 @@ +.\" -*- nroff -*- +.\" Copyright 1998 Andries E. Brouwer (aeb@cwi.nl) +.\" +.\" May be distributed under the GNU General Public License +.TH BLOCKDEV 8 "May 2000" "" +.SH NAME +blockdev \- call block device ioctls from the command line +.SH SYNOPSIS +.B blockdev +.RI [ options ] +.I commands devices +.SH DESCRIPTION +The utility +.B blockdev +allows one to call block device ioctls from the command line. +.SH OPTIONS +.TP +.B \-V +Print version and exit. +.TP +.B \-q +Be quiet. +.TP +.B \-v +Be verbose. +.SH COMMANDS +.TP +.B \--setro +Set read-only. +.TP +.B \--setrw +Set read-write. +.TP +.B \--getro +Get read-only. Print 1 if the device is read-only, 0 otherwise. +.TP +.B \--getss +Print sectorsize in bytes - usually 512. +.TP +.B \--getsize +Print device capacity (in 512-byte sectors). +.TP +.BI \--setra " N" +Set readahead to +.I N +512-byte sectors. +.TP +.B \--getra +Print readahead (in 512-byte sectors). +.TP +.B \--flushbufs +Flush buffers. +.TP +.B \--rereadpt +Reread partition table. diff --git a/disk-utils/elvtune.c b/disk-utils/elvtune.c index 00640fede..75ab57c0e 100644 --- a/disk-utils/elvtune.c +++ b/disk-utils/elvtune.c @@ -26,28 +26,33 @@ #include #include #include - -#define BLKELVGET _IO(0x12,106)/* elevator get */ -#define BLKELVSET _IO(0x12,107)/* elevator set */ +#include "nls.h" /* this has to match with the kernel structure */ +/* current version for ac19 and 2.2.16 */ typedef struct blkelv_ioctl_arg_s { - void * queue_ID; + int queue_ID; int read_latency; int write_latency; int max_bomb_segments; } blkelv_ioctl_arg_t; +#define BLKELVGET _IOR(0x12,106,sizeof(blkelv_ioctl_arg_t)) +#define BLKELVSET _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t)) + static void usage(void) { - fprintf(stderr, "usage:\n\telvtune [-r r_lat] [-w w_lat] [-b b_lat] /dev/blkdev1 [/dev/blkdev2...]\n"); + fprintf(stderr, "elvtune (%s)\n", util_linux_version); + fprintf(stderr, _("usage:\n")); + fprintf(stderr, "\telvtune [-r r_lat] [-w w_lat] [-b b_lat]" + " /dev/blkdev1 [/dev/blkdev2...]\n"); fprintf(stderr, "\telvtune -h\n"); fprintf(stderr, "\telvtune -v\n"); } static void version(void) { - fprintf(stderr, "elvtune: version 1.0\n"); + fprintf(stderr, "elvtune (%s)\n", util_linux_version); } int @@ -128,7 +133,7 @@ main(int argc, char * argv[]) { } } - printf("\n%s elevator ID %p\n", devname, elevator.queue_ID); + printf("\n%s elevator ID\t\t%d\n", devname, elevator.queue_ID); printf("\tread_latency:\t\t%d\n", elevator.read_latency); printf("\twrite_latency:\t\t%d\n", elevator.write_latency); printf("\tmax_bomb_segments:\t%d\n\n", elevator.max_bomb_segments); diff --git a/disk-utils/fdformat.c b/disk-utils/fdformat.c index 0251e3440..b4aec0076 100644 --- a/disk-utils/fdformat.c +++ b/disk-utils/fdformat.c @@ -1,4 +1,4 @@ -/* fdformat.c - Low-level formats a floppy disk. */ +/* fdformat.c - Low-level formats a floppy disk - Werner Almesberger */ /* 1999-02-22 Arkadiusz Mi¶kiewicz * - added Native Language Support @@ -135,11 +135,11 @@ int main(int argc,char **argv) exit(1); } if (access(argv[1],W_OK) < 0) PERROR(argv[1]); - if ((ctrl = open(argv[1],3)) < 0) PERROR(argv[1]); + if ((ctrl = open(argv[1],O_WRONLY)) < 0) PERROR(argv[1]); if (ioctl(ctrl,FDGETPRM,(long) ¶m) < 0) PERROR(_("Could not determine current format type")); printf(_("%s-sided, %d tracks, %d sec/track. Total capacity %d kB.\n"), - param.head ? _("Double") : _("Single"), + (param.head == 2) ? _("Double") : _("Single"), param.track, param.sect,param.size >> 1); format_disk(argv[1]); if (verify) verify_disk(argv[1]); diff --git a/disk-utils/isosize.8 b/disk-utils/isosize.8 new file mode 100644 index 000000000..47ab71fc5 --- /dev/null +++ b/disk-utils/isosize.8 @@ -0,0 +1,29 @@ +.TH ISOSIZE "8" "December 2000" "sg3_utils-0.91" SG_UTILS +.SH NAME +isosize \- outputs the length of a iso9660 file system +.SH SYNOPSIS +.B isosize +[\fI-x\fR] [\fI-d \fR] \fI\fR... +.SH DESCRIPTION +.\" Add any additional description here +.PP +This command outputs the length of an iso9660 file system that +is contained in given file. That file may be a normal file or +a block device (e.g. /dev/hdd or /dev/sr0). In the absence of +any switches (or errors) it will output the size of the iso9660 +file system in bytes. This can now be a large number (> > 4 GB). +.TP +-x +output in humanly readable form the block count and the block +size. Output uses the term "sectors" for "blocks". +.TP +-d +only has affect when "-x" is not given. The number output (if no errors) +is the iso9660 file size in bytes divided by . So if is +the block size then the output number will be the block count. +.PP +The size of the file (or block device) holding a iso9660 file +system can be marginally larger than the actual size of the +iso9660 file system. One reason for this is that cd writers +are allowed to add "run out" sectors at the end of a iso9660 +image. diff --git a/disk-utils/isosize.c b/disk-utils/isosize.c new file mode 100644 index 000000000..bff45d923 --- /dev/null +++ b/disk-utils/isosize.c @@ -0,0 +1,218 @@ +/* + * isosize.c - Andries Brouwer, 000608 + * + * use header info to find size of iso9660 file system + * output a number - useful in scripts + * + * Synopsis: + * isosize [-x] [-d ] + * where "-x" gives length in sectors and sector size while + * without this argument the size is given in bytes + * without "-x" gives length in bytes unless "-d " is + * given. In the latter case the length in bytes divided + * by is given + * + * Version 2.03 2000/12/21 + * - add "-d " option and use long long to fix things > 2 GB + * Version 2.02 2000/10/11 + * - error messages on IO failures [D. Gilbert] + * + */ +#include +#include +#include +#include +#include +#include + +#include "nls.h" + +#define ISODCL(from, to) (to - from + 1) + +int xflag; + +static int +isonum_721 (unsigned char * p) { + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8)); +} + +static int +isonum_722 (unsigned char * p) { + return ((p[1] & 0xff) + | ((p[0] & 0xff) << 8)); +} + +static int +isonum_723 (unsigned char * p) { + int le = isonum_721 (p); + int be = isonum_722 (p+2); + if (xflag && le != be) + /* translation is useless */ + fprintf(stderr, "723error: le=%d be=%d\n", le, be); + return (le); +} + +static int +isonum_731 (unsigned char * p) { + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +static int +isonum_732 (unsigned char * p) { + return ((p[3] & 0xff) + | ((p[2] & 0xff) << 8) + | ((p[1] & 0xff) << 16) + | ((p[0] & 0xff) << 24)); +} + + +static int +isonum_733 (unsigned char * p) { + int le = isonum_731 (p); + int be = isonum_732 (p+4); + if (xflag && le != be) + /* translation is useless */ + fprintf(stderr, "733error: le=%d be=%d\n", le, be); + return (le); +} + +struct iso_primary_descriptor { + unsigned char type [ISODCL ( 1, 1)]; /* 711 */ + unsigned char id [ISODCL ( 2, 6)]; + unsigned char version [ISODCL ( 7, 7)]; /* 711 */ + unsigned char unused1 [ISODCL ( 8, 8)]; + unsigned char system_id [ISODCL ( 9, 40)]; /* auchars */ + unsigned char volume_id [ISODCL ( 41, 72)]; /* duchars */ + unsigned char unused2 [ISODCL ( 73, 80)]; + unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + unsigned char unused3 [ISODCL ( 89, 120)]; + unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ + unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ + unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ + unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + unsigned char volume_set_id [ISODCL (191, 318)]; /* duchars */ + unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ + unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ + unsigned char application_id [ISODCL (575, 702)]; /* achars */ + unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ + unsigned char unused4 [ISODCL (883, 883)]; + unsigned char application_data [ISODCL (884, 1395)]; + unsigned char unused5 [ISODCL (1396, 2048)]; +}; + +const char *progname; +int divisor = 0; + +static void +isosize(char *filenamep) { + int fd, nsecs, ssize; + struct iso_primary_descriptor ipd; + + if ((fd = open(filenamep, O_RDONLY)) < 0) { + perror(filenamep); + fprintf(stderr, _("%s: failed to open: %s\n"), + progname, filenamep); + exit(1); + } + if (lseek(fd, 16 << 11, 0) == (off_t)-1) { + perror("lseek"); + fprintf(stderr, _("%s: seek error on %s\n"), + progname, filenamep); + exit(1); + } + if (read(fd, &ipd, sizeof(ipd)) < 0) { + perror("read"); + fprintf(stderr, _("%s: read error on %s\n"), + progname, filenamep); + exit(1); + } + + nsecs = isonum_733(ipd.volume_space_size); + ssize = isonum_723(ipd.logical_block_size); /* nowadays always 2048 */ + + if (xflag) { + printf (_("sector count: %d, sector size: %d\n"), + nsecs, ssize); + } else { + long long product = nsecs; + + if (divisor == 0) + printf ("%lld\n", product * ssize); + else if (divisor == ssize) + printf ("%d\n", nsecs); + else + printf ("%lld\n", (product * ssize) / divisor); + } +} + +int +main(int argc, char * argv[]) { + int j, ct; + char *p; + + progname = argv[0]; + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (argc >= 2 && + (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { + printf(_("%s from %s\n"), progname, util_linux_version); + exit(0); + } + + for (;;) { + int opt; + + opt = getopt(argc, argv, "xd:"); + if (opt < 0) + break; + switch (opt) { + case 'd': + divisor = atoi(optarg); + break; + case 'x': + xflag = 1; + break; + default: + fprintf(stderr, + _("%s: option parse error\n"), progname); + exit(1); + } + } + + ct = argc - optind; + + if (ct <= 0) { + fprintf(stderr, _("Usage: %s [-x] [-d ] iso9660-image\n"), + progname); + exit(1); + } + + for (j = optind; j < argc; j++) { + if (ct > 1) + printf("%s: ", argv[j]); + isosize(argv[j]); + } + + return 0; +} diff --git a/disk-utils/mkfs.bfs.c b/disk-utils/mkfs.bfs.c index a8f557837..b27fd2eb6 100644 --- a/disk-utils/mkfs.bfs.c +++ b/disk-utils/mkfs.bfs.c @@ -15,14 +15,13 @@ #include #include #include +#include "nls.h" /* cannot include */ #ifndef BLKGETSIZE #define BLKGETSIZE _IO(0x12,96) /* return device size */ #endif -#include "../defines.h" /* for util_linux_version */ - #define BFS_ROOT_INO 2 #define BFS_NAMELEN 14 #define BFS_BLOCKSIZE 512 @@ -85,9 +84,9 @@ fatal(char *s, ...) { static void usage(void) { - fprintf(stderr, + fprintf(stderr, _( "Usage: %s [-v] [-N nr-of-inodes] [-V volume-name]\n" - " [-F fsname] device [block-count]\n", + " [-F fsname] device [block-count]\n"), progname); exit(1); } @@ -117,7 +116,7 @@ main(int argc, char *argv[]) { if (argc == 2 && (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { - printf("%s from %s\n", progname, util_linux_version); + printf(_("%s from %s\n"), progname, util_linux_version); exit(0); } @@ -133,14 +132,14 @@ main(int argc, char *argv[]) { case 'V': len = strlen(optarg); if (len <= 0 || len > 6) - fatal("volume name too long"); + fatal(_("volume name too long")); volume = strdup(optarg); break; case 'F': len = strlen(optarg); if (len <= 0 || len > 6) - fatal("fsname name too long"); + fatal(_("fsname name too long")); fsname = strdup(optarg); break; @@ -165,16 +164,16 @@ main(int argc, char *argv[]) { if (stat(device, &statbuf) == -1) { perror(device); - fatal("cannot stat device %s", device); + fatal(_("cannot stat device %s"), device); } if (!S_ISBLK(statbuf.st_mode)) - fatal("%s is not a block special device", device); + fatal(_("%s is not a block special device"), device); fd = open(device, O_RDWR); if (fd == -1) { perror(device); - fatal("cannot open %s", device); + fatal(_("cannot open %s"), device); } if (optind == argc-1) @@ -185,12 +184,12 @@ main(int argc, char *argv[]) { if (ioctl(fd, BLKGETSIZE, &total_blocks) == -1) { if (!user_specified_total_blocks) { perror("BLKGETSIZE"); - fatal("cannot get size of %s", device); + fatal(_("cannot get size of %s"), device); } total_blocks = user_specified_total_blocks; } else if (user_specified_total_blocks) { if (user_specified_total_blocks > total_blocks) - fatal("blocks argument too large, max is %d", + fatal(_("blocks argument too large, max is %lu"), total_blocks); total_blocks = user_specified_total_blocks; } @@ -205,7 +204,7 @@ main(int argc, char *argv[]) { } else { /* believe the user */ if (inodes > 512) - fatal("too many inodes - max is 512"); + fatal(_("too many inodes - max is 512")); } ino_bytes = inodes * sizeof(struct bfsi); @@ -214,7 +213,7 @@ main(int argc, char *argv[]) { /* mimic the behaviour of SCO's mkfs - maybe this limit is needed */ if (data_blocks < 32) - fatal("not enough space, need at least %d blocks", + fatal(_("not enough space, need at least %lu blocks"), ino_blocks + 33); memset(&sb, 0, sizeof(sb)); @@ -226,19 +225,23 @@ main(int argc, char *argv[]) { memcpy(sb.s_volume, volume, 6); if (verbose) { - fprintf(stderr, "Device: %s\n", device); - fprintf(stderr, "Volume: <%-6s>\n", volume); - fprintf(stderr, "FSname: <%-6s>\n", fsname); - fprintf(stderr, "BlockSize: %d\n", BFS_BLOCKSIZE); - fprintf(stderr, "Inodes: %d (in %ld block%s)\n", - inodes, ino_blocks, (ino_blocks==1) ? "" : "s"); - fprintf(stderr, "Blocks: %ld\n", total_blocks); - fprintf(stderr, "Inode end: %d, Data end: %d\n", + fprintf(stderr, _("Device: %s\n"), device); + fprintf(stderr, _("Volume: <%-6s>\n"), volume); + fprintf(stderr, _("FSname: <%-6s>\n"), fsname); + fprintf(stderr, _("BlockSize: %d\n"), BFS_BLOCKSIZE); + if (ino_blocks==1) + fprintf(stderr, _("Inodes: %d (in 1 block)\n"), + inodes); + else + fprintf(stderr, _("Inodes: %d (in %ld blocks)\n"), + inodes, ino_blocks); + fprintf(stderr, _("Blocks: %ld\n"), total_blocks); + fprintf(stderr, _("Inode end: %d, Data end: %d\n"), sb.s_start-1, sb.s_end); } if (write(fd, &sb, sizeof(sb)) != sizeof(sb)) - fatal("error writing superblock"); + fatal(_("error writing superblock")); memset(&ri, 0, sizeof(ri)); ri.i_ino = BFS_ROOT_INO; @@ -258,29 +261,29 @@ main(int argc, char *argv[]) { ri.i_ctime = now; if (write(fd, &ri, sizeof(ri)) != sizeof(ri)) - fatal("error writing root inode"); + fatal(_("error writing root inode")); memset(&ri, 0, sizeof(ri)); for (i=1; i /* for _IO */ #include #include +#include "nls.h" + +#ifdef HAVE_asm_page_h #include /* for PAGE_SIZE and PAGE_SHIFT */ /* we also get PAGE_SIZE via getpagesize() */ -#include "nls.h" +/* recent glibc systems also define this in */ +#endif + #ifndef _IO /* pre-1.3.45 */ @@ -609,7 +614,9 @@ the -f option to force it.\n"), * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) */ +#ifdef HAVE_fsync if (fsync(DEV)) die(_("fsync failed")); +#endif return 0; } diff --git a/disk-utils/raw.c b/disk-utils/raw.c index 54e1008cb..4fc5e2470 100644 --- a/disk-utils/raw.c +++ b/disk-utils/raw.c @@ -161,6 +161,7 @@ int main(int argc, char *argv[]) break; default: + block_major = block_minor = 0; /* just to keep gcc happy */ usage(1); } diff --git a/disk-utils/setfdprm.c b/disk-utils/setfdprm.c index 73b3b7174..958f98c16 100644 --- a/disk-utils/setfdprm.c +++ b/disk-utils/setfdprm.c @@ -20,28 +20,29 @@ #define MAXLINE 200 -static int convert(char *arg) -{ +static int +convert(char *arg) { long result; char *end; result = strtol(arg,&end,0); - if (!*end) return (int) result; + if (!*end) + return (int) result; fprintf(stderr,_("Invalid number: %s\n"),arg); exit(1); } - -static void cmd_without_param(int cmd,int fd) -{ - if (ioctl(fd,cmd,NULL) >= 0) exit(0); +static void +cmd_without_param(int cmd,int fd) { + if (ioctl(fd,cmd,NULL) >= 0) + exit(0); perror("ioctl"); exit(1); } - -static void set_params(int cmd,int fd,char **params) -{ +/* set given fd parameters */ +static void +set_params(int cmd,int fd,char **params) { struct floppy_struct ft; ft.size = convert(params[0]); @@ -59,9 +60,9 @@ static void set_params(int cmd,int fd,char **params) exit(1); } - -static void find_params(int cmd,int fd,char *name) -{ +/* find parameter set in file, and use it */ +static void +find_params(int cmd,int fd,char *name) { FILE *file; char line[MAXLINE+2],this[MAXLINE+2],param[9][MAXLINE+2]; char *params[9],*start; @@ -91,9 +92,8 @@ static void find_params(int cmd,int fd,char *name) exit(1); } - -static void usage(char *name) -{ +static void +usage(char *name) { char *this; if ((this = strrchr(name,'/')) != NULL) name = this+1; @@ -109,8 +109,7 @@ gap rate spec1 fmt_gap\n"),name); } int -main(int argc, char **argv) -{ +main(int argc, char **argv) { int fd; unsigned int cmd; char *progname, *p; @@ -129,7 +128,8 @@ main(int argc, char **argv) exit(0); } - if (argc < 3) usage(progname); + if (argc < 2) + usage(progname); cmd = FDSETPRM; if (*argv[1] == '-') { switch (argv[1][1]) { @@ -156,7 +156,7 @@ main(int argc, char **argv) argc--; argv++; } - if ((fd = open(argv[1],3)) < 0) { /* 3 == no access at all */ + if ((fd = open(argv[1],3)) < 0) { /* O_WRONLY needed in a few kernels */ perror(argv[1]); exit(1); } diff --git a/fdisk/Makefile b/fdisk/Makefile index a319c2baf..3a851fa02 100644 --- a/fdisk/Makefile +++ b/fdisk/Makefile @@ -18,12 +18,13 @@ NOTMADE=cfdisk endif endif -ifeq "$(CPU)" "m68k" +ifeq "$(ARCH)" "m68k" # It seems the m68k people do not want *fdisk else SBIN:=$(SBIN) fdisk MAN8:=$(MAN8) fdisk.8 -ifneq "$(CPU)" "sparc" + +ifneq "$(ARCH)" "sparc" SBIN:=$(SBIN) $(CFDISK) sfdisk MAN8:=$(MAN8) cfdisk.8 sfdisk.8 endif diff --git a/fdisk/common.h b/fdisk/common.h index c5e237148..86802c41e 100644 --- a/fdisk/common.h +++ b/fdisk/common.h @@ -5,6 +5,7 @@ #define BLKRRPART _IO(0x12,95) /* re-read partition table */ #define BLKGETSIZE _IO(0x12,96) /* return device size */ #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ +#define BLKSSZGET _IO(0x12,104) /* get block device sector size */ struct systypes { unsigned char type; diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 45110ccd6..969bf8790 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -57,6 +57,8 @@ #include #endif +static void delete_partition(int i); + #define hex_val(c) ({ \ char _c = (c); \ isdigit(_c) ? _c - '0' : \ @@ -176,6 +178,7 @@ uint heads, sectors, cylinders, sector_size = DEFAULT_SECTOR_SIZE, + user_set_sector_size = 0, sector_offset = 1, units_per_sector = 1, display_in_cyl_units = 1, @@ -567,13 +570,13 @@ void update_units(void) static void warn_cylinders(void) { if (dos_label && cylinders > 1024 && !nowarn) - fprintf(stderr, "\n\ -The number of cylinders for this disk is set to %d.\n\ -There is nothing wrong with that, but this is larger than 1024,\n\ -and could in certain setups cause problems with:\n\ -1) software that runs at boot time (e.g., old versions of LILO)\n\ -2) booting and partitioning software from other OSs\n\ - (e.g., DOS FDISK, OS/2 FDISK)\n", + fprintf(stderr, _("\n" +"The number of cylinders for this disk is set to %d.\n" +"There is nothing wrong with that, but this is larger than 1024,\n" +"and could in certain setups cause problems with:\n" +"1) software that runs at boot time (e.g., old versions of LILO)\n" +"2) booting and partitioning software from other OSs\n" +" (e.g., DOS FDISK, OS/2 FDISK)\n"), cylinders); } @@ -588,9 +591,13 @@ read_extended(int ext) { pex->ext_pointer = pex->part_table; p = pex->part_table; - if (!get_start_sect(p)) - fprintf(stderr, _("Bad offset in primary extended partition\n")); - else while (IS_EXTENDED (p->sys_ind)) { + if (!get_start_sect(p)) { + fprintf(stderr, + _("Bad offset in primary extended partition\n")); + return; + } + + while (IS_EXTENDED (p->sys_ind)) { struct pte *pe = &ptes[partitions]; if (partitions >= MAXIMUM_PARTS) { @@ -613,7 +620,7 @@ read_extended(int ext) { extended_offset = get_start_sect(p); q = p = pt_offset(pe->sectorbuffer, 0); - for (i = 0; i < 4; i++, p++) { + for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) { if (IS_EXTENDED (p->sys_ind)) { if (pe->ext_pointer) fprintf(stderr, _("Warning: extra link" @@ -649,6 +656,18 @@ read_extended(int ext) { p = pe->ext_pointer; partitions++; } + + /* remove empty links */ + remove: + for (i = 4; i < partitions; i++) { + struct pte *pe = &ptes[i]; + + if (!get_nr_sects(pe->part_table)) { + printf("omitting empty partition (%d)\n", i+1); + delete_partition(i); + goto remove; /* numbering changed */ + } + } } static void @@ -672,19 +691,39 @@ create_doslabel(void) { get_boot(create_empty); } +#include +#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) + +static int +linux_version_code(void) { + static int kernel_version = 0; + struct utsname my_utsname; + int p, q, r; + + if (!kernel_version && uname(&my_utsname) == 0) { + p = atoi(strtok(my_utsname.release, ".")); + q = atoi(strtok(NULL, ".")); + r = atoi(strtok(NULL, ".")); + kernel_version = MAKE_VERSION(p,q,r); + } + return kernel_version; +} + static void get_sectorsize(int fd) { -#if defined(BLKSSZGET) && defined(HAVE_blkpg_h) - /* For a short while BLKSSZGET gave a wrong sector size */ - { int arg; - if (ioctl(fd, BLKSSZGET, &arg) == 0) - sector_size = arg; - if (sector_size != DEFAULT_SECTOR_SIZE) - printf(_("Note: sector size is %d (not %d)\n"), - sector_size, DEFAULT_SECTOR_SIZE); +#if defined(BLKSSZGET) + if (!user_set_sector_size && + linux_version_code() >= MAKE_VERSION(2,3,3)) { + int arg; + if (ioctl(fd, BLKSSZGET, &arg) == 0) + sector_size = arg; + if (sector_size != DEFAULT_SECTOR_SIZE) + printf(_("Note: sector size is %d (not %d)\n"), + sector_size, DEFAULT_SECTOR_SIZE); } #else - sector_size = DEFAULT_SECTOR_SIZE; + /* maybe the user specified it; and otherwise we still + have the DEFAULT_SECTOR_SIZE default */ #endif } @@ -818,9 +857,9 @@ got_table: pe->part_table = pt_offset(MBRbuffer, i); pe->ext_pointer = NULL; - pe->changed = 0; pe->offset = 0; pe->sectorbuffer = MBRbuffer; + pe->changed = (what == create_empty); } for (i = 0; i < 4; i++) { @@ -877,6 +916,7 @@ read_char(char *mesg) { do { fputs(mesg, stdout); + fflush (stdout); /* requested by niles@scyld.com */ } while (!read_line()); return *line_ptr; } @@ -885,6 +925,7 @@ char read_chars(char *mesg) { fputs(mesg, stdout); + fflush (stdout); /* niles@scyld.com */ if (!read_line()) { *line_ptr = '\n'; line_ptr[1] = 0; @@ -1079,10 +1120,12 @@ delete_partition(int i) { sun_delete_partition(i); return; } + if (sgi_label) { sgi_delete_partition(i); return; } + if (i < 4) { if (IS_EXTENDED (p->sys_ind) && i == ext_index) { partitions = 4; @@ -1090,14 +1133,15 @@ delete_partition(int i) { extended_offset = 0; } clear_partition(p); + return; } - else if (!q->sys_ind && i > 4) { + + if (!q->sys_ind && i > 4) { --partitions; --i; clear_partition(ptes[i].ext_pointer); ptes[i].changed = 1; - } - else if (i > 3) { + } else { if (i > 4) { p = ptes[i-1].ext_pointer; p->boot_ind = 0; @@ -1111,7 +1155,7 @@ delete_partition(int i) { set_start_sect(p, get_start_sect(q)); set_nr_sects(p, get_nr_sects(q)); ptes[i-1].changed = 1; - } else { + } else if (partitions > 5) { /* 5 will be moved to 4 */ struct pte *pe = &ptes[5]; if(pe->part_table) /* prevent SEGFAULT */ @@ -1121,6 +1165,7 @@ delete_partition(int i) { pe->offset = extended_offset; pe->changed = 1; } + if (partitions > 5) { partitions--; while (i < partitions) { @@ -1389,7 +1434,7 @@ list_table(int xtra) { struct pte *pe = &ptes[i]; p = pe->part_table; - if (p->sys_ind) { + if (p && p->sys_ind) { unsigned int psects = get_nr_sects(p); unsigned int pblocks = psects; unsigned int podd = 0; @@ -2030,6 +2075,8 @@ try(char *device, int user_specified) { if ((fd = open(disk_device, type_open)) >= 0) { if (get_boot(try_only) < 0) { list_disk_geometry(); + if (aix_label) + return; if (btrydev(device) < 0) fprintf(stderr, _("Disk %s doesn't contain a valid " @@ -2075,7 +2122,7 @@ tryprocpt(void) { if (isdigit(s[-1])) continue; sprintf(devname, "/dev/%s", ptname); - try(devname, 1); + try(devname, 0); } } @@ -2091,7 +2138,6 @@ int main(int argc, char **argv) { int j, c; int optl = 0, opts = 0; - int user_set_sector_size = 0; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); @@ -2194,6 +2240,8 @@ main(int argc, char **argv) { fatal(usage2); get_boot(fdisk); + if (aix_label) + exit(0); #ifdef __alpha__ /* On alpha, if we detect a disklabel, go directly to diff --git a/fdisk/fdiskbsdlabel.h b/fdisk/fdiskbsdlabel.h index 68747d48e..e46e02614 100644 --- a/fdisk/fdiskbsdlabel.h +++ b/fdisk/fdiskbsdlabel.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -#include /* for __u32 etc */ +#include /* for __u32, __u16, __u8, __s16 */ #ifndef BSD_DISKMAGIC /* perhaps from */ #define BSD_DISKMAGIC ((__u32) 0x82564557) diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c index 3ec5624a1..f96cb0b15 100644 --- a/fdisk/fdisksunlabel.c +++ b/fdisk/fdisksunlabel.c @@ -67,6 +67,12 @@ get_num_sectors(struct sun_partition p) { return SSWAP32(p.num_sectors); } +#ifndef IDE0_MAJOR +#define IDE0_MAJOR 3 +#endif +#ifndef IDE1_MAJOR +#define IDE1_MAJOR 22 +#endif void guess_device_type(int fd) { struct stat bootstat; diff --git a/fdisk/fdisksunlabel.h b/fdisk/fdisksunlabel.h index 424f462ea..647a2cec1 100644 --- a/fdisk/fdisksunlabel.h +++ b/fdisk/fdisksunlabel.h @@ -1,4 +1,4 @@ -#include /* for __u32 etc */ +#include /* for __u16, __u32 */ typedef struct { unsigned char info[128]; /* Informative text string */ diff --git a/fdisk/i386_sys_types.c b/fdisk/i386_sys_types.c index 0cad6fa72..3e5f0f1b7 100644 --- a/fdisk/i386_sys_types.c +++ b/fdisk/i386_sys_types.c @@ -29,6 +29,7 @@ struct systypes i386_sys_types[] = { {0x1c, N_("Hidden Win95 FAT32 (LBA)")}, {0x1e, N_("Hidden Win95 FAT16 (LBA)")}, {0x24, N_("NEC DOS")}, + {0x39, N_("Plan 9")}, {0x3c, N_("PartitionMagic recovery")}, {0x40, N_("Venix 80286")}, {0x41, N_("PPC PReP Boot")}, @@ -72,16 +73,21 @@ struct systypes i386_sys_types[] = { {0xc4, N_("DRDOS/sec (FAT-16 < 32M)")}, {0xc6, N_("DRDOS/sec (FAT-16)")}, {0xc7, N_("Syrinx")}, - {0xdb, N_("CP/M / CTOS / ...")},/* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */ - {0xe1, N_("DOS access")}, /* DOS access or SpeedStor 12-bit FAT extended partition */ + {0xda, N_("Non-FS data")}, + {0xdb, N_("CP/M / CTOS / ...")},/* CP/M or Concurrent CP/M or + Concurrent DOS or CTOS */ + {0xe1, N_("DOS access")}, /* DOS access or SpeedStor 12-bit FAT + extended partition */ {0xe3, N_("DOS R/O")}, /* DOS R/O or SpeedStor */ - {0xe4, N_("SpeedStor")}, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */ + {0xe4, N_("SpeedStor")}, /* SpeedStor 16-bit FAT extended + partition < 1024 cyl. */ {0xeb, N_("BeOS fs")}, {0xf1, N_("SpeedStor")}, {0xf4, N_("SpeedStor")}, /* SpeedStor large partition */ {0xf2, N_("DOS secondary")}, /* DOS 3.3+ secondary */ - {0xfd, N_("Linux raid autodetect")},/* New (2.2.x) raid partition with autodetect - using persistent superblock */ + {0xfd, N_("Linux raid autodetect")},/* New (2.2.x) raid partition with + autodetect using persistent + superblock */ {0xfe, N_("LANstep")}, /* SpeedStor >1024 cyl. or LANstep */ {0xff, N_("BBT")}, /* Xenix Bad Block Table */ { 0, 0 } diff --git a/fdisk/llseek.c b/fdisk/llseek.c index 9e00d3e6d..b55dfa792 100644 --- a/fdisk/llseek.c +++ b/fdisk/llseek.c @@ -35,10 +35,24 @@ extern ext2_loff_t ext2_llseek (unsigned int, ext2_loff_t, unsigned int); static int _llseek (unsigned int, unsigned long, unsigned long, ext2_loff_t *, unsigned int); +#ifdef __NR__llseek + static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high, unsigned long, offset_low,ext2_loff_t *,result, unsigned int, origin) +#else + +/* no __NR__llseek on compilation machine - might give it explicitly */ +static int _llseek (unsigned int fd, unsigned long oh, + unsigned long ol, ext2_loff_t *result, + unsigned int origin) { + errno = ENOSYS; + return -1; +} + +#endif + static ext2_loff_t my_llseek (unsigned int fd, ext2_loff_t offset, unsigned int origin) { diff --git a/fdisk/sfdisk.c b/fdisk/sfdisk.c index 206ea28dc..e60259849 100644 --- a/fdisk/sfdisk.c +++ b/fdisk/sfdisk.c @@ -432,25 +432,25 @@ get_cylindersize(char *dev, int fd, int silent) { if (R.start && !force) { warn( - _("Warning: start=%d - this looks like a partition rather than\n" + _("Warning: start=%lu - this looks like a partition rather than\n" "the entire disk. Using fdisk on it is probably meaningless.\n" "[Use the --force option if you really want this]\n"), R.start); exit(1); } if (R.heads && B.heads != R.heads) - warn(_("Warning: HDIO_GETGEO says that there are %d heads\n"), + warn(_("Warning: HDIO_GETGEO says that there are %lu heads\n"), R.heads); if (R.sectors && B.sectors != R.sectors) - warn(_("Warning: HDIO_GETGEO says that there are %d sectors\n"), + warn(_("Warning: HDIO_GETGEO says that there are %lu sectors\n"), R.sectors); if (R.cylinders && B.cylinders != R.cylinders && B.cylinders < 65536 && R.cylinders < 65536) - warn(_("Warning: BLKGETSIZE/HDIO_GETGEO says that there are %d cylinders\n"), + warn(_("Warning: BLKGETSIZE/HDIO_GETGEO says that there are %lu cylinders\n"), R.cylinders); if (B.sectors > 63) - warn(_("Warning: unlikely number of sectors (%d) - usually at most 63\n" + warn(_("Warning: unlikely number of sectors (%lu) - usually at most 63\n" "This will give problems with all software that uses C/H/S addressing.\n"), B.sectors); if (!silent) @@ -537,17 +537,17 @@ chs_ok (chs a, char *v, char *w) { return 1; if (B.heads && aa.h >= B.heads) { warn(_("%s of partition %s has impossible value for head: " - "%d (should be in 0-%d)\n"), w, v, aa.h, B.heads-1); + "%lu (should be in 0-%lu)\n"), w, v, aa.h, B.heads-1); ret = 0; } if (B.sectors && (aa.s == 0 || aa.s > B.sectors)) { warn(_("%s of partition %s has impossible value for sector: " - "%d (should be in 1-%d)\n"), w, v, aa.s, B.sectors); + "%lu (should be in 1-%lu)\n"), w, v, aa.s, B.sectors); ret = 0; } if (B.cylinders && aa.c >= B.cylinders) { warn(_("%s of partition %s has impossible value for cylinders: " - "%d (should be in 0-%d)\n"), w, v, aa.c, B.cylinders-1); + "%lu (should be in 0-%lu)\n"), w, v, aa.c, B.cylinders-1); ret = 0; } return ret; @@ -2774,7 +2774,7 @@ do_change_id(char *dev, char *pnam, char *id) { } i = strtoul(id, NULL, 16); if (i > 255) - fatal(_("Bad Id %x\n"), i); + fatal(_("Bad Id %lx\n"), i); z->partitions[pno].p.sys_type = i; if(write_partitions(dev, fd, z)) diff --git a/getopt-1.0.3b/COPYING b/getopt-1.0.3b/COPYING deleted file mode 100644 index a43ea2126..000000000 --- a/getopt-1.0.3b/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/getopt-1.0.3b/Changelog b/getopt-1.0.3b/Changelog deleted file mode 100644 index 24a4c3235..000000000 --- a/getopt-1.0.3b/Changelog +++ /dev/null @@ -1,14 +0,0 @@ -980628: Bumped up version number to 1.0.3 -980628: Removed remaining incompatibility with tcsh-6.02 from parse.tcsh -980626: Added separate Makefile for util-linux -980625: Removed several bugs from parse.tcsh, partly thanks to Volker Kuhlmann - (v.kuhlmann@elec.canterbury.ac.nz). -980612: Removed reference to getopt in util-linux -980611: Bumped up version number to 1.0.2 -980611: Fixed --version bug (was not available, though documented!) -980611: Removed compiler warnings. -980603: Bumped up version number to 1.0.1 -980603: Fixed sizeof() bug (should be strlen) in getopt.c, thanks to Bob Proulx - (rwp@hprwp.fc.hp.com). -980505: Changed date field in LSM to proper syntax -980505: Released version 1.0 diff --git a/getopt-1.0.3b/Makefile b/getopt-1.0.3b/Makefile deleted file mode 100644 index 92e99e9de..000000000 --- a/getopt-1.0.3b/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -.SUFFIXES: - -include ../make_include -include ../MCONFIG - -GETOPTDIR=$(USRLIBDIR)/getopt - -# Define this to 0 to use the getopt(3) routines in this package. -LIBCGETOPT=1 - -SHELL=/bin/sh - -LD=ld -RM=rm -f -INSTALL=install - -CPPFLAGS=-DLIBCGETOPT=$(LIBCGETOPT) -ifeq ($(LIBCGETOPT),0) -CPPFLAGS+=-I./gnu -endif - -# -Wcast-align causes problems with the identifier stderr on alpha's -# with an old glibc. -# -Wbad-function-cast and -Wmissing-declarations are unknown for gcc 2.5.8. -WARNINGS=-Wall \ - -W -Wshadow -Wpointer-arith -Wcast-qual \ - -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ - -Wnested-externs -Winline -CFLAGS=$(WARNINGS) $(OPT) - -SOURCES=getopt.c -ifeq ($(LIBCGETOPT),0) -SOURCES+=gnu/getopt.c gnu/getopt1.c -endif - -OBJECTS=$(SOURCES:.c=.o) - -BINARIES=getopt - -.PHONY: all clean realclean -all: $(BINARIES) - -clean: - -$(RM) $(OBJECTS) $(BINARIES) - -getopt: $(OBJECTS) - $(CC) $(LDFLAGS) $< -o $@ - -install: getopt - $(INSTALLDIR) $(USRBINDIR) $(MAN1DIR) $(GETOPTDIR) - $(INSTALLBIN) getopt $(USRBINDIR) - $(INSTALLMAN) getopt.1 $(MAN1DIR) - $(INSTALLBIN) parse.bash parse.tcsh test.bash test.tcsh $(GETOPTDIR) diff --git a/getopt-1.0.3b/README b/getopt-1.0.3b/README deleted file mode 100644 index 1d795f5e4..000000000 --- a/getopt-1.0.3b/README +++ /dev/null @@ -1,80 +0,0 @@ -This package contains a reimplementation of getopt(1). - -PREFACE - -Getopt(1) is a program to help shell scripts parse command-line parameters. -It is for example included in the util-linux distribution (upto version -2.7.1). But, there are some problems with that getopt(1) implementation, -as listed in the 'BUGS' section of its man-page: - ->BUGS -> Whatever getopt(3) has. -> -> Arguments containing white space or imbedded shell metacharacters gener- -> ally will not survive intact; this looks easy to fix but isn't. -> -> The error message for an invalid option is identified as coming from -> getopt rather than from the shell procedure containing the invocation of -> getopt; this again is hard to fix. -> -> The precise best way to use the set command to set the arguments without -> disrupting the value(s) of shell options varies from one shell version to -> another. - -This implementation of getopt(1) is written to solve some of these problems, -while still staying (for all practical purposes) completely compatible with -other getopt(1) implementations. - - -INSTALLATION - -Installation should be very easy. Just type 'make' to compile the sources. -It should compile cleanly, without any warnings, but even if it does not -you probably don't have to worry. You must use GNU Make and gcc, or you -will have to edit the Makefile. - -Type 'make install' to install the binary and the manual page. It installs -by default in /usr/local/bin and /usr/local/man/man1, to install in /usr/bin -and /usr/man/man1 try 'make install prefix=/usr'. - -The example files can be installed in /usr/local/lib/getopt by calling -'make install_doc'. - -If you do not trust the getopt(3) in your libc, or if you do not use a libc -with the GNU getopt(3) routines, you can use the gnu sources as provided -in the gnu directory. Try 'make LIBCGETOPT=0'. Ignore any compile warnings. - -You can check whether the new implementation of getopt is found first -in your path by calling 'bash test.bash'. - - -HIGHLIGHTS - -It can do anything that the GNU getopt(3) routines can do. - -It can cope with spaces and shell metacharacters within arguments. - -It can parse long parameters. - -It can shuffle parameters, so you can mix options and other parameters on -the command-line. - -It can be easily identified as an enhanced getopt(1) from within shell scripts. - -It can report parse errors as coming from the shell script. - -It is fully compatible with other getopt(1) implementations. - -COPYING - -This program comes under the GNU general public licence version 2. See the -file COPYING included in this package. Note that though you may freely -copy it, it is copyright (c) 1997 by Frodo Looijaard . -Files in the gnu directory are from glibc-2.0.4: copyright (C) 1987, 88, -89, 90, 91, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. - - -DOWNLOADING - -You can find the latest version of this program at -. diff --git a/getopt-1.0.3b/TODO b/getopt-1.0.3b/TODO deleted file mode 100644 index 70f2ea9cb..000000000 --- a/getopt-1.0.3b/TODO +++ /dev/null @@ -1,6 +0,0 @@ -Other shells, like zsh and ash, should be supported (perhaps they will work -already, depending on quoting conventions). (zsh seems OK). - -Perhaps a nice configure script? - -Add a `test' target in Makefile. diff --git a/getopt-1.0.3b/getopt.1 b/getopt-1.0.3b/getopt.1 deleted file mode 100644 index c3aaa0195..000000000 --- a/getopt-1.0.3b/getopt.1 +++ /dev/null @@ -1,436 +0,0 @@ -.TH GETOPT 1 "May 31, 1997" Linux "" -.SH NAME -getopt \- parse command options (enhanced) -.SH SYNOPSIS -.BR getopt " optstring parameters" - -.BR getopt " [options] [" -- "] optstring parameters" - -.BR getopt " [options] " -o | --options " optstring [options] [" -- "] parameters" -.SH DESCRIPTION -.B getopt -is used to break up -.RI ( parse ) -options in command lines for easy parsing by -shell procedures, and to check for legal options. -It uses the -.SM GNU -.BR getopt (3) -routines to do this. - -The parameters -.B getopt -is called with can be divided into two parts: options -which modify the way getopt will parse -.RI ( options -and -.I -o|--options optstring -in the -.BR SYNOPSIS), -and the parameters which are to be -parsed -.RI ( parameters -in the -.BR SYNOPSIS). -The second part will start at the first non-option parameter -that is not an option argument, or after the first occurence of -.RB ` -- '. -If no -.RB ` -o ' -or -.RB ` --options ' -option is found in the first part, the first -parameter of the second part is used as the short options string. - -If the environment variable -.B GETOPT_COMPATIBLE -is set, or if its first parameter -is not an option (does not start with a -.RB ` - ', -this is the first format in the -.BR SYNOPSIS), -.B getopt -will generate output that is compatible with that of other versions of -.BR getopt (1). -It will still do parameter shuffling and recognize optional -arguments (see section -.B COMPATIBILITY -for more information). - -Traditional implementations of -.BR getopt (1) -are unable to cope with whitespace and other (shell-specific) special characters -in arguments and non-option parameters. To solve this problem, this -implementation can generate -quoted output which must once again be interpreted by the shell (usually -by using the -.B eval -command). This has the effect of preserving those characters, but -you must call -.B getopt -in a way that is no longer compatible with other versions (the second -or third format in the -.BR SYNOPSIS). -To determine whether this enhanced version of -.BR getopt (1) -is installed, a special test option -.RB ( -T ) -can be used. -.SH OPTIONS -.IP "-a, --alternative" -Allow long options to start with a single -.RB ` - '. -.IP "-h, --help" -Output a small usage guide and exit succesfully. No other output is generated. -.IP "-l, --longoptions longopts" -The long (multi-character) options to be recognized. -More than one option name -may be specified at once, by separating the names with commas. This option -may be given more than once, the -.I longopts -are cummulative. -Each long option name -in -.I longopts -may be followed by one colon to indicate it has a required argument,and by two colons to indicate it has an optional argument. -.IP "-n, --name progname" -The name that will be used by the -.BR getopt (3) -routines when it reports errors. Note that errors of -.BR getopt (1) -are still reported as coming from getopt. -.IP "-o, --options shortopts" -The short (one-character) options to be recognized. If this options is not -found, the first parameter of -.B getopt -that does not start with -a -.RB ` - ' -(and is not an option argument) is used as the short options string. -Each short option character -in -.I shortopts -may be followed by one colon to indicate it has a required argument, -and by two colons to indicate it has an optional argument. -The first character of shortopts may be -.RB ` + ' -or -.RB ` - ' -to influence the way -options are parsed and output is generated (see section -.B SCANNING MODES -for details). -.IP "-q, --quiet" -Disable error reporting by getopt(3). -.IP "-Q, --quiet-output" -Do not generate normal output. Errors are still reported by -.BR getopt (3), -unless you also use -.IR -q . -.IP "-s, --shell shell" -Set quoting conventions to those of shell. If no -s argument is found, -the -.SM BASH -conventions are used. Valid arguments are currently -.RB ` sh ' -.RB ` bash ', -.RB ` csh ', -and -.RB ` tcsh '. -.IP "-u, --unquoted" -Do not quote the output. Note that whitespace and special (shell-dependent) -characters can cause havoc in this mode (like they do with other -.BR getopt (1) -implementations). -.IP "-T --test" -Test if your -.BR getopt (1) -is this enhanced version or an old version. This generates no output, -and sets the error status to 4. Other implementations of -.BR getopt (1), -and this version if the environment variable -.B GETOPT_COMPATIBLE -is set, -will return -.RB ` -- ' -and error status 0. -.IP "-V, --version" -Output version information and exit succesfully. No other output is generated. -.SH PARSING -This section specifies the format of the second part of the parameters of -.B getopt -(the -.I parameters -in the -.BR SYNOPSIS ). -The next section -.RB ( OUTPUT ) -describes the output that is -generated. These parameters were typically the parameters a shell function -was called with. -Care must be taken that each parameter the shell function was -called with corresponds to exactly one parameter in the parameter list of -.B getopt -(see the -.BR EXAMPLES ). -All parsing is done by the GNU -.BR getopt (3) -routines. - -The parameters are parsed from left to right. Each parameter is classified as a -short option, a long option, an argument to an option, -or a non-option parameter. - -A simple short option is a -.RB ` - ' -followed by a short option character. If -the option has a required argument, it may be written directly after the option -character or as the next parameter (ie. separated by whitespace on the -command line). If the -option has an optional argument, it must be written directly after the -option character if present. - -It is possible to specify several short options after one -.RB ` - ', -as long as all (except possibly the last) do not have required or optional -arguments. - -A long option normally begins with -.RB ` -- ' -followed by the long option name. -If the option has a required argument, it may be written directly after -the long option name, separated by -.RB ` = ', -or as the next argument (ie. separated by whitespace on the command line). -If the option has an optional argument, it must -be written directly after the long option name, separated by -.RB ` = ', -if present (if you add the -.RB ` = ' -but nothing behind it, it is interpreted -as if no argument was present; this is a slight bug, see the -.BR BUGS ). -Long options may be abbreviated, as long as the abbreviation is not -ambiguous. - -Each parameter not starting with a -.RB ` - ', -and not a required argument of -a previous option, is a non-option parameter. Each parameter after -a -.RB ` -- ' -parameter is always interpreted as a non-option parameter. -If the environment variable -.B POSIXLY_CORRECT -is set, or if the short -option string started with a -.RB ` + ', -all remaining parameters are interpreted -as non-option parameters as soon as the first non-option parameter is -found. -.SH OUTPUT -Output is generated for each element described in the previous section. -Output is done -in the same order as the elements are specified in the input, except -for non-option parameters. Output can be done in -.I compatible -.RI ( unquoted ) -mode, or in such way that whitespace and other special characters within -arguments and non-option parameters are preserved (see -.BR QUOTING ). -When the output is processed in the shell script, it will seem to be -composed of distinct elements that can be processed one by one (by using the -shift command in most shell languages). This is imperfect in unquoted mode, -as elements can be split at unexpected places if they contain whitespace -or special characters. - -If there are problems parsing the parameters, for example because a -required argument is not found or an option is not recognized, an error -will be reported on stderr, there will be no output for the offending -element, and a non-zero error status is returned. - -For a short option, a single -.RB ` - ' -and the option character are generated -as one parameter. If the option has an argument, the next -parameter will be the argument. If the option takes an optional argument, -but none was found, the next parameter will be generated but be empty in -quoting mode, -but no second parameter will be generated in unquoted (compatible) mode. -Note that many other -.BR getopt (1) -implemetations do not support optional arguments. - -If several short options were specified after a single -.RB ` - ', -each will be present in the output as a separate parameter. - -For a long option, -.RB ` -- ' -and the full option name are generated as one -parameter. This is done regardless whether the option was abbreviated or -specified with a single -.RB ` - ' -in the input. Arguments are handled as with short options. - -Normally, no non-option parameters output is generated until all options -and their arguments have been generated. Then -.RB ` -- ' -is generated as a -single parameter, and after it the non-option parameters in the order -they were found, each as a separate parameter. -Only if the first character of the short options string was a -.RB ` - ', -non-option parameter output is generated at the place they are found in the -input (this is not supported if the first format of the -.B SYNOPSIS -is used; in that case all preceding occurences of -.RB ` - ' -and -.RB ` + ' -are ignored). -.SH QUOTING -In compatible mode, whitespace or 'special' characters in arguments or -non-option parameters are not handled correctly. As the output is -fed to the shell script, the script does not know how it is supposed to break -the output into separate parameters. To circumvent this -problem, this implementation offers quoting. The idea is that output -is generated with quotes around each parameter. When this output is once -again fed to the shell (usually by a shell -.B eval -command), it is split correctly into separate parameters. - -Quoting is not enabled if the environment variable -.B GETOPT_COMPATIBLE -is set, if the first form of the -.B SYNOPSIS -is used, or if the option -.RB ` -u ' -is found. - -Different shells use different quoting conventions. You can use the -.RB ` -s ' -option to select the shell you are using. The following shells are -currently supported: -.RB ` sh ', -.RB ` bash ', -.RB ` csh ' -and -.RB ` tcsh '. -Actually, only two `flavors' are distinguished: sh-like quoting conventions -and csh-like quoting conventions. Chances are that if you use another shell -script language, one of these flavors can still be used. - -.SH "SCANNING MODES" -The first character of the short options string may be a -.RB ` - ' -or a -.RB ` + ' -to indicate a special scanning mode. If the first calling form -in the -.B SYNOPSIS -is used they are ignored; the environment variable -.B POSIXLY_CORRECT -is still examined, though. - -If the first character is -.RB ` + ', -or if the environment variable -.B POSIXLY_CORRECT -is set, parsing stops as soon as the first non-option parameter -(ie. a parameter that does not start with a -.RB ` - ') -is found that -is not an option argument. The remaining parameters are all interpreted as -non-option parameters. - -If the first character is a -.RB ` - ', -non-option parameters are outputed at the place where they are found; in normal -operation, they are all collected at the end of output after a -.RB ` -- ' -parameter has been generated. Note that this -.RB ` -- ' -parameter is still generated, but it will always be the last parameter in -this mode. -.SH COMPATIBILITY -This version of -.BR getopt (1) -is written to be as compatible as possible to -other versions. Usually you can just replace them with this version -without any modifications, and with some advantages. - -If the first character of the first parameter of getopt is not a -.RB ` - ', -getopt goes into compatibility mode. It will interpret its first parameter as -the string of short options, and all other arguments will be parsed. It -will still do parameter shuffling (ie. all non-option parameters are outputed -at the end), unless the environment variable -.B POSIXLY_CORRECT -is set. - -The environment variable -.B GETOPT_COMPATIBLE -forces -.B getopt -into compatibility mode. Setting both this environment variable and -.B POSIXLY_CORRECT -offers 100% compatibility for `difficult' programs. Usually, though, -neither is needed. - -In compatibility mode, leading -.RB ` - ' -and -.RB ` + ' -characters in the short options string are ignored. -.SH RETURN CODES -.B getopt -returns error code -.B 0 -for succesful parsing, -.B 1 -if -.BR getopt (3) -returns errors, -.B 2 -if it does not understand its own parameters, -.B 3 -if an internal error occurs like out-of-memory, and -.B 4 -if it is called with -.BR -T . -.SH EXAMPLES -Example scripts for (ba)sh and (t)csh are provided with the -.BR getopt (1) -distribution, and are optionally installed in -.B /usr/local/lib/getopt -or -.BR /usr/lib/getopt . -.SH ENVIRONMENT -.IP POSIXLY_CORRECT -This environment variable is examined by the -.BR getopt (3) -routines. -If it is set, parsing stops as soon as a parameter -is found that is not an option or an option argument. All remaining -parameters are also interpreted as non-option parameters, regardless -whether they start with a -.RB ` - '. -.IP GETOPT_COMPATIBLE -Forces -.B getopt -to use the first calling format as specified in the -.BR SYNOPSIS . -.SH BUGS -.BR getopt (3) -can parse long options with optional arguments that are given an empty optional -argument (but can not do this for short options). This -.BR getopt (1) -treats optional arguments that are empty as if they were not present. -.SH AUTHOR -Frodo Looijaard -.SH "SEE ALSO" -.BR getopt (3), -.BR bash (1), -.BR tcsh (1). - diff --git a/getopt-1.0.3b/getopt.c b/getopt-1.0.3b/getopt.c deleted file mode 100644 index 345c1b977..000000000 --- a/getopt-1.0.3b/getopt.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - getopt.c - Enhanced implementation of BSD getopt(1) - Copyright (c) 1997, 1998 Frodo Looijaard - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - * Version 1.0-b4: Tue Sep 23 1997. First public release. - * Version 1.0: Wed Nov 19 1997. - * Bumped up the version number to 1.0 - * Fixed minor typo (CSH instead of TCSH) - * Version 1.0.1: Tue Jun 3 1998 - * Fixed sizeof instead of strlen bug - * Bumped up the version number to 1.0.1 - * Version 1.0.2: Thu Jun 11 1998 (not present) - * Fixed gcc-2.8.1 warnings - * Fixed --version/-V option (not present) - * Version 1.0.3 - * 1999-02-22 Arkadiusz Mi¶kiewicz - * - added Native Language Support - * - */ - -#include -#include -#include -#include -#include -#include "../lib/nls.h" - -#if LIBCGETOPT -#include -#else -#include "getopt.h" -#endif - -/* NON_OPT is the code that is returned when a non-option is found in '+' - mode */ -#define NON_OPT 1 -/* LONG_OPT is the code that is returned when a long option is found. */ -#define LONG_OPT 2 - -/* The shells recognized. */ -typedef enum {BASH,TCSH} shell_t; - - -/* Some global variables that tells us how to parse. */ -shell_t shell=BASH; /* The shell we generate output for. */ -int quiet_errors=0; /* 0 is not quiet. */ -int quiet_output=0; /* 0 is not quiet. */ -int quote=1; /* 1 is do quote. */ -int alternative=0; /* 0 is getopt_long, 1 is getopt_long_only */ - -/* Function prototypes */ -void *our_malloc(size_t size); -void *our_realloc(void *ptr, size_t size); -const char *normalize(const char *arg); -int generate_output(char * argv[],int argc,const char *optstr, - const struct option *longopts); -int main(int argc, char *argv[]); -void parse_error(const char *message); -void add_long_options(char *options); -void add_longopt(const char *name,int has_arg); -void print_help(void); -void set_shell(const char *new_shell); -void set_initial_shell(void); - -void *our_malloc(size_t size) -{ - void *ret=malloc(size); - if (! ret) { - fprintf(stderr,_("%s: Out of memory!\n"),"getopt"); - exit(3); - } - return(ret); -} - -void *our_realloc(void *ptr, size_t size) -{ - void *ret=realloc(ptr,size); - if (! ret && size) { - fprintf(stderr,_("%s: Out of memory!\n"), "getopt"); - exit(3); - } - return(ret); -} - -/* - * This function 'normalizes' a single argument: it puts single quotes around - * it and escapes other special characters. If quote is false, it just - * returns its argument. - * Bash only needs special treatment for single quotes; tcsh also recognizes - * exclamation marks within single quotes, and nukes whitespace. - * This function returns a pointer to a buffer that is overwritten by - * each call. - */ -const char *normalize(const char *arg) -{ - static char *BUFFER=NULL; - const char *argptr=arg; - char *bufptr; - - if (BUFFER != NULL) - free(BUFFER); - - if (!quote) { /* Just copy arg */ - BUFFER=our_malloc(strlen(arg)+1); - - strcpy(BUFFER,arg); - return BUFFER; - } - - /* Each character in arg may take upto four characters in the result: - For a quote we need a closing quote, a backslash, a quote and an - opening quote! We need also the global opening and closing quote, - and one extra character for '\0'. */ - BUFFER=our_malloc(strlen(arg)*4+3); - - bufptr=BUFFER; - *bufptr++='\''; - - while (*argptr) { - if (*argptr == '\'') { - /* Quote: replace it with: '\'' */ - *bufptr++='\''; - *bufptr++='\\'; - *bufptr++='\''; - *bufptr++='\''; - } else if (shell==TCSH && *argptr=='!') { - /* Exclamation mark: replace it with: \! */ - *bufptr++='\''; - *bufptr++='\\'; - *bufptr++='!'; - *bufptr++='\''; - } else if (shell==TCSH && *argptr=='\n') { - /* Newline: replace it with: \n */ - *bufptr++='\\'; - *bufptr++='n'; - } else if (shell==TCSH && isspace(*argptr)) { - /* Non-newline whitespace: replace it with \ */ - *bufptr++='\''; - *bufptr++='\\'; - *bufptr++=*argptr; - *bufptr++='\''; - } else - /* Just copy */ - *bufptr++=*argptr; - argptr++; - } - *bufptr++='\''; - *bufptr++='\0'; - return BUFFER; -} - -/* - * Generate the output. argv[0] is the program name (used for reporting errors). - * argv[1..] contains the options to be parsed. argc must be the number of - * elements in argv (ie. 1 if there are no options, only the program name), - * optstr must contain the short options, and longopts the long options. - * Other settings are found in global variables. - */ -int generate_output(char * argv[],int argc,const char *optstr, - const struct option *longopts) -{ - int exit_code = 0; /* We assume everything will be OK */ - int opt; - int longindex; - const char *charptr; - - if (quiet_errors) /* No error reporting from getopt(3) */ - opterr=0; - optind=0; /* Reset getopt(3) */ - - while ((opt = (alternative? - getopt_long_only(argc,argv,optstr,longopts,&longindex): - getopt_long(argc,argv,optstr,longopts,&longindex))) - != EOF) - if (opt == '?' || opt == ':' ) - exit_code = 1; - else if (!quiet_output) - { - if (opt == LONG_OPT) { - printf(" --%s",longopts[longindex].name); - if (longopts[longindex].has_arg) - printf(" %s", - normalize(optarg?optarg:"")); - } else if (opt == NON_OPT) - printf(" %s",normalize(optarg)); - else { - printf(" -%c",opt); - charptr = strchr(optstr,opt); - if (charptr != NULL && *++charptr == ':') - printf(" %s", - normalize(optarg?optarg:"")); - } - } - - if (! quiet_output) { - printf(" --"); - while (optind < argc) - printf(" %s",normalize(argv[optind++])); - printf("\n"); - } - return exit_code; -} - -/* - * Report an error when parsing getopt's own arguments. - * If message is NULL, we already sent a message, we just exit with a helpful - * hint. - */ -void parse_error(const char *message) -{ - if (message) - fprintf(stderr,"getopt: %s\n",message); - fputs(_("Try `getopt --help' for more information.\n"),stderr); - exit(2); -} - -static struct option *long_options=NULL; -static int long_options_length=0; /* Length of array */ -static int long_options_nr=0; /* Nr of used elements in array */ -#define LONG_OPTIONS_INCR 10 -#define init_longopt() add_longopt(NULL,0) - -/* Register a long option. The contents of name is copied. */ -void add_longopt(const char *name,int has_arg) -{ - char *tmp; - if (!name) { /* init */ - free(long_options); - long_options=NULL; - long_options_length=0; - long_options_nr=0; - } - - if (long_options_nr == long_options_length) { - long_options_length += LONG_OPTIONS_INCR; - long_options=our_realloc(long_options, - sizeof(struct option) * - long_options_length); - } - - long_options[long_options_nr].name=NULL; - long_options[long_options_nr].has_arg=0; - long_options[long_options_nr].flag=NULL; - long_options[long_options_nr].val=0; - - if (long_options_nr) { /* Not for init! */ - long_options[long_options_nr-1].has_arg=has_arg; - long_options[long_options_nr-1].flag=NULL; - long_options[long_options_nr-1].val=LONG_OPT; - tmp = our_malloc(strlen(name)+1); - strcpy(tmp,name); - long_options[long_options_nr-1].name=tmp; - } - long_options_nr++; -} - - -/* - * Register several long options. options is a string of long options, - * separated by commas or whitespace. - * This nukes options! - */ -void add_long_options(char *options) -{ - int arg_opt; - char *tokptr=strtok(options,", \t\n"); - while (tokptr) { - arg_opt=no_argument; - if (strlen(tokptr) > 0) { - if (tokptr[strlen(tokptr)-1] == ':') { - if (tokptr[strlen(tokptr)-2] == ':') { - tokptr[strlen(tokptr)-2]='\0'; - arg_opt=optional_argument; - } else { - tokptr[strlen(tokptr)-1]='\0'; - arg_opt=required_argument; - } - if (strlen(tokptr) == 0) - parse_error(_("empty long option after " - "-l or --long argument")); - } - add_longopt(tokptr,arg_opt); - } - tokptr=strtok(NULL,", \t\n"); - } -} - -void set_shell(const char *new_shell) -{ - if (!strcmp(new_shell,"bash")) - shell=BASH; - else if (!strcmp(new_shell,"tcsh")) - shell=TCSH; - else if (!strcmp(new_shell,"sh")) - shell=BASH; - else if (!strcmp(new_shell,"csh")) - shell=TCSH; - else - parse_error(_("unknown shell after -s or --shell argument")); -} - -void print_help(void) -{ - fputs(_("Usage: getopt optstring parameters\n"),stderr); - fputs(_(" getopt [options] [--] optstring parameters\n"),stderr); - fputs(_(" getopt [options] -o|--options optstring [options] [--]\n"),stderr); - fputs(_(" parameters\n"),stderr); - fputs(_(" -a, --alternative Allow long options starting with single -\n"),stderr); - fputs(_(" -h, --help This small usage guide\n"),stderr); - fputs(_(" -l, --longoptions=longopts Long options to be recognized\n"),stderr); - fputs(_(" -n, --name=progname The name under which errors are reported\n"),stderr); - fputs(_(" -o, --options=optstring Short options to be recognized\n"),stderr); - fputs(_(" -q, --quiet Disable error reporting by getopt(3)\n"),stderr); - fputs(_(" -Q, --quiet-output No normal output\n"),stderr); - fputs(_(" -s, --shell=shell Set shell quoting conventions\n"),stderr); - fputs(_(" -T, --test Test for getopt(1) version\n"),stderr); - fputs(_(" -V, --version Output version information\n"),stderr); - exit(2); -} - -/* Exit codes: - * 0) No errors, succesful operation. - * 1) getopt(3) returned an error. - * 2) A problem with parameter parsing for getopt(1). - * 3) Internal error, out of memory - * 4) Returned for -T - */ - -static struct option longopts[]={ {"options",required_argument,NULL,'o'}, - {"longoptions",required_argument,NULL,'l'}, - {"quiet",no_argument,NULL,'q'}, - {"quiet-output",no_argument,NULL,'Q'}, - {"shell",required_argument,NULL,'s'}, - {"test",no_argument,NULL,'T'}, - {"unquoted",no_argument,NULL,'u'}, - {"help",no_argument,NULL,'h'}, - {"alternative",no_argument,NULL,'a'}, - {"name",required_argument,NULL,'n'}, - {"version",no_argument,NULL,'V'}, - {NULL,0,NULL,0} - }; - -/* Stop scanning as soon as a non-option argument is found! */ -static const char *shortopts="+ao:l:n:qQs:TuhV"; - -int main(int argc, char *argv[]) -{ - char *optstr=NULL; - char *name=NULL; - int opt; - int compatible=0; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - init_longopt(); - - if (getenv("GETOPT_COMPATIBLE")) - compatible=1; - - if (argc == 1) - { - if (compatible) { - /* For some reason, the original getopt gave no error - when there were no arguments. */ - printf(" --\n"); - exit(0); - } - else - parse_error(_("missing optstring argument")); - } - - if (argv[1][0] != '-' || compatible) { - quote=0; - optstr=our_malloc(strlen(argv[1])+1); - strcpy(optstr,argv[1]+strspn(argv[1],"-+")); - argv[1]=argv[0]; - exit(generate_output(argv+1,argc-1,optstr,long_options)); - } - - while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF) - switch (opt) { - case 'a': - alternative=1; - break; - case 'h': - print_help(); - exit(0); - case 'o': - if (optstr) - free(optstr); - optstr=our_malloc(strlen(optarg)+1); - strcpy(optstr,optarg); - break; - case 'l': - add_long_options(optarg); - break; - case 'n': - if (name) - free(name); - name=our_malloc(strlen(optarg)+1); - strcpy(name,optarg); - break; - case 'q': - quiet_errors=1; - break; - case 'Q': - quiet_output=1; - break; - case 's': - set_shell(optarg); - break; - case 'T': - exit(4); - case 'V': - printf(_("getopt (enhanced) 1.0.3\n")); - exit(0); - case '?': - case ':': - parse_error(NULL); - default: - parse_error(_("internal error, contact the author.")); - } - - if (!optstr) - { - if (optind >= argc) - parse_error(_("missing optstring argument")); - else { - optstr=our_malloc(strlen(argv[optind])+1); - strcpy(optstr,argv[optind]); - optind++; - } - } - if (name) - argv[optind-1]=name; - else - argv[optind-1]=argv[0]; - exit(generate_output(argv+optind-1,argc-optind+1,optstr,long_options)); -} diff --git a/getopt-1.0.3b/gnu/getopt.c b/getopt-1.0.3b/gnu/getopt.c deleted file mode 100644 index 59b51cd67..000000000 --- a/getopt-1.0.3b/gnu/getopt.c +++ /dev/null @@ -1,1050 +0,0 @@ -/* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu - before changing it! - - Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 - Free Software Foundation, Inc. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* This tells Alpha OSF/1 not to define a getopt prototype in . - Ditto for AIX 3.2 and . */ -#ifndef _NO_PROTO -#define _NO_PROTO -#endif - -#ifdef HAVE_CONFIG_H -#include -#endif - -#if !defined (__STDC__) || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 -#include -#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -#define ELIDE_CODE -#endif -#endif - -#ifndef ELIDE_CODE - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -/* Don't include stdlib.h for non-GNU C libraries because some of them - contain conflicting prototypes for getopt. */ -#include -#include -#endif /* GNU C library. */ - -#ifdef VMS -#include -#if HAVE_STRING_H - 0 -#include -#endif -#endif - -#if defined (WIN32) && !defined (__CYGWIN32__) -/* It's not Unix, really. See? Capital letters. */ -#include -#define getpid() GetCurrentProcessId() -#endif - -#ifndef _ -/* This is for other GNU distributions with internationalized messages. - When compiling libc, the _ macro is predefined. */ -#ifdef HAVE_LIBINTL_H -# include -# define _(msgid) gettext (msgid) -#else -# define _(msgid) (msgid) -#endif -#endif - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg = NULL; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* 1003.2 says this must be 1 before any call. */ -int optind = 1; - -/* Formerly, initialization of getopt depended on optind==0, which - causes problems with re-calling getopt as programs generally don't - know that. */ - -int __getopt_initialized = 0; - -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; - -#ifdef __GNU_LIBRARY__ -/* We want to avoid inclusion of string.h with non-GNU libraries - because there are many ways it can cause trouble. - On some systems, it contains special magic macros that don't work - in GCC. */ -#include -#define my_index strchr -#else - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -char *getenv (); - -static char * -my_index (str, chr) - const char *str; - int chr; -{ - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; -} - -/* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. */ -#ifdef __GNUC__ -/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. - That was relevant to code that was here before. */ -#if !defined (__STDC__) || !__STDC__ -/* gcc with -traditional declares the built-in strlen to return int, - and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -#endif /* not __STDC__ */ -#endif /* __GNUC__ */ - -#endif /* not __GNU_LIBRARY__ */ - -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - -#ifdef _LIBC -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; - -static int nonoption_flags_max_len; -static int nonoption_flags_len; - -static int original_argc; -static char *const *original_argv; - -extern pid_t __libc_pid; - -/* Make sure the environment variable bash 2.0 puts in the environment - is valid for the getopt call we must make sure that the ARGV passed - to getopt is that one passed to the process. */ -static void -__attribute__ ((unused)) -store_args_and_env (int argc, char *const *argv) -{ - /* XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ - original_argc = argc; - original_argv = argv; -} -text_set_element (__libc_subinit, store_args_and_env); - -# define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -#if defined (__STDC__) && __STDC__ -static void exchange (char **); -#endif - -static void -exchange (argv) - char **argv; -{ - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - -#ifdef _LIBC - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; - else - { - memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len); - memset (&new_str[nonoption_flags_max_len], '\0', - top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; -} - -/* Initialize the internal data when the first call is made. */ - -#if defined (__STDC__) && __STDC__ -static const char *_getopt_initialize (int, char *const *, const char *); -#endif -static const char * -_getopt_initialize (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - first_nonopt = last_nonopt = optind; - - nextchar = NULL; - - posixly_correct = getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - -#ifdef _LIBC - if (posixly_correct == NULL - && argc == original_argc && argv == original_argv) - { - if (nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; - else - { - memcpy (__getopt_nonoption_flags, orig_str, len); - memset (&__getopt_nonoption_flags[len], '\0', - nonoption_flags_max_len - len); - } - } - } - nonoption_flags_len = nonoption_flags_max_len; - } - else - nonoption_flags_len = 0; -#endif - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; -{ - optarg = NULL; - - if (optind == 0 || !__getopt_initialized) - { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; - } - - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -#ifdef _LIBC -#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) -#else -#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') -#endif - - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; - - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (ordering == REQUIRE_ORDER) - return -1; - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - _("%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - _("%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); - - nextchar += strlen (nextchar); - - optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) - { - if (opterr) - { - if (argv[optind][1] == '-') - /* --option */ - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); - else - /* +option or -option */ - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); - } - nextchar = (char *) ""; - optind++; - optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *nextchar++; - char *temp = my_index (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (opterr) - { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: illegal option -- %c\n"), - argv[0], c); - else - fprintf (stderr, _("%s: invalid option -- %c\n"), - argv[0], c); - } - optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - fprintf (stderr, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, - _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } -} - -int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); -} - -#endif /* Not ELIDE_CODE. */ - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/getopt-1.0.3b/gnu/getopt.h b/getopt-1.0.3b/gnu/getopt.h deleted file mode 100644 index d6ceb0eee..000000000 --- a/getopt-1.0.3b/gnu/getopt.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Declarations for getopt. - Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _GETOPT_H -#define _GETOPT_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ - -extern int optopt; - -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - -struct option -{ -#if defined (__STDC__) && __STDC__ - const char *name; -#else - char *name; -#endif - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* Names for the values of the `has_arg' field of `struct option'. */ - -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - -#if defined (__STDC__) && __STDC__ -#ifdef __GNU_LIBRARY__ -/* Many other libraries have conflicting prototypes for getopt, with - differences in the consts, in stdlib.h. To avoid compilation - errors, only prototype getopt for the GNU C library. */ -extern int getopt (int argc, char *const *argv, const char *shortopts); -#else /* not __GNU_LIBRARY__ */ -extern int getopt (); -#endif /* __GNU_LIBRARY__ */ -extern int getopt_long (int argc, char *const *argv, const char *shortopts, - const struct option *longopts, int *longind); -extern int getopt_long_only (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind); - -/* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind, - int long_only); -#else /* not __STDC__ */ -extern int getopt (); -extern int getopt_long (); -extern int getopt_long_only (); - -extern int _getopt_internal (); -#endif /* __STDC__ */ - -#ifdef __cplusplus -} -#endif - -#endif /* _GETOPT_H */ diff --git a/getopt-1.0.3b/gnu/getopt1.c b/getopt-1.0.3b/gnu/getopt1.c deleted file mode 100644 index 4aa8de6f6..000000000 --- a/getopt-1.0.3b/gnu/getopt1.c +++ /dev/null @@ -1,187 +0,0 @@ -/* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "getopt.h" - -#if !defined (__STDC__) || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 -#include -#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -#define ELIDE_CODE -#endif -#endif - -#ifndef ELIDE_CODE - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -#include -#endif - -#ifndef NULL -#define NULL 0 -#endif - -int -getopt_long (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal (argc, argv, options, long_options, opt_index, 0); -} - -/* Like getopt_long, but '-' as well as '--' can indicate a long option. - If an option that starts with '-' (not '--') doesn't match a long option, - but does match a short option, it is parsed as a short option - instead. */ - -int -getopt_long_only (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal (argc, argv, options, long_options, opt_index, 1); -} - - -#endif /* Not ELIDE_CODE. */ - -#ifdef TEST - -#include - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/getopt-1.0.3b/parse.bash b/getopt-1.0.3b/parse.bash deleted file mode 100644 index 864fc0add..000000000 --- a/getopt-1.0.3b/parse.bash +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -# A small example program for using the new getopt(1) program. -# This program will only work with bash(1) -# An similar program using the tcsh(1) script language can be found -# as parse.tcsh - -# Example input and output (from the bash prompt): -# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long " -# Option a -# Option c, no argument -# Option c, argument `more' -# Option b, argument ` very long ' -# Remaining arguments: -# --> `par1' -# --> `another arg' -# --> `wow!*\?' - -# Note that we use `"$@"' to let each command-line parameter expand to a -# separate word. The quotes around `$@' are essential! -# We need TEMP as the `eval set --' would nuke the return value of getopt. -TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \ - -n 'example.bash' -- "$@"` - -if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi - -# Note the quotes around `$TEMP': they are essential! -eval set -- "$TEMP" - -while true ; do - case "$1" in - -a|--a-long) echo "Option a" ; shift ;; - -b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;; - -c|--c-long) - # c has an optional argument. As we are in quoted mode, - # an empty parameter will be generated if its optional - # argument is not found. - case "$2" in - "") echo "Option c, no argument"; shift 2 ;; - *) echo "Option c, argument \`$2'" ; shift 2 ;; - esac ;; - --) shift ; break ;; - *) echo "Internal error!" ; exit 1 ;; - esac -done -echo "Remaining arguments:" -for arg do echo '--> '"\`$arg'" ; done diff --git a/getopt-1.0.3b/parse.tcsh b/getopt-1.0.3b/parse.tcsh deleted file mode 100644 index 2266d0e64..000000000 --- a/getopt-1.0.3b/parse.tcsh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/tcsh - -# A small example program for using the new getopt(1) program. -# This program will only work with tcsh(1) -# An similar program using the bash(1) script language can be found -# as parse.bash - -# Example input and output (from the tcsh prompt): -# ./parse.tcsh -a par1 'another arg' --c-long 'wow\!*\?' -cmore -b " very long " -# Option a -# Option c, no argument -# Option c, argument `more' -# Option b, argument ` very long ' -# Remaining arguments: -# --> `par1' -# --> `another arg' -# --> `wow!*\?' - -# Note that we had to escape the exclamation mark in the wow-argument. This -# is _not_ a problem with getopt, but with the tcsh command parsing. If you -# would give the same line from the bash prompt (ie. call ./parse.tcsh), -# you could remove the exclamation mark. - -# This is a bit tricky. We use a temp variable, to be able to check the -# return value of getopt (eval nukes it). argv contains the command arguments -# as a list. The ':q` copies that list without doing any substitutions: -# each element of argv becomes a separate argument for getopt. The braces -# are needed because the result is also a list. -set temp=(`getopt -s tcsh -o ab:c:: --long a-long,b-long:,c-long:: -- $argv:q`) -if ($? != 0) then - echo "Terminating..." >/dev/stderr - exit 1 -endif - -# Now we do the eval part. As the result is a list, we need braces. But they -# must be quoted, because they must be evaluated when the eval is called. -# The 'q` stops doing any silly substitutions. -eval set argv=\($temp:q\) - -while (1) - switch($1:q) - case -a: - case --a-long: - echo "Option a" ; shift - breaksw; - case -b: - case --b-long: - echo "Option b, argument "\`$2:q\' ; shift ; shift - breaksw - case -c: - case --c-long: - # c has an optional argument. As we are in quoted mode, - # an empty parameter will be generated if its optional - # argument is not found. - - if ($2:q == "") then - echo "Option c, no argument" - else - echo "Option c, argument "\`$2:q\' - endif - shift; shift - breaksw - case --: - shift - break - default: - echo "Internal error!" ; exit 1 - endsw -end - -echo "Remaining arguments:" -# foreach el ($argv:q) created problems for some tcsh-versions (at least -# 6.02). So we use another shift-loop here: -while ($#argv > 0) - echo '--> '\`$1:q\' - shift -end diff --git a/getopt-1.0.3b/test.bash b/getopt-1.0.3b/test.bash deleted file mode 100644 index 149e1f9b0..000000000 --- a/getopt-1.0.3b/test.bash +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -if `getopt -T >/dev/null 2>&1` ; [ $? = 4 ] ; then - echo "Enhanced getopt(1)" -else - echo "Old getopt(1)" -fi diff --git a/getopt-1.0.3b/test.tcsh b/getopt-1.0.3b/test.tcsh deleted file mode 100644 index d661e767d..000000000 --- a/getopt-1.0.3b/test.tcsh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/tcsh -getopt -T >&/dev/null -if ( $status == 4) then - echo "Enhanced getopt(1)" -else - echo "Old getopt(1)" -endif diff --git a/getopt-1.1.0a/COPYING b/getopt-1.1.0a/COPYING new file mode 100644 index 000000000..a43ea2126 --- /dev/null +++ b/getopt-1.1.0a/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/getopt-1.1.0a/Changelog b/getopt-1.1.0a/Changelog new file mode 100644 index 000000000..e144bb0f8 --- /dev/null +++ b/getopt-1.1.0a/Changelog @@ -0,0 +1,24 @@ +20000630: Ported the Native Language Support patches from util-linux + They are written by Arkadiusz Mi¶kiewicz +20000627: Bumped up version number to 1.0.6 +20000627: A few manpage tweaks +20000616: Introduced DESTDIR and directory creation in the Makefile. +19990716: Bumped up version number to 1.0.5 +19990622: Made -u work +19990101: Bumped up version number to 1.0.4 (aka. 1.0.3a in util-linux) +19990101: Very small fix in main() +19990101: Updated util-linux Makefile +19980628: Bumped up version number to 1.0.3 +19980628: Removed remaining incompatibility with tcsh-6.02 from parse.tcsh +980626: Added separate Makefile for util-linux +19980625: Removed several bugs from parse.tcsh, partly thanks to Volker Kuhlmann + (v.kuhlmann@elec.canterbury.ac.nz). +19980612: Removed reference to getopt in util-linux +19980611: Bumped up version number to 1.0.2 +19980611: Fixed --version bug (was not available, though documented!) +19980611: Removed compiler warnings. +19980603: Bumped up version number to 1.0.1 +19980603: Fixed sizeof() bug (should be strlen) in getopt.c, thanks to + Bob Proulx (rwp@hprwp.fc.hp.com). +19980505: Changed date field in LSM to proper syntax +19980505: Released version 1.0 diff --git a/getopt-1.1.0a/Makefile b/getopt-1.1.0a/Makefile new file mode 100644 index 000000000..6b50f849b --- /dev/null +++ b/getopt-1.1.0a/Makefile @@ -0,0 +1,53 @@ +.SUFFIXES: + +include ../make_include +include ../MCONFIG + +GETOPTDIR=$(USRSHAREMISCDIR)/getopt + +# Define this to 0 to use the getopt(3) routines in this package. +LIBCGETOPT=1 + +SHELL=/bin/sh + +LD=ld +RM=rm -f +INSTALL=install + +CPPFLAGS=-DLIBCGETOPT=$(LIBCGETOPT) +ifeq ($(LIBCGETOPT),0) +CPPFLAGS+=-I./gnu +endif + +# -Wcast-align causes problems with the identifier stderr on alpha's +# with an old glibc. +# -Wbad-function-cast and -Wmissing-declarations are unknown for gcc 2.5.8. +WARNINGS=-Wall \ + -W -Wshadow -Wpointer-arith -Wcast-qual \ + -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ + -Wnested-externs -Winline +# CFLAGS= $(WARNINGS) $(OPT) + +SOURCES=getopt.c +ifeq ($(LIBCGETOPT),0) +SOURCES+=gnu/getopt.c gnu/getopt1.c +endif + +OBJECTS=$(SOURCES:.c=.o) + +BINARIES=getopt + +.PHONY: all clean realclean +all: $(BINARIES) + +clean: + -$(RM) $(OBJECTS) $(BINARIES) + +getopt: $(OBJECTS) + $(CC) $(LDFLAGS) $< -o $@ + +install: getopt + $(INSTALLDIR) $(USRBINDIR) $(MAN1DIR) $(GETOPTDIR) + $(INSTALLBIN) getopt $(USRBINDIR) + $(INSTALLMAN) getopt.1 $(MAN1DIR) + $(INSTALLBIN) parse.bash parse.tcsh test.bash test.tcsh $(GETOPTDIR) diff --git a/getopt-1.1.0a/README b/getopt-1.1.0a/README new file mode 100644 index 000000000..1d795f5e4 --- /dev/null +++ b/getopt-1.1.0a/README @@ -0,0 +1,80 @@ +This package contains a reimplementation of getopt(1). + +PREFACE + +Getopt(1) is a program to help shell scripts parse command-line parameters. +It is for example included in the util-linux distribution (upto version +2.7.1). But, there are some problems with that getopt(1) implementation, +as listed in the 'BUGS' section of its man-page: + +>BUGS +> Whatever getopt(3) has. +> +> Arguments containing white space or imbedded shell metacharacters gener- +> ally will not survive intact; this looks easy to fix but isn't. +> +> The error message for an invalid option is identified as coming from +> getopt rather than from the shell procedure containing the invocation of +> getopt; this again is hard to fix. +> +> The precise best way to use the set command to set the arguments without +> disrupting the value(s) of shell options varies from one shell version to +> another. + +This implementation of getopt(1) is written to solve some of these problems, +while still staying (for all practical purposes) completely compatible with +other getopt(1) implementations. + + +INSTALLATION + +Installation should be very easy. Just type 'make' to compile the sources. +It should compile cleanly, without any warnings, but even if it does not +you probably don't have to worry. You must use GNU Make and gcc, or you +will have to edit the Makefile. + +Type 'make install' to install the binary and the manual page. It installs +by default in /usr/local/bin and /usr/local/man/man1, to install in /usr/bin +and /usr/man/man1 try 'make install prefix=/usr'. + +The example files can be installed in /usr/local/lib/getopt by calling +'make install_doc'. + +If you do not trust the getopt(3) in your libc, or if you do not use a libc +with the GNU getopt(3) routines, you can use the gnu sources as provided +in the gnu directory. Try 'make LIBCGETOPT=0'. Ignore any compile warnings. + +You can check whether the new implementation of getopt is found first +in your path by calling 'bash test.bash'. + + +HIGHLIGHTS + +It can do anything that the GNU getopt(3) routines can do. + +It can cope with spaces and shell metacharacters within arguments. + +It can parse long parameters. + +It can shuffle parameters, so you can mix options and other parameters on +the command-line. + +It can be easily identified as an enhanced getopt(1) from within shell scripts. + +It can report parse errors as coming from the shell script. + +It is fully compatible with other getopt(1) implementations. + +COPYING + +This program comes under the GNU general public licence version 2. See the +file COPYING included in this package. Note that though you may freely +copy it, it is copyright (c) 1997 by Frodo Looijaard . +Files in the gnu directory are from glibc-2.0.4: copyright (C) 1987, 88, +89, 90, 91, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. + + +DOWNLOADING + +You can find the latest version of this program at +. diff --git a/getopt-1.1.0a/TODO b/getopt-1.1.0a/TODO new file mode 100644 index 000000000..70f2ea9cb --- /dev/null +++ b/getopt-1.1.0a/TODO @@ -0,0 +1,6 @@ +Other shells, like zsh and ash, should be supported (perhaps they will work +already, depending on quoting conventions). (zsh seems OK). + +Perhaps a nice configure script? + +Add a `test' target in Makefile. diff --git a/getopt-1.1.0a/getopt-1.0.6.lsm b/getopt-1.1.0a/getopt-1.0.6.lsm new file mode 100644 index 000000000..6323916c3 --- /dev/null +++ b/getopt-1.1.0a/getopt-1.0.6.lsm @@ -0,0 +1,19 @@ +Begin3 +Title: Getopt +Version: 1.0.6 +Entered-date: 27JUN00 +Description: An improved implementation of getopt(1), a program to parse + options within a shell script. Fully compatible with other + getopt(1) implementations, but with many additions like + long options and mixing of options and parameters. +Keywords: getopt script parse bash tcsh +Author: frodol@dds.nl (Frodo Looijaard) +Primary-site: http://huizen.dds.nl/~frodol + 28kB getopt-1.0.6.tar.gz + 600 getopt-1.0.6.lsm +Alternate-site: sunsite.unc.edu /pub/Linux/utils/shell + 28kB getopt-1.0.6.tar.gz + 600 getopt-1.0.6.lsm +Copying-policy: GPL +End + diff --git a/getopt-1.1.0a/getopt.1 b/getopt-1.1.0a/getopt.1 new file mode 100644 index 000000000..b7e360315 --- /dev/null +++ b/getopt-1.1.0a/getopt.1 @@ -0,0 +1,441 @@ +.TH GETOPT 1 "May 31, 1997" Linux "" +.SH NAME +getopt \- parse command options (enhanced) +.SH SYNOPSIS +.BR getopt " optstring parameters" + +.BR getopt " [options] [" -- "] optstring parameters" + +.BR getopt " [options] " -o | --options " optstring [options] [" -- "] parameters" +.SH DESCRIPTION +.B getopt +is used to break up +.RI ( parse ) +options in command lines for easy parsing by +shell procedures, and to check for legal options. +It uses the +.SM GNU +.BR getopt (3) +routines to do this. + +The parameters +.B getopt +is called with can be divided into two parts: options +which modify the way getopt will parse +.RI ( options +and +.I -o|--options optstring +in the +.BR SYNOPSIS), +and the parameters which are to be +parsed +.RI ( parameters +in the +.BR SYNOPSIS). +The second part will start at the first non-option parameter +that is not an option argument, or after the first occurence of +.RB ` -- '. +If no +.RB ` -o ' +or +.RB ` --options ' +option is found in the first part, the first +parameter of the second part is used as the short options string. + +If the environment variable +.B GETOPT_COMPATIBLE +is set, or if its first parameter +is not an option (does not start with a +.RB ` - ', +this is the first format in the +.BR SYNOPSIS), +.B getopt +will generate output that is compatible with that of other versions of +.BR getopt (1). +It will still do parameter shuffling and recognize optional +arguments (see section +.B COMPATIBILITY +for more information). + +Traditional implementations of +.BR getopt (1) +are unable to cope with whitespace and other (shell-specific) special characters +in arguments and non-option parameters. To solve this problem, this +implementation can generate +quoted output which must once again be interpreted by the shell (usually +by using the +.B eval +command). This has the effect of preserving those characters, but +you must call +.B getopt +in a way that is no longer compatible with other versions (the second +or third format in the +.BR SYNOPSIS). +To determine whether this enhanced version of +.BR getopt (1) +is installed, a special test option +.RB ( -T ) +can be used. +.SH OPTIONS +.IP "-a, --alternative" +Allow long options to start with a single +.RB ` - '. +.IP "-h, --help" +Output a small usage guide and exit succesfully. No other output is generated. +.IP "-l, --longoptions longopts" +The long (multi-character) options to be recognized. +More than one option name +may be specified at once, by separating the names with commas. This option +may be given more than once, the +.I longopts +are cummulative. +Each long option name +in +.I longopts +may be followed by one colon to indicate it has a required argument,and by two colons to indicate it has an optional argument. +.IP "-n, --name progname" +The name that will be used by the +.BR getopt (3) +routines when it reports errors. Note that errors of +.BR getopt (1) +are still reported as coming from getopt. +.IP "-o, --options shortopts" +The short (one-character) options to be recognized. If this options is not +found, the first parameter of +.B getopt +that does not start with +a +.RB ` - ' +(and is not an option argument) is used as the short options string. +Each short option character +in +.I shortopts +may be followed by one colon to indicate it has a required argument, +and by two colons to indicate it has an optional argument. +The first character of shortopts may be +.RB ` + ' +or +.RB ` - ' +to influence the way +options are parsed and output is generated (see section +.B SCANNING MODES +for details). +.IP "-q, --quiet" +Disable error reporting by getopt(3). +.IP "-Q, --quiet-output" +Do not generate normal output. Errors are still reported by +.BR getopt (3), +unless you also use +.IR -q . +.IP "-s, --shell shell" +Set quoting conventions to those of shell. If no -s argument is found, +the +.SM BASH +conventions are used. Valid arguments are currently +.RB ` sh ' +.RB ` bash ', +.RB ` csh ', +and +.RB ` tcsh '. +.IP "-u, --unquoted" +Do not quote the output. Note that whitespace and special (shell-dependent) +characters can cause havoc in this mode (like they do with other +.BR getopt (1) +implementations). +.IP "-T --test" +Test if your +.BR getopt (1) +is this enhanced version or an old version. This generates no output, +and sets the error status to 4. Other implementations of +.BR getopt (1), +and this version if the environment variable +.B GETOPT_COMPATIBLE +is set, +will return +.RB ` -- ' +and error status 0. +.IP "-V, --version" +Output version information and exit succesfully. No other output is generated. +.SH PARSING +This section specifies the format of the second part of the parameters of +.B getopt +(the +.I parameters +in the +.BR SYNOPSIS ). +The next section +.RB ( OUTPUT ) +describes the output that is +generated. These parameters were typically the parameters a shell function +was called with. +Care must be taken that each parameter the shell function was +called with corresponds to exactly one parameter in the parameter list of +.B getopt +(see the +.BR EXAMPLES ). +All parsing is done by the GNU +.BR getopt (3) +routines. + +The parameters are parsed from left to right. Each parameter is classified as a +short option, a long option, an argument to an option, +or a non-option parameter. + +A simple short option is a +.RB ` - ' +followed by a short option character. If +the option has a required argument, it may be written directly after the option +character or as the next parameter (ie. separated by whitespace on the +command line). If the +option has an optional argument, it must be written directly after the +option character if present. + +It is possible to specify several short options after one +.RB ` - ', +as long as all (except possibly the last) do not have required or optional +arguments. + +A long option normally begins with +.RB ` -- ' +followed by the long option name. +If the option has a required argument, it may be written directly after +the long option name, separated by +.RB ` = ', +or as the next argument (ie. separated by whitespace on the command line). +If the option has an optional argument, it must +be written directly after the long option name, separated by +.RB ` = ', +if present (if you add the +.RB ` = ' +but nothing behind it, it is interpreted +as if no argument was present; this is a slight bug, see the +.BR BUGS ). +Long options may be abbreviated, as long as the abbreviation is not +ambiguous. + +Each parameter not starting with a +.RB ` - ', +and not a required argument of +a previous option, is a non-option parameter. Each parameter after +a +.RB ` -- ' +parameter is always interpreted as a non-option parameter. +If the environment variable +.B POSIXLY_CORRECT +is set, or if the short +option string started with a +.RB ` + ', +all remaining parameters are interpreted +as non-option parameters as soon as the first non-option parameter is +found. +.SH OUTPUT +Output is generated for each element described in the previous section. +Output is done +in the same order as the elements are specified in the input, except +for non-option parameters. Output can be done in +.I compatible +.RI ( unquoted ) +mode, or in such way that whitespace and other special characters within +arguments and non-option parameters are preserved (see +.BR QUOTING ). +When the output is processed in the shell script, it will seem to be +composed of distinct elements that can be processed one by one (by using the +shift command in most shell languages). This is imperfect in unquoted mode, +as elements can be split at unexpected places if they contain whitespace +or special characters. + +If there are problems parsing the parameters, for example because a +required argument is not found or an option is not recognized, an error +will be reported on stderr, there will be no output for the offending +element, and a non-zero error status is returned. + +For a short option, a single +.RB ` - ' +and the option character are generated +as one parameter. If the option has an argument, the next +parameter will be the argument. If the option takes an optional argument, +but none was found, the next parameter will be generated but be empty in +quoting mode, +but no second parameter will be generated in unquoted (compatible) mode. +Note that many other +.BR getopt (1) +implemetations do not support optional arguments. + +If several short options were specified after a single +.RB ` - ', +each will be present in the output as a separate parameter. + +For a long option, +.RB ` -- ' +and the full option name are generated as one +parameter. This is done regardless whether the option was abbreviated or +specified with a single +.RB ` - ' +in the input. Arguments are handled as with short options. + +Normally, no non-option parameters output is generated until all options +and their arguments have been generated. Then +.RB ` -- ' +is generated as a +single parameter, and after it the non-option parameters in the order +they were found, each as a separate parameter. +Only if the first character of the short options string was a +.RB ` - ', +non-option parameter output is generated at the place they are found in the +input (this is not supported if the first format of the +.B SYNOPSIS +is used; in that case all preceding occurences of +.RB ` - ' +and +.RB ` + ' +are ignored). +.SH QUOTING +In compatible mode, whitespace or 'special' characters in arguments or +non-option parameters are not handled correctly. As the output is +fed to the shell script, the script does not know how it is supposed to break +the output into separate parameters. To circumvent this +problem, this implementation offers quoting. The idea is that output +is generated with quotes around each parameter. When this output is once +again fed to the shell (usually by a shell +.B eval +command), it is split correctly into separate parameters. + +Quoting is not enabled if the environment variable +.B GETOPT_COMPATIBLE +is set, if the first form of the +.B SYNOPSIS +is used, or if the option +.RB ` -u ' +is found. + +Different shells use different quoting conventions. You can use the +.RB ` -s ' +option to select the shell you are using. The following shells are +currently supported: +.RB ` sh ', +.RB ` bash ', +.RB ` csh ' +and +.RB ` tcsh '. +Actually, only two `flavors' are distinguished: sh-like quoting conventions +and csh-like quoting conventions. Chances are that if you use another shell +script language, one of these flavors can still be used. + +.SH "SCANNING MODES" +The first character of the short options string may be a +.RB ` - ' +or a +.RB ` + ' +to indicate a special scanning mode. If the first calling form +in the +.B SYNOPSIS +is used they are ignored; the environment variable +.B POSIXLY_CORRECT +is still examined, though. + +If the first character is +.RB ` + ', +or if the environment variable +.B POSIXLY_CORRECT +is set, parsing stops as soon as the first non-option parameter +(ie. a parameter that does not start with a +.RB ` - ') +is found that +is not an option argument. The remaining parameters are all interpreted as +non-option parameters. + +If the first character is a +.RB ` - ', +non-option parameters are outputed at the place where they are found; in normal +operation, they are all collected at the end of output after a +.RB ` -- ' +parameter has been generated. Note that this +.RB ` -- ' +parameter is still generated, but it will always be the last parameter in +this mode. +.SH COMPATIBILITY +This version of +.BR getopt (1) +is written to be as compatible as possible to +other versions. Usually you can just replace them with this version +without any modifications, and with some advantages. + +If the first character of the first parameter of getopt is not a +.RB ` - ', +getopt goes into compatibility mode. It will interpret its first parameter as +the string of short options, and all other arguments will be parsed. It +will still do parameter shuffling (ie. all non-option parameters are outputed +at the end), unless the environment variable +.B POSIXLY_CORRECT +is set. + +The environment variable +.B GETOPT_COMPATIBLE +forces +.B getopt +into compatibility mode. Setting both this environment variable and +.B POSIXLY_CORRECT +offers 100% compatibility for `difficult' programs. Usually, though, +neither is needed. + +In compatibility mode, leading +.RB ` - ' +and +.RB ` + ' +characters in the short options string are ignored. +.SH RETURN CODES +.B getopt +returns error code +.B 0 +for succesful parsing, +.B 1 +if +.BR getopt (3) +returns errors, +.B 2 +if it does not understand its own parameters, +.B 3 +if an internal error occurs like out-of-memory, and +.B 4 +if it is called with +.BR -T . +.SH EXAMPLES +Example scripts for (ba)sh and (t)csh are provided with the +.BR getopt (1) +distribution, and are optionally installed in +.B /usr/local/lib/getopt +or +.BR /usr/lib/getopt . +.SH ENVIRONMENT +.IP POSIXLY_CORRECT +This environment variable is examined by the +.BR getopt (3) +routines. +If it is set, parsing stops as soon as a parameter +is found that is not an option or an option argument. All remaining +parameters are also interpreted as non-option parameters, regardless +whether they start with a +.RB ` - '. +.IP GETOPT_COMPATIBLE +Forces +.B getopt +to use the first calling format as specified in the +.BR SYNOPSIS . +.SH BUGS +.BR getopt (3) +can parse long options with optional arguments that are given an empty optional +argument (but can not do this for short options). This +.BR getopt (1) +treats optional arguments that are empty as if they were not present. + +The syntax if you do not want any short option variables at all is +not very intuitive (you have to set them explicitely to the empty +string). + +.SH AUTHOR +Frodo Looijaard +.SH "SEE ALSO" +.BR getopt (3), +.BR bash (1), +.BR tcsh (1). + diff --git a/getopt-1.1.0a/getopt.c b/getopt-1.1.0a/getopt.c new file mode 100644 index 000000000..86efe2f84 --- /dev/null +++ b/getopt-1.1.0a/getopt.c @@ -0,0 +1,465 @@ +/* + getopt.c - Enhanced implementation of BSD getopt(1) + Copyright (c) 1997, 1998, 1999, 2000 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + * Version 1.0-b4: Tue Sep 23 1997. First public release. + * Version 1.0: Wed Nov 19 1997. + * Bumped up the version number to 1.0 + * Fixed minor typo (CSH instead of TCSH) + * Version 1.0.1: Tue Jun 3 1998 + * Fixed sizeof instead of strlen bug + * Bumped up the version number to 1.0.1 + * Version 1.0.2: Thu Jun 11 1998 (not present) + * Fixed gcc-2.8.1 warnings + * Fixed --version/-V option (not present) + * Version 1.0.5: Tue Jun 22 1999 + * Make -u option work (not present) + * Version 1.0.6: Tue Jun 27 2000 + * No important changes + * Version 1.1.0: Tue Jun 30 2000 + * Added NLS support (partly written by Arkadiusz Mikiewicz + * ) + */ + +#include +#include +#include +#include +#include + +#if LIBCGETOPT +#include +#else +#include "getopt.h" +#endif + +#include "../lib/nls.h" + +/* NON_OPT is the code that is returned when a non-option is found in '+' + mode */ +#define NON_OPT 1 +/* LONG_OPT is the code that is returned when a long option is found. */ +#define LONG_OPT 2 + +/* The shells recognized. */ +typedef enum {BASH,TCSH} shell_t; + + +/* Some global variables that tells us how to parse. */ +shell_t shell=BASH; /* The shell we generate output for. */ +int quiet_errors=0; /* 0 is not quiet. */ +int quiet_output=0; /* 0 is not quiet. */ +int quote=1; /* 1 is do quote. */ +int alternative=0; /* 0 is getopt_long, 1 is getopt_long_only */ + +/* Function prototypes */ +void *our_malloc(size_t size); +void *our_realloc(void *ptr, size_t size); +const char *normalize(const char *arg); +int generate_output(char * argv[],int argc,const char *optstr, + const struct option *longopts); +int main(int argc, char *argv[]); +void parse_error(const char *message); +void add_long_options(char *options); +void add_longopt(const char *name,int has_arg); +void print_help(void); +void set_shell(const char *new_shell); +void set_initial_shell(void); + +void *our_malloc(size_t size) +{ + void *ret=malloc(size); + if (! ret) { + fprintf(stderr,_("%s: Out of memory!\n"),"getopt"); + exit(3); + } + return(ret); +} + +void *our_realloc(void *ptr, size_t size) +{ + void *ret=realloc(ptr,size); + if (! ret && size) { + fprintf(stderr,_("%s: Out of memory!\n"),"getopt"); + exit(3); + } + return(ret); +} + +/* + * This function 'normalizes' a single argument: it puts single quotes around + * it and escapes other special characters. If quote is false, it just + * returns its argument. + * Bash only needs special treatment for single quotes; tcsh also recognizes + * exclamation marks within single quotes, and nukes whitespace. + * This function returns a pointer to a buffer that is overwritten by + * each call. + */ +const char *normalize(const char *arg) +{ + static char *BUFFER=NULL; + const char *argptr=arg; + char *bufptr; + + if (BUFFER != NULL) + free(BUFFER); + + if (!quote) { /* Just copy arg */ + BUFFER=our_malloc(strlen(arg)+1); + + strcpy(BUFFER,arg); + return BUFFER; + } + + /* Each character in arg may take upto four characters in the result: + For a quote we need a closing quote, a backslash, a quote and an + opening quote! We need also the global opening and closing quote, + and one extra character for '\0'. */ + BUFFER=our_malloc(strlen(arg)*4+3); + + bufptr=BUFFER; + *bufptr++='\''; + + while (*argptr) { + if (*argptr == '\'') { + /* Quote: replace it with: '\'' */ + *bufptr++='\''; + *bufptr++='\\'; + *bufptr++='\''; + *bufptr++='\''; + } else if (shell==TCSH && *argptr=='!') { + /* Exclamation mark: replace it with: \! */ + *bufptr++='\''; + *bufptr++='\\'; + *bufptr++='!'; + *bufptr++='\''; + } else if (shell==TCSH && *argptr=='\n') { + /* Newline: replace it with: \n */ + *bufptr++='\\'; + *bufptr++='n'; + } else if (shell==TCSH && isspace(*argptr)) { + /* Non-newline whitespace: replace it with \ */ + *bufptr++='\''; + *bufptr++='\\'; + *bufptr++=*argptr; + *bufptr++='\''; + } else + /* Just copy */ + *bufptr++=*argptr; + argptr++; + } + *bufptr++='\''; + *bufptr++='\0'; + return BUFFER; +} + +/* + * Generate the output. argv[0] is the program name (used for reporting errors). + * argv[1..] contains the options to be parsed. argc must be the number of + * elements in argv (ie. 1 if there are no options, only the program name), + * optstr must contain the short options, and longopts the long options. + * Other settings are found in global variables. + */ +int generate_output(char * argv[],int argc,const char *optstr, + const struct option *longopts) +{ + int exit_code = 0; /* We assume everything will be OK */ + int opt; + int longindex; + const char *charptr; + + if (quiet_errors) /* No error reporting from getopt(3) */ + opterr=0; + optind=0; /* Reset getopt(3) */ + + while ((opt = (alternative? + getopt_long_only(argc,argv,optstr,longopts,&longindex): + getopt_long(argc,argv,optstr,longopts,&longindex))) + != EOF) + if (opt == '?' || opt == ':' ) + exit_code = 1; + else if (!quiet_output) + { + if (opt == LONG_OPT) { + printf(" --%s",longopts[longindex].name); + if (longopts[longindex].has_arg) + printf(" %s", + normalize(optarg?optarg:"")); + } else if (opt == NON_OPT) + printf(" %s",normalize(optarg)); + else { + printf(" -%c",opt); + charptr = strchr(optstr,opt); + if (charptr != NULL && *++charptr == ':') + printf(" %s", + normalize(optarg?optarg:"")); + } + } + + if (! quiet_output) { + printf(" --"); + while (optind < argc) + printf(" %s",normalize(argv[optind++])); + printf("\n"); + } + return exit_code; +} + +/* + * Report an error when parsing getopt's own arguments. + * If message is NULL, we already sent a message, we just exit with a helpful + * hint. + */ +void parse_error(const char *message) +{ + if (message) + fprintf(stderr,"getopt: %s\n",message); + fputs(_("Try `getopt --help' for more information.\n"),stderr); + exit(2); +} + +static struct option *long_options=NULL; +static int long_options_length=0; /* Length of array */ +static int long_options_nr=0; /* Nr of used elements in array */ +#define LONG_OPTIONS_INCR 10 +#define init_longopt() add_longopt(NULL,0) + +/* Register a long option. The contents of name is copied. */ +void add_longopt(const char *name,int has_arg) +{ + char *tmp; + if (!name) { /* init */ + free(long_options); + long_options=NULL; + long_options_length=0; + long_options_nr=0; + } + + if (long_options_nr == long_options_length) { + long_options_length += LONG_OPTIONS_INCR; + long_options=our_realloc(long_options, + sizeof(struct option) * + long_options_length); + } + + long_options[long_options_nr].name=NULL; + long_options[long_options_nr].has_arg=0; + long_options[long_options_nr].flag=NULL; + long_options[long_options_nr].val=0; + + if (long_options_nr) { /* Not for init! */ + long_options[long_options_nr-1].has_arg=has_arg; + long_options[long_options_nr-1].flag=NULL; + long_options[long_options_nr-1].val=LONG_OPT; + tmp = our_malloc(strlen(name)+1); + strcpy(tmp,name); + long_options[long_options_nr-1].name=tmp; + } + long_options_nr++; +} + + +/* + * Register several long options. options is a string of long options, + * separated by commas or whitespace. + * This nukes options! + */ +void add_long_options(char *options) +{ + int arg_opt; + char *tokptr=strtok(options,", \t\n"); + while (tokptr) { + arg_opt=no_argument; + if (strlen(tokptr) > 0) { + if (tokptr[strlen(tokptr)-1] == ':') { + if (tokptr[strlen(tokptr)-2] == ':') { + tokptr[strlen(tokptr)-2]='\0'; + arg_opt=optional_argument; + } else { + tokptr[strlen(tokptr)-1]='\0'; + arg_opt=required_argument; + } + if (strlen(tokptr) == 0) + parse_error(_("empty long option after " + "-l or --long argument")); + } + add_longopt(tokptr,arg_opt); + } + tokptr=strtok(NULL,", \t\n"); + } +} + +void set_shell(const char *new_shell) +{ + if (!strcmp(new_shell,"bash")) + shell=BASH; + else if (!strcmp(new_shell,"tcsh")) + shell=TCSH; + else if (!strcmp(new_shell,"sh")) + shell=BASH; + else if (!strcmp(new_shell,"csh")) + shell=TCSH; + else + parse_error(_("unknown shell after -s or --shell argument")); +} + +void print_help(void) +{ + fputs(_("Usage: getopt optstring parameters\n"),stderr); + fputs(_(" getopt [options] [--] optstring parameters\n"),stderr); + fputs(_(" getopt [options] -o|--options optstring [options] [--]\n"),stderr); + fputs(_(" parameters\n"),stderr); + fputs(_(" -a, --alternative Allow long options starting with single -\n"),stderr); + fputs(_(" -h, --help This small usage guide\n"),stderr); + fputs(_(" -l, --longoptions=longopts Long options to be recognized\n"),stderr); + fputs(_(" -n, --name=progname The name under which errors are reported\n"),stderr); + fputs(_(" -o, --options=optstring Short options to be recognized\n"),stderr); + fputs(_(" -q, --quiet Disable error reporting by getopt(3)\n"),stderr); + fputs(_(" -Q, --quiet-output No normal output\n"),stderr); + fputs(_(" -s, --shell=shell Set shell quoting conventions\n"),stderr); + fputs(_(" -T, --test Test for getopt(1) version\n"),stderr); + fputs(_(" -u, --unqote Do not quote the output\n"),stderr); + fputs(_(" -V, --version Output version information\n"),stderr); + exit(2); +} + +/* Exit codes: + * 0) No errors, succesful operation. + * 1) getopt(3) returned an error. + * 2) A problem with parameter parsing for getopt(1). + * 3) Internal error, out of memory + * 4) Returned for -T + */ + +static struct option longopts[]={ {"options",required_argument,NULL,'o'}, + {"longoptions",required_argument,NULL,'l'}, + {"quiet",no_argument,NULL,'q'}, + {"quiet-output",no_argument,NULL,'Q'}, + {"shell",required_argument,NULL,'s'}, + {"test",no_argument,NULL,'T'}, + {"unquoted",no_argument,NULL,'u'}, + {"help",no_argument,NULL,'h'}, + {"alternative",no_argument,NULL,'a'}, + {"name",required_argument,NULL,'n'}, + {"version",no_argument,NULL,'V'}, + {NULL,0,NULL,0} + }; + +/* Stop scanning as soon as a non-option argument is found! */ +static const char *shortopts="+ao:l:n:qQs:TuhV"; + +int main(int argc, char *argv[]) +{ + char *optstr=NULL; + char *name=NULL; + int opt; + int compatible=0; + + setlocale(LC_ALL,""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + init_longopt(); + + if (getenv("GETOPT_COMPATIBLE")) + compatible=1; + + if (argc == 1) + { + if (compatible) { + /* For some reason, the original getopt gave no error + when there were no arguments. */ + printf(" --\n"); + exit(0); + } + else + parse_error(_("missing optstring argument")); + } + + if (argv[1][0] != '-' || compatible) { + quote=0; + optstr=our_malloc(strlen(argv[1])+1); + strcpy(optstr,argv[1]+strspn(argv[1],"-+")); + argv[1]=argv[0]; + exit(generate_output(argv+1,argc-1,optstr,long_options)); + } + + while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF) + switch (opt) { + case 'a': + alternative=1; + break; + case 'h': + print_help(); + exit(0); + case 'o': + if (optstr) + free(optstr); + optstr=our_malloc(strlen(optarg)+1); + strcpy(optstr,optarg); + break; + case 'l': + add_long_options(optarg); + break; + case 'n': + if (name) + free(name); + name=our_malloc(strlen(optarg)+1); + strcpy(name,optarg); + break; + case 'q': + quiet_errors=1; + break; + case 'Q': + quiet_output=1; + break; + case 's': + set_shell(optarg); + break; + case 'T': + exit(4); + case 'u': + quote=0; + break; + case 'V': + printf(_("getopt (enhanced) 1.1.0\n")); + exit(0); + case '?': + case ':': + parse_error(NULL); + default: + parse_error(_("internal error, contact the author.")); + } + + if (!optstr) + { + if (optind >= argc) + parse_error(_("missing optstring argument")); + else { + optstr=our_malloc(strlen(argv[optind])+1); + strcpy(optstr,argv[optind]); + optind++; + } + } + if (name) + argv[optind-1]=name; + else + argv[optind-1]=argv[0]; + exit(generate_output(argv+optind-1,argc-optind+1,optstr,long_options)); +} diff --git a/getopt-1.1.0a/gnu/getopt.c b/getopt-1.1.0a/gnu/getopt.c new file mode 100644 index 000000000..59b51cd67 --- /dev/null +++ b/getopt-1.1.0a/gnu/getopt.c @@ -0,0 +1,1050 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 + Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#include +#endif /* GNU C library. */ + +#ifdef VMS +#include +#if HAVE_STRING_H - 0 +#include +#endif +#endif + +#if defined (WIN32) && !defined (__CYGWIN32__) +/* It's not Unix, really. See? Capital letters. */ +#include +#define getpid() GetCurrentProcessId() +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +#ifdef HAVE_LIBINTL_H +# include +# define _(msgid) gettext (msgid) +#else +# define _(msgid) (msgid) +#endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +extern pid_t __libc_pid; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void +__attribute__ ((unused)) +store_args_and_env (int argc, char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +text_set_element (__libc_subinit, store_args_and_env); + +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined (__STDC__) && __STDC__ +static void exchange (char **); +#endif + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#ifdef _LIBC + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len); + memset (&new_str[nonoption_flags_max_len], '\0', + top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined (__STDC__) && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen (orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + { + memcpy (__getopt_nonoption_flags, orig_str, len); + memset (&__getopt_nonoption_flags[len], '\0', + nonoption_flags_max_len - len); + } + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring); + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + + nextchar += strlen (nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf (stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/getopt-1.1.0a/gnu/getopt.h b/getopt-1.1.0a/gnu/getopt.h new file mode 100644 index 000000000..d6ceb0eee --- /dev/null +++ b/getopt-1.1.0a/gnu/getopt.h @@ -0,0 +1,131 @@ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if defined (__STDC__) && __STDC__ +#ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/getopt-1.1.0a/gnu/getopt1.c b/getopt-1.1.0a/gnu/getopt1.c new file mode 100644 index 000000000..4aa8de6f6 --- /dev/null +++ b/getopt-1.1.0a/gnu/getopt1.c @@ -0,0 +1,187 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "getopt.h" + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +#include + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/getopt-1.1.0a/parse.bash b/getopt-1.1.0a/parse.bash new file mode 100644 index 000000000..864fc0add --- /dev/null +++ b/getopt-1.1.0a/parse.bash @@ -0,0 +1,47 @@ +#!/bin/bash + +# A small example program for using the new getopt(1) program. +# This program will only work with bash(1) +# An similar program using the tcsh(1) script language can be found +# as parse.tcsh + +# Example input and output (from the bash prompt): +# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long " +# Option a +# Option c, no argument +# Option c, argument `more' +# Option b, argument ` very long ' +# Remaining arguments: +# --> `par1' +# --> `another arg' +# --> `wow!*\?' + +# Note that we use `"$@"' to let each command-line parameter expand to a +# separate word. The quotes around `$@' are essential! +# We need TEMP as the `eval set --' would nuke the return value of getopt. +TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \ + -n 'example.bash' -- "$@"` + +if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi + +# Note the quotes around `$TEMP': they are essential! +eval set -- "$TEMP" + +while true ; do + case "$1" in + -a|--a-long) echo "Option a" ; shift ;; + -b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;; + -c|--c-long) + # c has an optional argument. As we are in quoted mode, + # an empty parameter will be generated if its optional + # argument is not found. + case "$2" in + "") echo "Option c, no argument"; shift 2 ;; + *) echo "Option c, argument \`$2'" ; shift 2 ;; + esac ;; + --) shift ; break ;; + *) echo "Internal error!" ; exit 1 ;; + esac +done +echo "Remaining arguments:" +for arg do echo '--> '"\`$arg'" ; done diff --git a/getopt-1.1.0a/parse.tcsh b/getopt-1.1.0a/parse.tcsh new file mode 100644 index 000000000..2266d0e64 --- /dev/null +++ b/getopt-1.1.0a/parse.tcsh @@ -0,0 +1,77 @@ +#!/bin/tcsh + +# A small example program for using the new getopt(1) program. +# This program will only work with tcsh(1) +# An similar program using the bash(1) script language can be found +# as parse.bash + +# Example input and output (from the tcsh prompt): +# ./parse.tcsh -a par1 'another arg' --c-long 'wow\!*\?' -cmore -b " very long " +# Option a +# Option c, no argument +# Option c, argument `more' +# Option b, argument ` very long ' +# Remaining arguments: +# --> `par1' +# --> `another arg' +# --> `wow!*\?' + +# Note that we had to escape the exclamation mark in the wow-argument. This +# is _not_ a problem with getopt, but with the tcsh command parsing. If you +# would give the same line from the bash prompt (ie. call ./parse.tcsh), +# you could remove the exclamation mark. + +# This is a bit tricky. We use a temp variable, to be able to check the +# return value of getopt (eval nukes it). argv contains the command arguments +# as a list. The ':q` copies that list without doing any substitutions: +# each element of argv becomes a separate argument for getopt. The braces +# are needed because the result is also a list. +set temp=(`getopt -s tcsh -o ab:c:: --long a-long,b-long:,c-long:: -- $argv:q`) +if ($? != 0) then + echo "Terminating..." >/dev/stderr + exit 1 +endif + +# Now we do the eval part. As the result is a list, we need braces. But they +# must be quoted, because they must be evaluated when the eval is called. +# The 'q` stops doing any silly substitutions. +eval set argv=\($temp:q\) + +while (1) + switch($1:q) + case -a: + case --a-long: + echo "Option a" ; shift + breaksw; + case -b: + case --b-long: + echo "Option b, argument "\`$2:q\' ; shift ; shift + breaksw + case -c: + case --c-long: + # c has an optional argument. As we are in quoted mode, + # an empty parameter will be generated if its optional + # argument is not found. + + if ($2:q == "") then + echo "Option c, no argument" + else + echo "Option c, argument "\`$2:q\' + endif + shift; shift + breaksw + case --: + shift + break + default: + echo "Internal error!" ; exit 1 + endsw +end + +echo "Remaining arguments:" +# foreach el ($argv:q) created problems for some tcsh-versions (at least +# 6.02). So we use another shift-loop here: +while ($#argv > 0) + echo '--> '\`$1:q\' + shift +end diff --git a/getopt-1.1.0a/test.bash b/getopt-1.1.0a/test.bash new file mode 100644 index 000000000..149e1f9b0 --- /dev/null +++ b/getopt-1.1.0a/test.bash @@ -0,0 +1,6 @@ +#!/bin/bash +if `getopt -T >/dev/null 2>&1` ; [ $? = 4 ] ; then + echo "Enhanced getopt(1)" +else + echo "Old getopt(1)" +fi diff --git a/getopt-1.1.0a/test.tcsh b/getopt-1.1.0a/test.tcsh new file mode 100644 index 000000000..d661e767d --- /dev/null +++ b/getopt-1.1.0a/test.tcsh @@ -0,0 +1,7 @@ +#!/bin/tcsh +getopt -T >&/dev/null +if ( $status == 4) then + echo "Enhanced getopt(1)" +else + echo "Old getopt(1)" +endif diff --git a/hwclock/Makefile b/hwclock/Makefile new file mode 100644 index 000000000..70ff6436c --- /dev/null +++ b/hwclock/Makefile @@ -0,0 +1,35 @@ +# Makefile -- Makefile for util-linux Linux utilities +# +include ../make_include +include ../MCONFIG + +# Where to put man pages? + +MAN8= hwclock.8 + +# Where to put binaries? +# See the "install" rule for the links. . . + +SBIN= hwclock + + +all: $(SBIN) + + +hwclock.o: hwclock.c shhopt.h +hwclock.o cmos.o rtc.o kd.o: clock.h +hwclock: hwclock.o shhopt.o cmos.o rtc.o kd.o + +CWFLAGS := $(subst -Wmissing-prototypes,,$(CFLAGS)) + +cmos.o: cmos.c + $(CC) $(CWFLAGS) -c cmos.c -o $@ +# $< expands to clock.h on some systems + +install: all + $(INSTALLDIR) $(SBINDIR) $(BINDIR) $(USRBINDIR) + $(INSTALLBIN) $(SBIN) $(SBINDIR) + $(INSTALLMAN) $(MAN8) $(MAN8DIR) + +clean: + -rm -f *.o *~ core $(SBIN) diff --git a/hwclock/README.aeb b/hwclock/README.aeb new file mode 100644 index 000000000..3955f9050 --- /dev/null +++ b/hwclock/README.aeb @@ -0,0 +1,9 @@ +This directory contains the hwclock stuff as fixed by me. +It should work on all architectures. + +Bryan has backported my changes to his original source, +so the present directory should be superfluous - +however, his code fails on my Sparc. +Will look at it later. + +Andries Brouwer - aeb@cwi.nl diff --git a/hwclock/README.hwclock b/hwclock/README.hwclock new file mode 100644 index 000000000..ba8bc44c3 --- /dev/null +++ b/hwclock/README.hwclock @@ -0,0 +1,27 @@ +Hwclock is a program that runs under Linux and sets and queries the +Hardware Clock, which is often called the Real Time Clock, RTC, or +CMOS clock. + +Sometimes, you need to install hwclock setuid root. If you want users +other than the superuser to be able to display the clock value using the +direct ISA I/O method, install it setuid root. If you have the /dev/rtc +interface on your system or are on a non-ISA system, there's probably +no need for users to use the direct ISA I/O method, so don't bother. + +To install setuid root, do something like this: + + chmod a=rx,u=s /sbin/hwclock + +In any case, hwclock will not allow you to set anything unless you have +the superuser _real_ uid. (This is restriction is not necessary if you +haven't installed setuid root, but it's there for now). + +You may want to preformat and/or compress the man page before installing. + +If you want to build hwclock, just cd to the source directory and invoke +make with no parameters. + +hwclock calls option processing routines in the libsshopt library, +which is part of Sverre H. Huseby's "shhopt" package. You +can find a more authoritative copy of this package on metalab +(ftp://metalab.unc.edu/pub/Linux/libs/shhopt-X.Y). diff --git a/hwclock/README.shhopt-1.1 b/hwclock/README.shhopt-1.1 new file mode 100644 index 000000000..766d6cbdc --- /dev/null +++ b/hwclock/README.shhopt-1.1 @@ -0,0 +1,155 @@ +shhopt - library for parsing command line options. +================================================== + +This is a set of functions for parsing command line options. Both +traditional one-character options, and GNU-style --long-options are +supported. + + +What separates this from traditional getopt? +-------------------------------------------- + +This library does more of the parsing for you. You set up a special +structure describing the names and types of the options you want your +program to support. In the structure you also give addresses of +variables to update or functions to call for the various +options. By calling optParseOptions, all options in argv are parsed +and removed from argv. What is left, are the non-optional arguments to +your program. + +The down-side of this, is that you won't be able to make a program +where the position of the options between the non-options are +significant. + + +Usage +----- + +To see how to use this library, take a look at the sample program +example.c. + +A brief explanation: + +To parse your command line, you need to create and initialize an array +of optStruct's. Each element in the array describes a long and short +version of an option and specifies what type of option it is and how +to handle it. + +The structure fields (see also shhopt.h): + + `shortName' is the short option name without the leading '-'. + + `longName' is the long option name without the leading "--". + + `type' specifies what type of option this is. (Does it expect an + argument? Is it a flag? If it takes an argument,what type should + it be?) + + `arg' is either a function to be called with the argument from + the commandline, or a pointer to a location in which to store + the value. + + `flags' indicates whether `arg' points to a function or a storage + location. + +The different argument types: + + `OPT_END' flags this as the last element in the options array. + + `OPT_FLAG' indicates an option that takes no arguments. If `arg' is + not a function pointer, the value of `arg' will be set to 1 if + this flag is found on the command line. + + `OPT_STRING' expects a string argument. + + `OPT_INT' expects an int argument. + + `OPT_UINT' expects an unsigned int argument. + + `OPT_LONG' expects a long argument. + + `OPT_ULONG' expects an unsigned long argument. + +The different flag types: + + `OPT_CALLFUNC' indicates that `arg' is a function pointer. If this + is not given, `arg' is taken as a pointer to a variable. + + +Notes +----- + +* A dash (`-') by itself is not taken as any kind of an option, as + several programs use this to indicate the special files stdin and + stdout. It is thus left as a normal argument to the program. + +* Two dashes (`--') as an argument, is taken to mean that the rest of + the arguments should not be scanned for options. This simplifies + giving names of files that start with a dash. + +* Short (one-character) options accept parameters in two ways, either + directly following the option in the same argv-entry, or in the next + argv-entry: + + -sPARAMETER + -s PARAMETER + +* Long options accept parameters in two ways: + + --long-option=PARAMETER + --long-option PARAMETER + + To follow the GNU-tradition, your program documentation should use + the first form. + +* Several one-character options may be combined after a single + dash. If any of the options requires a parameter, the rest of the + string is taken as this parameter. If there is no "rest of the + string", the next argument is taken as the parameter. + +* There is no support for floating point (double) arguments to + options. This is to avoid unnecessary linking with the math + library. See example.c for how to get around this by writing a + function converting a string argument to a double. + + +Portability +----------- + +If your libc lacks strtoul, you will need to link with GNU's -liberty, +that may be found by anonymous ftp to prep.ai.mit.edu:/pub/gnu + +The library has (more or less recently) been compiled and `tested' on +the following systems: + + IRIX Release 5.3 IP22 + Linux 1.2.9 + SunOS Release 4.1.3_U1 (-liberty needed) + ULTRIX V4.4 (Rev. 69) + +All compilations were done using GNU's gcc, and GNU's make. + + +Author +------ + +The program is written by + + Sverre H. Huseby + Maridalsvn. 122, leil. 101 + N-0461 Oslo + Norway + + sverrehu@ifi.uio.no + http://www.ifi.uio.no/~sverrehu/ + +You can use and copy this for free. If you decide to use it, please do +me three small favours: + + 1. Tell me! (E-mail, postcard, letter, whatever. If you wish + to give me something, please send a bottle of your + favourite beer (making this BeerWare)) + 2. Let your friends and favourite download site have a copy! + (with all files intact, please..) + 3. Report any bugs you find! + diff --git a/hwclock/adjtime.patch b/hwclock/adjtime.patch new file mode 100644 index 000000000..81d0430fd --- /dev/null +++ b/hwclock/adjtime.patch @@ -0,0 +1,302 @@ +From ao112@rgfn.epcc.edu Fri Mar 19 06:27:26 1999 +Received: from rgfn.epcc.edu (rgfn.epcc.edu [208.136.234.19]) by hera.cwi.nl with ESMTP + id GAA27711 for ; Fri, 19 Mar 1999 06:27:23 +0100 (MET) +Received: (from ao112@localhost) + by rgfn.epcc.edu (8.8.8/8.8.8) id WAA16797; + Thu, 18 Mar 1999 22:27:19 -0700 (MST) +Date: Thu, 18 Mar 1999 22:27:19 -0700 (MST) +Message-Id: <199903190527.WAA16797@rgfn.epcc.edu> +From: ao112@rgfn.epcc.edu (James P. Rutledge) +To: Andries.Brouwer@cwi.nl +Subject: Re: hwclock patch for drift_factor calculation improvement +Reply-To: ao112@rgfn.epcc.edu +Status: R + + + +> +>Could you perhaps make your patch relative to +>util-linux-2.9n (found in ftp.cwi.nl/pub/aeb/util-linux/util-linux-2.9n.tar.gz) +>? +> +>(The hwclock stuff has changed quite a bit since 2.9g.) +> +>Andries +> + +Andries; + +Per your request, the patch has been modified for util-linux version +2.9n, from the version for 2.9g. + +The program "hwclock" (version 2.4c) could give more accurate +values for the drift factor that it places in the file "/etc/adjtime". + +A patch to improve the accuracy is included. + +I have incorporated some error sources which were not compensated +for into the drift factor calculation (performed when the "--set" +or the "--systohc" option is used) to make it more accurate. +In particular, the sync delay between the desired set time and the +start of the hardware clock second, and the expected drift since the +last hardware clock adjustment are now accounted for in the drift +factor calculation. + +With this patch, if at any time an adjust operation is attempted and +the hardware clock is found to be not valid, then the calibration +and adjustment time is set to zero to insure that if the hardware +clock should coincidentally return to validity, a calibration is not +done with bad history data (hardware clock info bad) and an adjust is +not attempted on bad (but now passing validity test) hardware clock +data. (With this patch, a previous calibration time of zero causes +the calibration time to initialize with the current time, when the +hardware clock is set, but no change is made to the drift factor, +so in effect, an initial calibration is started over while the previous +drift factor is retained.) + +Also, the behavior in the case of an initially missing "/etc/adjtime" +file or such a file produced by the predecessor "clock" program has +been slightly improved as follows: + + With this patch, if the file exists but was produced by "clock" + and, thus, is given a zero calibration time, the drift factor is + not updated upon the first calibration by "hwclock", but is left alone + and is only changed by subsequent calibrations. + + With this patch, if the file does not exist and, thus, is given + a zero calibration time, the drift factor is set to zero upon the + first calibration by "hwclock" and is then changed, as appropriate, by + subsequent calibrations. + + Also, with this patch, an "--adjust" operation against a non-existent + "/etc/adjtime" file or one which has zero as the last adjustment + time will not change the hardware clock setting. + +A context diff for a patch to the file "hwclock.c" in the directory +"util-linux-2.9n/clock" is appended. +To use the patch, "cd" to the directory "util-linux-2.9n/clock". +Run "patch < bug-report", where "bug-report" is the file name of +this mail message, to get new file "hwclock.c" which contains the proposed +new version. This patch is, of course, submitted per the GPL and the +appropriate "NO WARRANTY OF ANY KIND" and "USE AT YOUR OWN RISK" +disclaimers apply. + +Note that the patch presumptuously changes the "hwclock.c" version +number from 2.4c to 2.4c1 in "hwclock.c". + +Jim + +------------------ Patch file follows ---------------------------- +*** hwclock.c Thu Mar 18 22:04:01 1999 +--- new-hwclock.c Thu Mar 18 22:03:18 1999 +*************** +*** 76,86 **** + + #include "clock.h" + #include "../version.h" + + #define MYNAME "hwclock" +! #define VERSION "2.4c" + + char *progname = MYNAME; + + /* The struct that holds our hardware access routines */ + struct clock_ops *ur; +--- 76,86 ---- + + #include "clock.h" + #include "../version.h" + + #define MYNAME "hwclock" +! #define VERSION "2.4c1" + + char *progname = MYNAME; + + /* The struct that holds our hardware access routines */ + struct clock_ops *ur; +*************** +*** 581,601 **** + + + static void + adjust_drift_factor(struct adjtime *adjtime_p, + const time_t nowtime, +! const bool hclock_valid, const time_t hclocktime ) { + /*--------------------------------------------------------------------------- + Update the drift factor in <*adjtime_p> to reflect the fact that the + Hardware Clock was calibrated to and before that was set + to . + +- We assume that the user has been doing regular drift adjustments +- using the drift factor in the adjtime file, so if and +- are different, that means the adjustment factor isn't +- quite right. +- + We record in the adjtime file the time at which we last calibrated + the clock so we can compute the drift rate each time we calibrate. + + EXCEPT: if is false, assume Hardware Clock was not set + before to anything meaningful and regular adjustments have not been +--- 581,598 ---- + + + static void + adjust_drift_factor(struct adjtime *adjtime_p, + const time_t nowtime, +! const bool hclock_valid, +! const time_t hclocktime, +! const float sync_delay ) { + /*--------------------------------------------------------------------------- + Update the drift factor in <*adjtime_p> to reflect the fact that the + Hardware Clock was calibrated to and before that was set + to . + + We record in the adjtime file the time at which we last calibrated + the clock so we can compute the drift rate each time we calibrate. + + EXCEPT: if is false, assume Hardware Clock was not set + before to anything meaningful and regular adjustments have not been +*************** +*** 604,629 **** + ----------------------------------------------------------------------------*/ + if (!hclock_valid) { + if (debug) + printf("Not adjusting drift factor because the Hardware Clock " + "previously contained garbage.\n"); + } else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) { + if (debug) + printf("Not adjusting drift factor because it has been less than a " + "day since the last calibration.\n"); + } else { +! const float factor_adjust = +! ((float) (nowtime - hclocktime) +! / (hclocktime - adjtime_p->last_calib_time)) +! * 24 * 60 * 60; + + if (debug) +! printf("Clock drifted %d seconds in the past %d seconds " + "in spite of a drift factor of %f seconds/day.\n" + "Adjusting drift factor by %f seconds/day\n", +! (int) (nowtime - hclocktime), +! (int) (hclocktime - adjtime_p->last_calib_time), + adjtime_p->drift_factor, + factor_adjust ); + + adjtime_p->drift_factor += factor_adjust; + } +--- 601,642 ---- + ----------------------------------------------------------------------------*/ + if (!hclock_valid) { + if (debug) + printf("Not adjusting drift factor because the Hardware Clock " + "previously contained garbage.\n"); ++ } else if (adjtime_p->last_calib_time == 0) { ++ if (debug) ++ printf("Not adjusting drift factor because last calibration " ++ "time is zero,\nso history is bad and calibration startover " ++ "is necessary.\n"); + } else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) { + if (debug) + printf("Not adjusting drift factor because it has been less than a " + "day since the last calibration.\n"); + } else { +! const float sec_per_day = 24.0 * 60.0 * 60.0; +! float atime_per_htime; /* adjusted time units per hardware time unit */ +! float adj_days; /* days since last adjustment (in hardware clock time) */ +! float cal_days; /* days since last calibration (in hardware clock time) */ +! float exp_drift; /* expected drift (sec) since last adjustment */ +! float unc_drift; /* uncorrected drift (sec) since last calibration */ +! float factor_adjust; /* amount to add to previous drift factor */ +! atime_per_htime = 1.0 + adjtime_p->drift_factor / sec_per_day; +! adj_days = (float)(hclocktime - adjtime_p->last_adj_time) / sec_per_day; +! exp_drift = adj_days * adjtime_p->drift_factor + adjtime_p->not_adjusted; +! unc_drift = (float)(nowtime - hclocktime) + sync_delay - exp_drift; +! cal_days = ((float)(adjtime_p->last_adj_time - adjtime_p->last_calib_time) +! + adjtime_p->not_adjusted) / (sec_per_day * atime_per_htime) +! + adj_days; +! factor_adjust = unc_drift / cal_days; + + if (debug) +! printf("Clock drifted %.1f seconds in the past %d seconds " + "in spite of a drift factor of %f seconds/day.\n" + "Adjusting drift factor by %f seconds/day\n", +! unc_drift, +! (int) (nowtime - adjtime_p->last_calib_time), + adjtime_p->drift_factor, + factor_adjust ); + + adjtime_p->drift_factor += factor_adjust; + } +*************** +*** 764,773 **** +--- 777,794 ---- + + ----------------------------------------------------------------------------*/ + if (!hclock_valid) { + fprintf(stderr, "The Hardware Clock does not contain a valid time, " + "so we cannot adjust it.\n"); ++ adjtime_p->last_calib_time = 0; /* calibration startover is required */ ++ adjtime_p->last_adj_time = 0; ++ adjtime_p->not_adjusted = 0; ++ adjtime_p->dirty = TRUE; ++ } else if (adjtime_p->last_adj_time == 0) { ++ if (debug) ++ printf("Not setting clock because last adjustment time is zero, " ++ "so history is bad."); + } else { + int adjustment; + /* Number of seconds we must insert in the Hardware Clock */ + float retro; + /* Fraction of second we have to remove from clock after inserting +*************** +*** 878,888 **** + time_diff(read_time, startup_time)); + *retcode_p = 0; + } else if (set) { + set_hardware_clock_exact(set_time, startup_time, + universal, testing); +! adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime); + *retcode_p = 0; + } else if (adjust) { + do_adjustment(&adjtime, hclock_valid, hclocktime, + read_time, universal, testing); + *retcode_p = 0; +--- 899,910 ---- + time_diff(read_time, startup_time)); + *retcode_p = 0; + } else if (set) { + set_hardware_clock_exact(set_time, startup_time, + universal, testing); +! adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime, +! time_diff(read_time, startup_time)); + *retcode_p = 0; + } else if (adjust) { + do_adjustment(&adjtime, hclock_valid, hclocktime, + read_time, universal, testing); + *retcode_p = 0; +*************** +*** 898,908 **** + + set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, + universal, testing); + *retcode_p = 0; + adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, +! hclocktime); + } else if (hctosys) { + rc = set_system_clock(hclock_valid, hclocktime, testing); + if (rc != 0) { + printf("Unable to set system clock.\n"); + *retcode_p = 1; +--- 920,930 ---- + + set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, + universal, testing); + *retcode_p = 0; + adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, +! hclocktime, (float)(read_time.tv_usec / 1E6)); + } else if (hctosys) { + rc = set_system_clock(hclock_valid, hclocktime, testing); + if (rc != 0) { + printf("Unable to set system clock.\n"); + *retcode_p = 1; + diff --git a/hwclock/clock-ppc.c b/hwclock/clock-ppc.c new file mode 100644 index 000000000..6d8969adb --- /dev/null +++ b/hwclock/clock-ppc.c @@ -0,0 +1,459 @@ +/* +From t-matsuu@protein.osaka-u.ac.jp Sat Jan 22 13:43:20 2000 +Date: Sat, 22 Jan 2000 21:42:54 +0900 (JST) +To: Andries.Brouwer@cwi.nl +Subject: Please merge the source for PPC +From: MATSUURA Takanori + +Even now, it is used clock-1.1 based source on Linux for PowerPC +architecture, attached on this mail. + +Please merge this source in main util-linux source. + +But I'm not an author of this source, but Paul Mackerras. +http://linuxcare.com.au/paulus/ +shows details of him. + +MATSUURA Takanori @ Division of Protein Chemistry, + Institute for Protein Research, Osaka University, Japan +E-Mail: t-matsuu@protein.osaka-u.ac.jp +Web Page: http://www.protein.osaka-u.ac.jp/chemistry/matsuura/ +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* + * Adapted for Power Macintosh by Paul Mackerras. + */ + +/* V1.0 + * CMOS clock manipulation - Charles Hedrick, hedrick@cs.rutgers.edu, Apr 1992 + * + * clock [-u] -r - read cmos clock + * clock [-u] -w - write cmos clock from system time + * clock [-u] -s - set system time from cmos clock + * clock [-u] -a - set system time from cmos clock, adjust the time to + * correct for systematic error, and put it back to the cmos. + * -u indicates cmos clock is kept in universal time + * + * The program is designed to run setuid, since we need to be able to + * write to the CUDA. + * + ********************* + * V1.1 + * Modified for clock adjustments - Rob Hooft, hooft@chem.ruu.nl, Nov 1992 + * Also moved error messages to stderr. The program now uses getopt. + * Changed some exit codes. Made 'gcc 2.3 -Wall' happy. + * + * I think a small explanation of the adjustment routine should be given + * here. The problem with my machine is that its CMOS clock is 10 seconds + * per day slow. With this version of clock.c, and my '/etc/rc.local' + * reading '/etc/clock -au' instead of '/etc/clock -u -s', this error + * is automatically corrected at every boot. + * + * To do this job, the program reads and writes the file '/etc/adjtime' + * to determine the correction, and to save its data. In this file are + * three numbers: + * + * 1) the correction in seconds per day (So if your clock runs 5 + * seconds per day fast, the first number should read -5.0) + * 2) the number of seconds since 1/1/1970 the last time the program was + * used. + * 3) the remaining part of a second which was leftover after the last + * adjustment + * + * Installation and use of this program: + * + * a) create a file '/etc/adjtime' containing as the first and only line: + * '0.0 0 0.0' + * b) run 'clock -au' or 'clock -a', depending on whether your cmos is in + * universal or local time. This updates the second number. + * c) set your system time using the 'date' command. + * d) update your cmos time using 'clock -wu' or 'clock -w' + * e) replace the first number in /etc/adjtime by your correction. + * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local' + * + * If the adjustment doesn't work for you, try contacting me by E-mail. + * + ****** + * V1.2 + * + * Applied patches by Harald Koenig (koenig@nova.tat.physik.uni-tuebingen.de) + * Patched and indented by Rob Hooft (hooft@EMBL-Heidelberg.DE) + * + * A free quote from a MAIL-message (with spelling corrections): + * + * "I found the explanation and solution for the CMOS reading 0xff problem + * in the 0.99pl13c (ALPHA) kernel: the RTC goes offline for a small amount + * of time for updating. Solution is included in the kernel source + * (linux/kernel/time.c)." + * + * "I modified clock.c to fix this problem and added an option (now default, + * look for USE_INLINE_ASM_IO) that I/O instructions are used as inline + * code and not via /dev/port (still possible via #undef ...)." + * + * With the new code, which is partially taken from the kernel sources, + * the CMOS clock handling looks much more "official". + * Thanks Harald (and Torsten for the kernel code)! + * + ****** + * V1.3 + * Canges from alan@spri.levels.unisa.edu.au (Alan Modra): + * a) Fix a few typos in comments and remove reference to making + * clock -u a cron job. The kernel adjusts cmos time every 11 + * minutes - see kernel/sched.c and kernel/time.c set_rtc_mmss(). + * This means we should really have a cron job updating + * /etc/adjtime every 11 mins (set last_time to the current time + * and not_adjusted to ???). + * b) Swapped arguments of outb() to agree with asm/io.h macro of the + * same name. Use outb() from asm/io.h as it's slightly better. + * c) Changed CMOS_READ and CMOS_WRITE to inline functions. Inserted + * cli()..sti() pairs in appropriate places to prevent possible + * errors, and changed ioperm() call to iopl() to allow cli. + * d) Moved some variables around to localise them a bit. + * e) Fixed bug with clock -ua or clock -us that cleared environment + * variable TZ. This fix also cured the annoying display of bogus + * day of week on a number of machines. (Use mktime(), ctime() + * rather than asctime() ) + * f) Use settimeofday() rather than stime(). This one is important + * as it sets the kernel's timezone offset, which is returned by + * gettimeofday(), and used for display of MSDOS and OS2 file + * times. + * g) faith@cs.unc.edu added -D flag for debugging + * + * V1.4: alan@SPRI.Levels.UniSA.Edu.Au (Alan Modra) + * Wed Feb 8 12:29:08 1995, fix for years > 2000. + * faith@cs.unc.edu added -v option to print version. + * + * August 1996 Tom Dyas (tdyas@eden.rutgers.edu) + * Converted to be compatible with the SPARC /dev/rtc driver. + * + */ + +#define VERSION "1.4" + +/* Here the information for time adjustments is kept. */ +#define ADJPATH "/etc/adjtime" + +/* Apparently the RTC on PowerMacs stores seconds since 1 Jan 1904 */ +#define RTC_OFFSET 2082844800 + +/* used for debugging the code. */ +/*#define KEEP_OFF */ + +/* Globals */ +int readit = 0; +int adjustit = 0; +int writeit = 0; +int setit = 0; +int universal = 0; +int debug = 0; + +time_t mkgmtime(struct tm *); + +volatile void +usage ( void ) +{ + (void) fprintf (stderr, + "clock [-u] -r|w|s|a|v\n" + " r: read and print CMOS clock\n" + " w: write CMOS clock from system time\n" + " s: set system time from CMOS clock\n" + " a: get system time and adjust CMOS clock\n" + " u: CMOS clock is in universal time\n" + " v: print version (" VERSION ") and exit\n" + ); + exit(EXIT_FAILURE); +} + +int adb_fd; + +void +adb_init ( void ) +{ + adb_fd = open ("/dev/adb", 2); + if (adb_fd < 0) + { + perror ("unable to open /dev/adb read/write : "); + exit(EXIT_FAILURE); + } +} + +unsigned char get_packet[2] = { (unsigned char) CUDA_PACKET, + (unsigned char) CUDA_GET_TIME }; +unsigned char set_packet[6] = { (unsigned char) CUDA_PACKET, + (unsigned char) CUDA_SET_TIME }; + +int +main (int argc, char **argv ) +{ + struct tm tm, *tmp; + time_t systime; + time_t last_time; + time_t clock_time; + int i, arg; + double factor; + double not_adjusted; + int adjustment = 0; + /* unsigned char save_control, save_freq_select; */ + unsigned char reply[16]; + + while ((arg = getopt (argc, argv, "rwsuaDv")) != -1) + { + switch (arg) + { + case 'r': + readit = 1; + break; + case 'w': + writeit = 1; + break; + case 's': + setit = 1; + break; + case 'u': + universal = 1; + break; + case 'a': + adjustit = 1; + break; + case 'D': + debug = 1; + break; + case 'v': + (void) fprintf( stderr, "clock " VERSION "\n" ); + exit(EXIT_SUCCESS); + default: + usage (); + } + } + + /* If we are in MkLinux do not even bother trying to set the clock */ + if(!access("/proc/osfmach3/version", R_OK)) + { // We're running MkLinux + if ( readit | writeit | setit | adjustit ) + printf("You must change the clock setting in MacOS.\n"); + exit(0); + } + + if (readit + writeit + setit + adjustit > 1) + usage (); /* only allow one of these */ + + if (!(readit | writeit | setit | adjustit)) /* default to read */ + readit = 1; + + adb_init (); + + if (adjustit) + { /* Read adjustment parameters first */ + FILE *adj; + if ((adj = fopen (ADJPATH, "r")) == NULL) + { + perror (ADJPATH); + exit(EXIT_FAILURE); + } + if (fscanf (adj, "%lf %d %lf", &factor, (int *) (&last_time), + ¬_adjusted) < 0) + { + perror (ADJPATH); + exit(EXIT_FAILURE); + } + (void) fclose (adj); + if (debug) (void) printf( + "Last adjustment done at %d seconds after 1/1/1970\n", + (int) last_time); + } + + if (readit || setit || adjustit) + { + int ii; + + if (write(adb_fd, get_packet, sizeof(get_packet)) < 0) { + perror("write adb"); + exit(EXIT_FAILURE); + } + ii = (int) read(adb_fd, reply, sizeof(reply)); + if (ii < 0) { + perror("read adb"); + exit(EXIT_FAILURE); + } + if (ii != 7) + (void) fprintf(stderr, + "Warning: bad reply length from CUDA (%d)\n", ii); + clock_time = (time_t) ((reply[3] << 24) + (reply[4] << 16) + + (reply[5] << 8)) + (time_t) reply[6]; + clock_time -= RTC_OFFSET; + + if (universal) { + systime = clock_time; + } else { + tm = *gmtime(&clock_time); + (void) printf("time in rtc is %s", asctime(&tm)); + tm.tm_isdst = -1; /* don't know whether it's DST */ + systime = mktime(&tm); + } + } + + if (readit) + { + (void) printf ("%s", ctime (&systime )); + } + + if (setit || adjustit) + { + struct timeval tv; + struct timezone tz; + +/* program is designed to run setuid, be secure! */ + + if (getuid () != 0) + { + (void) fprintf (stderr, + "Sorry, must be root to set or adjust time\n"); + exit(EXIT_FAILURE); + } + + if (adjustit) + { /* the actual adjustment */ + double exact_adjustment; + + exact_adjustment = ((double) (systime - last_time)) + * factor / (24 * 60 * 60) + + not_adjusted; + if (exact_adjustment > 0.) + adjustment = (int) (exact_adjustment + 0.5); + else + adjustment = (int) (exact_adjustment - 0.5); + not_adjusted = exact_adjustment - (double) adjustment; + systime += adjustment; + if (debug) { + (void) printf ("Time since last adjustment is %d seconds\n", + (int) (systime - last_time)); + (void) printf ("Adjusting time by %d seconds\n", + adjustment); + (void) printf ("remaining adjustment is %.3f seconds\n", + not_adjusted); + } + } +#ifndef KEEP_OFF + tv.tv_sec = systime; + tv.tv_usec = 0; + tz.tz_minuteswest = timezone / 60; + tz.tz_dsttime = daylight; + + if (settimeofday (&tv, &tz) != 0) + { + (void) fprintf (stderr, + "Unable to set time -- probably you are not root\n"); + exit(EXIT_FAILURE); + } + + if (debug) { + (void) printf( "Called settimeofday:\n" ); + (void) printf( "\ttv.tv_sec = %ld, tv.tv_usec = %ld\n", + tv.tv_sec, tv.tv_usec ); + (void) printf( "\ttz.tz_minuteswest = %d, tz.tz_dsttime = %d\n", + tz.tz_minuteswest, tz.tz_dsttime ); + } +#endif + } + + if (writeit || (adjustit && adjustment != 0)) + { + systime = time (NULL); + + if (universal) { + clock_time = systime; + + } else { + tmp = localtime(&systime); + clock_time = mkgmtime(tmp); + } + + clock_time += RTC_OFFSET; + set_packet[2] = clock_time >> 24; + set_packet[3] = clock_time >> 16; + set_packet[4] = clock_time >> 8; + set_packet[5] = (unsigned char) clock_time; + + if (write(adb_fd, set_packet, sizeof(set_packet)) < 0) { + perror("write adb (set)"); + exit(EXIT_FAILURE); + } + i = (int) read(adb_fd, reply, sizeof(reply)); + if (debug) { + int j; + (void) printf("set reply %d bytes:", i); + for (j = 0; j < i; ++j) + (void) printf(" %.2x", (unsigned int) reply[j]); + (void) printf("\n"); + } + if (i != 3 || reply[1] != (unsigned char) 0) + (void) fprintf(stderr, "Warning: error %d setting RTC\n", + (int) reply[1]); + + if (debug) { + clock_time -= RTC_OFFSET; + (void) printf("set RTC to %s", asctime(gmtime(&clock_time))); + } + } + else + if (debug) (void) printf ("CMOS clock unchanged.\n"); + /* Save data for next 'adjustit' call */ + if (adjustit) + { + FILE *adj; + if ((adj = fopen (ADJPATH, "w")) == NULL) + { + perror (ADJPATH); + exit(EXIT_FAILURE); + } + (void) fprintf (adj, "%f %d %f\n", factor, (int) systime, not_adjusted); + (void) fclose (adj); + } + exit(EXIT_SUCCESS); +} + +/* Stolen from linux/arch/i386/kernel/time.c. */ +/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year/100+year/400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines were long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +time_t mkgmtime(struct tm *tm) +{ + int mon = tm->tm_mon + 1; + int year = tm->tm_year + 1900; + + if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + return ((( + (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12) + + tm->tm_mday + year*365 - 719499 + )*24 + tm->tm_hour /* now have hours */ + )*60 + tm->tm_min /* now have minutes */ + )*60 + tm->tm_sec; /* finally seconds */ +} diff --git a/hwclock/clock.h b/hwclock/clock.h new file mode 100644 index 000000000..91d3df801 --- /dev/null +++ b/hwclock/clock.h @@ -0,0 +1,35 @@ +#include +#include +#include +#include /* for errno, EPERM, EINVAL, ENOENT */ +#include + +struct clock_ops { + char *interface_name; + int (*get_permissions)(void); + int (*read_hardware_clock)(struct tm *tm); + int (*set_hardware_clock)(const struct tm *tm); + int (*synchronize_to_clock_tick)(void); +}; + +extern struct clock_ops *probe_for_cmos_clock(void); +extern struct clock_ops *probe_for_rtc_clock(void); +extern struct clock_ops *probe_for_kd_clock(void); + +typedef int bool; +#define TRUE 1 +#define FALSE 0 + +/* hwclock.c */ +extern char *progname; +extern int debug; +extern int epoch_option; +extern void outsyserr(char *msg, ...); + +/* cmos.c */ +extern void set_cmos_epoch(int ARCconsole, int SRM); +extern void set_cmos_access(int Jensen, int funky_toy); + +/* rtc.c */ +extern int get_epoch_rtc(unsigned long *epoch, int silent); +extern int set_epoch_rtc(unsigned long epoch); diff --git a/hwclock/cmos.c b/hwclock/cmos.c new file mode 100644 index 000000000..4fc82d798 --- /dev/null +++ b/hwclock/cmos.c @@ -0,0 +1,612 @@ +/* + * i386 CMOS starts out with 14 bytes clock data + * alpha has something similar, but with details + * depending on the machine type. + * + * byte 0: seconds (0-59) + * byte 2: minutes (0-59) + * byte 4: hours (0-23 in 24hr mode, + * 1-12 in 12hr mode, with high bit unset/set if am/pm) + * byte 6: weekday (1-7, Sunday=1) + * byte 7: day of the month (1-31) + * byte 8: month (1-12) + * byte 9: year (0-99) + * Numbers are stored in BCD/binary if bit 2 of byte 11 is unset/set + * The clock is in 12hr/24hr mode if bit 1 of byte 11 is unset/set + * The clock is undefined (being updated) if bit 7 of byte 10 is set. + * The clock is frozen (to be updated) by setting bit 7 of byte 11 + * Bit 7 of byte 14 indicates whether the CMOS clock is reliable: + * it is 1 if RTC power has been good since this bit was last read; + * it is 0 when the battery is dead and system power has been off. + * + * Avoid setting the RTC clock within 2 seconds of the day rollover + * that starts a new month or enters daylight saving time. + * + * The century situation is messy: + * Usually byte 50 (0x32) gives the century (in BCD, so 19 or 20 hex), + * but IBM PS/2 has (part of) a checksum there and uses byte 55 (0x37). + * Sometimes byte 127 (0x7f) or Bank 1, byte 0x48 gives the century. + * The original RTC will not access any century byte; some modern + * versions will. If a modern RTC or BIOS increments the century byte + * it may go from 0x19 to 0x20, but in some buggy cases 0x1a is produced. + */ + +/* + * A struct tm has int fields + * tm_sec (0-59, 60 or 61 only for leap seconds) + * tm_min (0-59) + * tm_hour (0-23) + * tm_mday (1-31) + * tm_mon (0-11) + * tm_year (number of years since 1900) + * tm_wday (0-6, 0=Sunday) + * tm_yday (0-365) + * tm_isdst (>0: yes, 0: no, <0: unknown) + */ + +#include /* for geteuid() */ +#include /* for O_RDWR */ + +#include "nls.h" + +#if defined(__i386__) || defined(__alpha__) +#include /* for inb, outb */ +#else +void outb(int a, int b){} +int inb(int c){ return 0; } +#endif + +#include "clock.h" + +#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) +#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) + +#define TM_EPOCH 1900 +int cmos_epoch = 1900; /* 1980 for an alpha in ARC console time */ + /* One also sees 1952 (Digital Unix) + and 1958 (ALPHA_PRE_V1_2_SRM_CONSOLE) */ + +/* Martin Ostermann writes: +The problem with the Jensen is twofold: First, it has the clock at a +different address. Secondly, it has a distinction beween "local" and +normal bus addresses. The local ones pertain to the hardware integrated +into the chipset, like serial/parallel ports and of course, the RTC. +Those need to be addressed differently. This is handled fine in the kernel, +and it's not a problem, since this usually gets totally optimized by the +compile. But the i/o routines of (g)libc lack this support so far. +The result of this is, that the old clock program worked only on the +Jensen when USE_DEV_PORT was defined, but not with the normal inb/outb +functions. + */ +int use_dev_port = 0; /* 1 for Jensen */ +int dev_port_fd; +unsigned short clock_ctl_addr = 0x70; /* 0x170 for Jensen */ +unsigned short clock_data_addr = 0x71; /* 0x171 for Jensen */ + + +int century_byte = 0; /* 0: don't access a century byte + 50 (0x32): usual PC value + 55 (0x37): PS/2 */ + +#ifdef __alpha__ +int funkyTOY = 0; /* 1 for PC164/LX164/SX164 type alpha */ +#endif + +#ifdef __alpha + +static int +is_in_cpuinfo(char *fmt, char *str) +{ + FILE *cpuinfo; + char field[256]; + char format[256]; + int found = 0; + + sprintf(format, "%s : %s", fmt, "%255s"); + + if ((cpuinfo = fopen ("/proc/cpuinfo", "r")) != NULL) { + while (!feof(cpuinfo)) { + if (fscanf (cpuinfo, format, field) == 1) { + if (strncmp(field, str, strlen(str)) == 0) + found = 1; + break; + } + fgets (field, 256, cpuinfo); + } + fclose(cpuinfo); + } + return found; +} + +/* Set cmos_epoch, either from user options, or by asking the kernel, + or by looking at /proc/cpu_info */ +void +set_cmos_epoch(int ARCconsole, int SRM) { + unsigned long epoch; + + /* Believe the user */ + if (epoch_option != -1) { + cmos_epoch = epoch_option; + return; + } + + if (ARCconsole) + cmos_epoch = 1980; + + if (ARCconsole || SRM) + return; + + + /* If we can ask the kernel, we don't need guessing from /proc/cpuinfo */ + if (get_epoch_rtc(&epoch, 1) == 0) { + cmos_epoch = epoch; + return; + } + + /* The kernel source today says: read the year. If it is + in 11-43 then the epoch is 1980 (this covers 1991-2023). + Otherwise, if it is less than 96 then the epoch is 1952 + (this covers 1952-1962 and 1996-2047). Otherwise, the epoch + is 1900 (this covers 1996-1999, or rather 1996-2155). */ + + + /* See whether we are dealing with SRM or MILO, as they have + different "epoch" ideas. */ + if (is_in_cpuinfo("system serial number", "MILO")) { + ARCconsole = 1; + if (debug) printf (_("booted from MILO\n")); + } + + /* See whether we are dealing with a RUFFIAN aka Alpha PC-164 UX (or BX), + as they have REALLY different TOY (TimeOfYear) format: BCD, and not + an ARC-style epoch. + BCD is detected dynamically, but we must NOT adjust like ARC. */ + if (ARCconsole && is_in_cpuinfo("system type", "Ruffian")) { + ARCconsole = 0; + if (debug) printf (_("Ruffian BCD clock\n")); + } + + if (ARCconsole) + cmos_epoch = 1980; +} + +void +set_cmos_access(int Jensen, int funky_toy) { + + /* See whether we're dealing with a Jensen---it has a weird I/O + system. DEC was just learning how to build Alpha PCs. */ + if (Jensen || is_in_cpuinfo("system type", "Jensen")) { + use_dev_port = 1; + clock_ctl_addr = 0x170; + clock_data_addr = 0x171; + if (debug) printf (_("clockport adjusted to 0x%x\n"), clock_ctl_addr); + } + + /* see whether we are dealing with PC164/LX164/SX164, as they have a TOY + that must be accessed differently to work correctly. */ + /* Nautilus stuff reported by Neoklis Kyriazis */ + if (funky_toy || + is_in_cpuinfo("system variation", "PC164") || + is_in_cpuinfo("system variation", "LX164") || + is_in_cpuinfo("system variation", "SX164") || + is_in_cpuinfo("system type", "Nautilus")) { + funkyTOY = 1; + if (debug) printf (_("funky TOY!\n")); + } +} +#endif + + + + +#ifdef __i386__ + +/* + * Try to do CMOS access atomically, so that no other processes + * can get a time slice while we are reading or setting the clock. + * (Also, if the kernel time is synchronized with an external source, + * the kernel itself will fiddle with the RTC every 11 minutes.) + */ + +static unsigned long +atomic(const char *name, unsigned long (*op)(unsigned long), + unsigned long arg) +{ + unsigned long v; + __asm__ volatile ("cli"); + v = (*op)(arg); + __asm__ volatile ("sti"); + return v; +} + +#elif __alpha__ + +/* + * The Alpha doesn't allow user-level code to disable interrupts (for + * good reasons). Instead, we ensure atomic operation by performing + * the operation and checking whether the high 32 bits of the cycle + * counter changed. If they did, a context switch must have occurred + * and we redo the operation. As long as the operation is reasonably + * short, it will complete atomically, eventually. + */ + +static unsigned long +atomic(const char *name, unsigned long (*op)(unsigned long), + unsigned long arg) +{ + unsigned long ts1, ts2, n, v; + + for (n = 0; n < 1000; ++n) { + asm volatile ("rpcc %0" : "r="(ts1)); + v = (*op)(arg); + asm volatile ("rpcc %0" : "r="(ts2)); + + if ((ts1 ^ ts2) >> 32 == 0) { + return v; + } + } + fprintf(stderr, _("%s: atomic %s failed for 1000 iterations!"), progname, name); + exit(1); +} + +#else + +/* + * Hmmh, this isn't very atomic. Maybe we should force an error + * instead? + */ +static unsigned long +atomic(const char *name, unsigned long (*op)(unsigned long), + unsigned long arg) +{ + return (*op)(arg); +} + +#endif + + +static inline +unsigned long cmos_read(unsigned long reg) +{ + if (use_dev_port) { + unsigned char v = reg | 0x80; + lseek(dev_port_fd, clock_ctl_addr, 0); + write(dev_port_fd, &v, 1); + lseek(dev_port_fd, clock_data_addr, 0); + read(dev_port_fd, &v, 1); + return v; + } else { + /* We only want to read CMOS data, but unfortunately + writing to bit 7 disables (1) or enables (0) NMI; + since this bit is read-only we have to guess the old status. + Various docs suggest that one should disable NMI while + reading/writing CMOS data, and enable it again afterwards. + This would yield the sequence + outb (reg | 0x80, 0x70); + val = inb(0x71); + outb (0x0d, 0x70); // 0x0d: random read-only location + Other docs state that "any write to 0x70 should be followed + by an action to 0x71 or the RTC wil be left in an unknown state". + Most docs say that it doesnt matter at all what one does. + */ + /* bit 0x80: disable NMI while reading - should we? + Let us follow the kernel and not disable. + Called only with 0 <= reg < 128 */ + outb (reg, clock_ctl_addr); + return inb (clock_data_addr); + } +} + +static inline +unsigned long cmos_write(unsigned long reg, unsigned long val) +{ + if (use_dev_port) { + unsigned char v = reg | 0x80; + lseek(dev_port_fd, clock_ctl_addr, 0); + write(dev_port_fd, &v, 1); + v = (val & 0xff); + lseek(dev_port_fd, clock_data_addr, 0); + write(dev_port_fd, &v, 1); + } else { + outb (reg, clock_ctl_addr); + outb (val, clock_data_addr); + } + return 0; +} + +unsigned long cmos_set_time(unsigned long arg) +{ + unsigned char save_control, save_freq_select, pmbit = 0; + struct tm tm = *(struct tm *) arg; + unsigned int century; + +/* + * CMOS byte 10 (clock status register A) has 3 bitfields: + * bit 7: 1 if data invalid, update in progress (read-only bit) + * (this is raised 224 us before the actual update starts) + * 6-4 select base frequency + * 010: 32768 Hz time base (default) + * 111: reset + * all other combinations are manufacturer-dependent + * (e.g.: DS1287: 010 = start oscillator, anything else = stop) + * 3-0 rate selection bits for interrupt + * 0000 none (may stop RTC) + * 0001, 0010 give same frequency as 1000, 1001 + * 0011 122 microseconds (minimum, 8192 Hz) + * .... each increase by 1 halves the frequency, doubles the period + * 1111 500 milliseconds (maximum, 2 Hz) + * 0110 976.562 microseconds (default 1024 Hz) + */ + + save_control = cmos_read (11); /* tell the clock it's being set */ + cmos_write (11, (save_control | 0x80)); + save_freq_select = cmos_read (10); /* stop and reset prescaler */ + cmos_write (10, (save_freq_select | 0x70)); + + tm.tm_year += TM_EPOCH; + century = tm.tm_year/100; + tm.tm_year -= cmos_epoch; + tm.tm_year %= 100; + tm.tm_mon += 1; + tm.tm_wday += 1; + + if (!(save_control & 0x02)) { /* 12hr mode; the default is 24hr mode */ + if (tm.tm_hour == 0) + tm.tm_hour = 24; + if (tm.tm_hour > 12) { + tm.tm_hour -= 12; + pmbit = 0x80; + } + } + + if (!(save_control & 0x04)) { /* BCD mode - the default */ + BIN_TO_BCD(tm.tm_sec); + BIN_TO_BCD(tm.tm_min); + BIN_TO_BCD(tm.tm_hour); + BIN_TO_BCD(tm.tm_wday); + BIN_TO_BCD(tm.tm_mday); + BIN_TO_BCD(tm.tm_mon); + BIN_TO_BCD(tm.tm_year); + BIN_TO_BCD(century); + } + + cmos_write (0, tm.tm_sec); + cmos_write (2, tm.tm_min); + cmos_write (4, tm.tm_hour | pmbit); + cmos_write (6, tm.tm_wday); + cmos_write (7, tm.tm_mday); + cmos_write (8, tm.tm_mon); + cmos_write (9, tm.tm_year); + if (century_byte) + cmos_write (century_byte, century); + + + /* The kernel sources, linux/arch/i386/kernel/time.c, have the + following comment: + + The following flags have to be released exactly in this order, + otherwise the DS12887 (popular MC146818A clone with integrated + battery and quartz) will not reset the oscillator and will not + update precisely 500 ms later. You won't find this mentioned + in the Dallas Semiconductor data sheets, but who believes data + sheets anyway ... -- Markus Kuhn + */ + + cmos_write (11, save_control); + cmos_write (10, save_freq_select); + return 0; +} + +static int +hclock_read(unsigned long reg) { + return atomic("clock read", cmos_read, (reg)); +} + +static void +hclock_set_time(const struct tm *tm) { + atomic("set time", cmos_set_time, (unsigned long)(tm)); +} + +static inline int +cmos_clock_busy(void) { + return +#ifdef __alpha__ + /* poll bit 4 (UF) of Control Register C */ + funkyTOY ? (hclock_read(12) & 0x10) : +#endif + /* poll bit 7 (UIP) of Control Register A */ + (hclock_read(10) & 0x80); +} + + +static int +synchronize_to_clock_tick_cmos(void) { + int i; + + /* Wait for rise. Should be within a second, but in case something + weird happens, we have a limit on this loop to reduce the impact + of this failure. + */ + for (i = 0; !cmos_clock_busy(); i++) + if (i >= 10000000) + return 1; + + /* Wait for fall. Should be within 2.228 ms. */ + for (i = 0; cmos_clock_busy(); i++) + if (i >= 1000000) + return 1; + return 0; +} + + + +static int +read_hardware_clock_cmos(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via argument. + Assume we have an ISA machine and read the clock directly with CPU I/O + instructions. + + This function is not totally reliable. It takes a finite and + unpredictable amount of time to execute the code below. During that + time, the clock may change and we may even read an invalid value in + the middle of an update. We do a few checks to minimize this + possibility, but only the kernel can actually read the clock + properly, since it can execute code in a short and predictable + amount of time (by turning of interrupts). + + In practice, the chance of this function returning the wrong time is + extremely remote. + +-----------------------------------------------------------------------------*/ + bool got_time = FALSE; + unsigned char status, pmbit; + + status = pmbit = 0; /* just for gcc */ + + while (!got_time) { + /* Bit 7 of Byte 10 of the Hardware Clock value is the Update In Progress + (UIP) bit, which is on while and 244 uS before the Hardware Clock + updates itself. It updates the counters individually, so reading + them during an update would produce garbage. The update takes 2mS, + so we could be spinning here that long waiting for this bit to turn + off. + + Furthermore, it is pathologically possible for us to be in this + code so long that even if the UIP bit is not on at first, the + clock has changed while we were running. We check for that too, + and if it happens, we start over. + */ + + if (!cmos_clock_busy()) { + /* No clock update in progress, go ahead and read */ + tm->tm_sec = hclock_read(0); + tm->tm_min = hclock_read(2); + tm->tm_hour = hclock_read(4); + tm->tm_wday = hclock_read(6); + tm->tm_mday = hclock_read(7); + tm->tm_mon = hclock_read(8); + tm->tm_year = hclock_read(9); + status = hclock_read(11); +#if 0 + if (century_byte) + century = hclock_read(century_byte); +#endif + + /* Unless the clock changed while we were reading, consider this + a good clock read . + */ + if (tm->tm_sec == hclock_read (0)) + got_time = TRUE; + } + /* Yes, in theory we could have been running for 60 seconds and + the above test wouldn't work! + */ + } + + if (!(status & 0x04)) { /* BCD mode - the default */ + BCD_TO_BIN(tm->tm_sec); + BCD_TO_BIN(tm->tm_min); + pmbit = (tm->tm_hour & 0x80); + tm->tm_hour &= 0x7f; + BCD_TO_BIN(tm->tm_hour); + BCD_TO_BIN(tm->tm_wday); + BCD_TO_BIN(tm->tm_mday); + BCD_TO_BIN(tm->tm_mon); + BCD_TO_BIN(tm->tm_year); +#if 0 + BCD_TO_BIN(century); +#endif + } + + /* We don't use the century byte of the Hardware Clock + since we don't know its address (usually 50 or 55). + Here, we follow the advice of the X/Open Base Working Group: + "if century is not specified, then values in the range [69-99] + refer to years in the twentieth century (1969 to 1999 inclusive), + and values in the range [00-68] refer to years in the twenty-first + century (2000 to 2068 inclusive)." + */ + + tm->tm_wday -= 1; + tm->tm_mon -= 1; + tm->tm_year += (cmos_epoch - TM_EPOCH); + if (tm->tm_year < 69) + tm->tm_year += 100; + if (pmbit) { + tm->tm_hour += 12; + if (tm->tm_hour == 24) + tm->tm_hour = 0; + } + + tm->tm_isdst = -1; /* don't know whether it's daylight */ + return 0; +} + + + +static int +set_hardware_clock_cmos(const struct tm *new_broken_time) { + + hclock_set_time(new_broken_time); + return 0; +} + +static int +i386_iopl(const int level) { +#if defined(__i386__) || defined(__alpha__) + extern int iopl(const int lvl); + return iopl(level); +#else + return -2; +#endif +} + +static int +get_permissions_cmos(void) { + int rc; + + if (use_dev_port) { + if ((dev_port_fd = open("/dev/port", O_RDWR)) < 0) { + int errsv = errno; + fprintf(stderr, _("Cannot open /dev/port: %s"), strerror(errsv)); + rc = 1; + } else + rc = 0; + } else { + rc = i386_iopl(3); + if (rc == -2) { + fprintf(stderr, _("I failed to get permission because I didnt try.\n")); + } else if (rc != 0) { + rc = errno; + fprintf(stderr, _("%s is unable to get I/O port access: " + "the iopl(3) call failed.\n"), progname); + if(rc == EPERM && geteuid()) + fprintf(stderr, _("Probably you need root privileges.\n")); + } + } + return rc ? 1 : 0; +} + +static struct clock_ops cmos = { + "direct I/O instructions to ISA clock", + get_permissions_cmos, + read_hardware_clock_cmos, + set_hardware_clock_cmos, + synchronize_to_clock_tick_cmos, +}; + + +/* return &cmos if cmos clock present, NULL otherwise */ +/* choose this construction to avoid gcc messages about unused variables */ + +struct clock_ops * +probe_for_cmos_clock(void){ + int have_cmos = +#if defined(__i386__) || defined(__alpha__) + TRUE; +#else + FALSE; +#endif + return have_cmos ? &cmos : NULL; +} diff --git a/hwclock/hwclock.8 b/hwclock/hwclock.8 new file mode 100644 index 000000000..7e4106d45 --- /dev/null +++ b/hwclock/hwclock.8 @@ -0,0 +1,595 @@ +.TH HWCLOCK 8 "02 March 1998" +.SH NAME +hwclock \- query and set the hardware clock (RTC) +.SH SYNOPSIS +.BR "hwclock \-r" " or " "hwclock \-\-show" +.br +.BR "hwclock \-w" " or " "hwclock \-\-systohc" +.br +.BR "hwclock \-s" " or " "hwclock \-\-hctosys" +.br +.BR "hwclock \-a" " or " "hwclock \-\-adjust" +.br +.BR "hwclock \-v" " or " "hwclock \-\-version" +.br +.B "hwclock \-\-set \-\-date=newdate" +.br +.B "hwclock \-\-getepoch" +.br +.B "hwclock \-\-setepoch \-\-epoch=year" +.PP +other options: +.PP +.B "[\-u|\-\-utc] \-\-localtime \-\-directisa \-\-test \-\-debug" +.PP +and arcane options for DEC Alpha: +.PP +.B "[\-A|\-\-arc] [\-J|\-\-jensen] [\-S|\-\-srm] [\-F|\-\-funky-toy]" +.PP +Minimum unique abbreviations of all options are acceptable. +.PP +Also, equivalent options \-r, \-w, \-s, \-a, \-v, \-u, +\-D, \-A, \-J, \-S, and \-F are accepted for compatibility +with the program "clock", while \-h asks for a help message. + +.SH DESCRIPTION +.B hwclock +is a tool for accessing the Hardware Clock. You can display the +current time, set the Hardware Clock to a specified time, set the +Hardware Clock to the System Time, and set the System Time from the +Hardware Clock. +.PP +You can also run +.B hwclock +periodically to insert or remove time from the Hardware Clock to +compensate for systematic drift (where the clock consistently gains or +loses time at a certain rate if left to run). + +.SH OPTIONS +You need exactly one of the following options to tell +.B hwclock +what function to perform: +.PP +.TP +.B \-\-show +Read the Hardware Clock and print the time on Standard Output. +The time is always in local time, even if you keep your Hardware Clock +in Coordinated Universal Time. See the +.B \-\-utc +option. + +.TP +.B \-\-set +Set the Hardware Clock to the time given by the +.B \-\-date +option. +.TP +.B \-\-hctosys +Set the System Time from the Hardware Clock. + +Also set the kernel's timezone value to the local timezone +as indicated by the TZ environment variable and/or +.IR /usr/lib/zoneinfo , +as +.BR tzset (3) +would interpret them. +The obsolete tz_dsttime field of the kernel's timezone value is set +to DST_NONE. (For details on what this field used to mean, see +.BR settimeofday (2).) + +This is a good option to use in one of the system startup scripts. +.TP +.B \-\-systohc +Set the Hardware Clock to the current System Time. +.TP +.B \-\-adjust +Add or subtract time from the Hardware Clock to account for systematic +drift since the last time the clock was set or adjusted. See discussion +below. +.TP +.B \-\-getepoch +Print out standard output the kernel's Hardware Clock epoch value. +This is the number of years into AD to which a zero year value in the +Hardware Clock refers. For example, if you are using the convention +that the year counter in your Hardware Clock contains the number of +full years since 1952, then the kernel's Hardware Counter epoch value +must be 1952. + +This epoch value is used whenever hwclock reads or sets the Hardware Clock. +.TP +.B \-\-setepoch +Set the kernel's Hardware Clock epoch value to the value specified by the +.B \-\-epoch +option. See the +.B \-\-getepoch +option for details. +.TP +.B \-\-version +Print the version of +.B hwclock +on Standard Output. +.br +You need the following option if you specify +.B \-\-set +option. Otherwise, it is ignored. +.TP +.B \-\-date=date_string +Specifies the time to which to set the Hardware Clock. The value of this +option is an argument to the +.BR date (1) +program. For example, +.sp +.I hwclock --set --date="9/22/96 16:45:05" +.sp +The argument is in local time, even if you keep your Hardware Clock in +Coordinated Universal time. See the +.B \-\-utc +option. + +.TP +.B \-\-epoch=year +Specifies the year which is the beginning of the Hardware Clock's +epoch. I.e. the number of years into AD to which a zero value in the +Hardware Clock's year counter refers. + +For example, +.sp +.I hwclock --setepoch --epoch=1952 + +.PP +The following options apply to most functions. +.TP +.B \-\-utc +.TP +.B \-\-localtime +Indicates that the Hardware Clock is kept in Coordinated Universal +Time or local time, respectively. It is your choice whether to keep +your clock in UTC or local time, but nothing in the clock tells which +you've chosen. So this option is how you give that information to +.BR hwclock . + +If you specify the wrong one of these options (or specify neither and +take a wrong default), both setting and querying of the Hardware Clock +will be messed up. + +If you specify neither +.B \-\-utc +nor +.B \-\-localtime +, the default is whichever was specified the last time +.B hwclock +was used to set the clock (i.e. hwclock was successfully run with the +.B \-\-set +, +.B \-\-systohc +, +or +.B \-\-adjust +options), as recorded in the adjtime file. If the adjtime file doesn't +exist, the default is local time. + +.TP +.B \-\-directisa +is meaningful only on an ISA machine or an Alpha (which implements enough +of ISA to be, roughly speaking, an ISA machine for +.BR hwclock 's +purposes). For other machines, it has no effect. This option tells +.B hwclock +to use explicit I/O instructions to access the Hardware Clock. +Without this option, +.B hwclock +will try to use the /dev/rtc device (which it assumes to be driven by the +rtc device driver). If it is unable to open the device (for read), it will +use the explicit I/O instructions anyway. + +The rtc device driver was new in Linux Release 2. +.TP +.B \-\-badyear +Indicates that the Hardware Clock is incapable of storing years outside +the range 1994-1999. There is a problem in some BIOSes (almost all +Award BIOSes made between 4/26/94 and 5/31/95) wherein they are unable +to deal with years after 1999. If one attempts to set the year-of-century +value to something less than 94 (or 95 in some cases), the value that +actually gets set is 94 (or 95). Thus, if you have one of these machines, +.B hwclock +cannot set the year after 1999 and cannot use the value of the clock as +the true time in the normal way. + +To compensate for this (without your getting a BIOS update, which would +definitely be preferable), always use +.B \-\-badyear +if you have one of these machines. When +.B hwclock +knows it's working with a brain-damaged clock, it ignores the year part of +the Hardware Clock value and instead tries to guess the year based on the +last calibrated date in the adjtime file, by assuming that that date is +within the past year. For this to work, you had better do a +.I hwclock \-\-set +or +.I hwclock \-\-systohc +at least once a year! + +Though +.B hwclock +ignores the year value when it reads the Hardware Clock, it sets the +year value when it sets the clock. It sets it to 1995, 1996, 1997, or +1998, whichever one has the same position in the leap year cycle as +the true year. That way, the Hardware Clock inserts leap days where +they belong. Again, if you let the Hardware Clock run for more than a +year without setting it, this scheme could be defeated and you could +end up losing a day. + +.B hwclock +warns you that you probably need +.B \-\-badyear +whenever it finds your Hardware Clock set to 1994 or 1995. + +.TP +.B \-\-srm +.TP +.B \-\-arc +.TP +.B \-\-jensen +.TP +.B \-\-funky\-toy +These options all tell +.B hwclock +what kind of Alpha machine you have. They +are invalid if you don't have an Alpha and shouldn't be necessary if you +do, because +.B hwclock +should be able to determine by itself what it's +running on, at least when +.I /proc +is mounted. These options make it possible for +.B hwclock +to work even when +its environment does not conform to its expectations and thus it cannot +accurately determine what sort of system it is running on. If you think +hwclock is incorrectly determining the system's characteristics, try +running with the +.B \-\-debug +option to see what conclusions the program is +reaching and how. If you find you need one of these options to make +.B hwclock +work, contact the +.B hwclock +maintainer to see if the program can be improved to detect your system +automatically. + +.B \-\-jensen +means you are running on a Jensen model. + +.B \-\-arc +means your machine uses epoch 1980 in its hardware clock, as is commonly +the case for machines on ARC console (but Ruffians have epoch 1900). + +.B \-\-srm +means your machine uses epoch 1900 in its hardware clock, as is commonly +the case for machines on SRM console. + +.B \-\-funky\-toy +means that on your machine, one has to use the UF bit instead +of the UIP bit in the Hardware Clock to detect a time transition. "Toy" +in the option name refers to the Time Of Year facility of the machine. + + +.TP +.B \-\-test +Do everything except actually updating the Hardware Clock or anything +else. This is useful, especially in conjunction with +.B \-\-debug, +in learning about +.B hwclock. +.TP +.B \-\-debug +Display a lot of information about what +.B hwclock +is doing internally. Some of its function is complex and this output +can help you understand how the program works. + + +.SH NOTES + + +.SH Clocks in a Linux System +.PP +There are two main clocks in a Linux system: +.PP +.B The Hardware Clock: +This is a clock that runs independently of any control program running +in the CPU and even when the machine is powered off. + +On an ISA system, this clock is specified as part of the ISA standard. +The control program can read or set this clock to a whole second, but +the control program can also detect the edges of the 1 second clock +ticks, so the clock actually has virtually infinite precision. +.PP +This clock is commonly called the hardware clock, the real time clock, +the RTC, the BIOS clock, and the CMOS clock. Hardware Clock, in its +capitalized form, was coined for use by +.B hwclock +because all of the other names are inappropriate to the point of being +misleading. +.PP +.B The System Time: +This is the time kept by a clock inside the Linux kernel and driven by +a timer interrupt. (On an ISA machine, the timer interrupt is part of +the ISA standard). It has meaning only while Linux is running on the +machine. The System Time is the number of seconds since 00:00:00 +January 1, 1970 UTC (or more succinctly, the number of seconds since +1969). The System Time is not an integer, though. It has virtually +infinite precision. +.PP +The System Time is the time that matters. The Hardware Clock's basic +purpose in a Linux system is to keep time when Linux is not running. You +initialize the System Time to the time from the Hardware Clock when Linux +starts up, and then never use the Hardware Clock again. Note that in DOS, +for which ISA was designed, the Hardware Clock is the only real time clock. +.PP +It is important that the System Time not have any discontinuities such as +would happen if you used the +.BR date (1L) +program to set it while the system is running. You can, however, do whatever +you want to the Hardware Clock while the system is running, and the next +time Linux starts up, it will do so with the adjusted time from the Hardware +Clock. You can also use the program +.BR adjtimex (8) +to smoothly adjust the System Time while the system runs. +.PP +A Linux kernel maintains a concept of a local timezone for the system. +But don't be misled -- almost nobody cares what timezone the kernel +thinks it is in. Instead, programs that care about the timezone +(perhaps because they want to display a local time for you) almost +always use a more traditional method of determining the timezone: They +use the TZ environment variable and/or the /usr/local/timezone +directory, as explained in the man page for tzset(3). However, some +programs and fringe parts of the Linux kernel such as filesystems use +the kernel timezone value. An example is the vfat filesystem. If the +kernel timezone value is wrong, the vfat filesystem will report and +set the wrong timestamps on files. +.PP +.B hwclock +sets the kernel timezone to the value indicated by TZ and/or +/usr/local/timezone when you set the System Time using the +.B \-\-hctosys +option. +.PP +The timezone value actually consists of two parts: 1) a field +tz_minuteswest indicating how many minutes local time (not adjusted +for DST) lags behind UTC, and 2) a field tz_dsttime indicating +the type of Daylight Savings Time (DST) convention that is in effect +in the locality at the present time. +This second field is not used under Linux and is always zero. +(See also +.BR settimeofday (2).) + +.SH How hwclock Accesses the Hardware Clock +.PP +.B hwclock +Uses many different ways to get and set Hardware Clock values. +The most normal way is to do I/O to the device special file /dev/rtc, +which is presumed to be driven by the rtc device driver. However, +this method is not always available. For one thing, the rtc driver is +a relatively recent addition to Linux. Older systems don't have it. +Also, though there are versions of the rtc driver that work on DEC +Alphas, there appear to be plenty of Alphas on which the rtc driver +does not work (a common symptom is hwclock hanging). +.PP +On older systems, the method of accessing the Hardware Clock depends on +the system hardware. +.PP +On an ISA system, +.B hwclock +can directly access the "CMOS memory" registers that +constitute the clock, by doing I/O to Ports 0x70 and 0x71. It does +this with actual I/O instructions and consequently can only do it if +running with superuser effective userid. (In the case of a Jensen +Alpha, there is no way for +.B hwclock +to execute those I/O instructions, and so it uses instead the +/dev/port device special file, which provides almost as low-level an +interface to the I/O subsystem). + +This is a really poor method of accessing the clock, for all the +reasons that user space programs are generally not supposed to do +direct I/O and disable interrupts. Hwclock provides it because it is +the only method available on ISA and Alpha systems which don't have +working rtc device drivers available. + +.PP +On an m68k system, +.B hwclock +can access the clock via the console driver, via the device special +file /dev/tty1. +.PP +.B hwclock +tries to use /dev/rtc. If it is compiled for a kernel that doesn't have +that function or it is unable to open /dev/rtc, +.B hwclock +will fall back to another method, if available. On an ISA or Alpha +machine, you can force +.B hwclock +to use the direct manipulation of the CMOS registers without even trying +.I /dev/rtc +by specifying the \-\-directisa option. + + +.SH The Adjust Function +.PP +The Hardware Clock is usually not very accurate. However, much of its +inaccuracy is completely predictable - it gains or loses the same amount +of time every day. This is called systematic drift. +.BR hwclock 's +"adjust" function lets you make systematic corrections to correct the +systematic drift. +.PP +It works like this: +.B hwclock +keeps a file, +.I /etc/adjtime, +that keeps some historical information. This is called the adjtime file. +.PP +Suppose you start with no adjtime file. You issue a +.I hwclock \-\-set +command to set the Hardware Clock to the true current time. +.B Hwclock +creates the adjtime file and records in it the current time as the +last time the clock was calibrated. +5 days later, the clock has gained 10 seconds, so you issue another +.I hwclock \-\-set +command to set it back 10 seconds. +.B Hwclock +updates the adjtime file to show the current time as the last time the +clock was calibrated, and records 2 seconds per day as the systematic +drift rate. 24 hours go by, and then you issue a +.I hwclock \-\-adjust +command. +.B Hwclock +consults the adjtime file and sees that the clock gains 2 seconds per +day when left alone and that it has been left alone for exactly one +day. So it subtracts 2 seconds from the Hardware Clock. It then +records the current time as the last time the clock was adjusted. +Another 24 hours goes by and you issue another +.I hwclock \-\-adjust. +.B Hwclock +does the same thing: subtracts 2 seconds and updates the adjtime file +with the current time as the last time the clock was adjusted. +.PP +Every time you calibrate (set) the clock (using +.I \-\-set +or +.I \-\-systohc +), +.B hwclock +recalculates the systematic drift rate based on how long it has been +since the last calibration, how long it has been since the last +adjustment, what drift rate was assumed in any intervening +adjustments, and the amount by which the clock is presently off. +.PP +A small amount of error creeps in any time +.B hwclock +sets the clock, so it refrains from making an adjustment that would be +less than 1 second. Later on, when you request an adjustment again, +the accumulated drift will be more than a second and +.B hwclock +will do the adjustment then. +.PP +It is good to do a +.I hwclock \-\-adjust +just before the +.I hwclock \-\-hctosys +at system startup time, and maybe periodically while the system is +running via cron. +.PP +The adjtime file, while named for its historical purpose of controlling +adjustments only, actually contains other information for use by hwclock +in remembering information from one invocation to the next. +.PP +The format of the adjtime file is, in ASCII: +.PP +Line 1: 3 numbers, separated by blanks: 1) systematic drift rate in +seconds per day, floating point decimal; 2) Resulting number of +seconds since 1969 UTC of most recent adjustment or calibration, +decimal integer; 3) zero (for compatibility with +.BR clock (8)) +as a decimal integer. +.PP +Line 2: 1 number: Resulting number of seconds since 1969 UTC of most +recent calibration. Zero if there has been no calibration yet or it +is known that any previous calibration is moot (for example, because +the Hardware Clock has been found, since that calibration, not to +contain a valid time). This is a decimal integer. +.PP +Line 3: "UTC" or "LOCAL". Tells whether the Hardware Clock is set to +Coordinated Universal Time or local time. You can always override this +value with options on the +.B hwclock +command line. +.PP +You can use an adjtime file that was previously used with the +.BR clock (8) +program with +.B hwclock. + + +.SH "Automatic Hardware Clock Synchronization By the Kernel" + +You should be aware of another way that the Hardware Clock is kept +synchronized in some systems. The Linux kernel has a mode wherein it +copies the System Time to the Hardware Clock every 11 minutes. +This is a good mode to use when you are using something sophisticated +like ntp to keep your System Time synchronized. (ntp is a way to keep +your System Time synchronized either to a time server somewhere on the +network or to a radio clock hooked up to your system. See RFC 1305). + +This mode (we'll call it "11 minute mode") is off until something +turns it on. The ntp daemon xntpd is one thing that turns it on. You +can turn it off by running anything, including +.IR "hwclock \-\-hctosys" , +that sets the System Time the old fashioned way. + +To see if it is on or +off, use the command +.I adjtimex \-\-print +and look at the value of "status". If the "64" bit of this number +(expressed in binary) equal to 0, 11 minute mode is on. Otherwise, it +is off. + +If your system runs with 11 minute mode on, don't use +.I hwclock \-\-adjust +or +.IR "hwclock \-\-hctosys" . +You'll just make a mess. It is acceptable to use a +.I hwclock \-\-hctosys +at startup time to get a reasonable System Time until your system is +able to set the System Time from the external source and start 11 +minute mode. + + +.SH ISA Hardware Clock Century value + +There is some sort of standard that defines CMOS memory Byte 50 on an ISA +machine as an indicator of what century it is. +.B hwclock +does not use or set that byte because there are some machines that +don't define the byte that way, and it really isn't necessary anyway, +since the year-of-century does a good job of implying which century it +is. + +If you have a bona fide use for a CMOS century byte, contact the +.B hwclock +maintainer; an option may be appropriate. + +Note that this section is only relevant when you are using the "direct +ISA" method of accessing the Hardware Clock. + + + +.SH "ENVIRONMENT VARIABLES" +.I TZ + +.SH FILES +.I /etc/adjtime +.I /usr/lib/zoneinfo/ +.I /dev/rtc +.I /dev/port +.I /dev/tty1 +.I /proc/cpuinfo + +.SH "SEE ALSO" +.BR adjtimex (8), +.BR date (1), +.BR gettimeofday (2), +.BR settimeofday (2), +.BR crontab (1), +.BR tzset (3) + +.SH AUTHORS +Written By Bryan Henderson, September 1996 (bryanh@giraffe-data.com), +based on work done on the +.I clock +program by Charles Hedrick, Rob Hooft, and Harald Koenig. +See the source code for complete history and credits. + + diff --git a/hwclock/hwclock.c b/hwclock/hwclock.c new file mode 100644 index 000000000..3a3a94e1a --- /dev/null +++ b/hwclock/hwclock.c @@ -0,0 +1,1448 @@ +/* + * hwclock.c + * + * clock.c was written by Charles Hedrick, hedrick@cs.rutgers.edu, Apr 1992 + * Modified for clock adjustments - Rob Hooft , Nov 1992 + * Improvements by Harald Koenig + * and Alan Modra . + * + * Major rewrite by Bryan Henderson , 96.09.19. + * The new program is called hwclock. New features: + * - You can set the hardware clock without also modifying the system clock. + * - You can read and set the clock with finer than 1 second precision. + * - When you set the clock, hwclock automatically refigures the drift + * rate, based on how far off the clock was before you set it. + * + * Reshuffled things, added sparc code, and re-added alpha stuff + * by David Mosberger + * and Jay Estabrook + * and Martin Ostermann , aeb@cwi.nl, 990212. + * + * Fix for Award 2094 bug, Dave Coffin (dcoffin@shore.net) 11/12/98 + * Change of local time handling, Stefan Ring + * + * Distributed under GPL + */ + +/* + * clock [-u] -r - read hardware clock + * clock [-u] -w - write hardware clock from system time + * clock [-u] -s - set system time from hardware clock + * clock [-u] -a - set system time from hardware clock, adjust the time + * to correct for systematic error, and write it back to + * the hardware clock + * -u indicates cmos clock is kept in universal time + * -A indicates cmos clock is kept in Alpha ARC console time (0 == 1980) + * -J indicates we're dealing with a Jensen (early DEC Alpha PC) + */ + +/* + * Explanation of `adjusting' (Rob Hooft): + * + * The problem with my machine is that its CMOS clock is 10 seconds + * per day slow. With this version of clock.c, and my '/etc/rc.local' + * reading '/etc/clock -au' instead of '/etc/clock -u -s', this error + * is automatically corrected at every boot. + * + * To do this job, the program reads and writes the file '/etc/adjtime' + * to determine the correction, and to save its data. In this file are + * three numbers: + * + * 1) the correction in seconds per day. (So if your clock runs 5 + * seconds per day fast, the first number should read -5.0) + * 2) the number of seconds since 1/1/1970 the last time the program + * was used + * 3) the remaining part of a second which was leftover after the last + * adjustment + * + * Installation and use of this program: + * + * a) create a file '/etc/adjtime' containing as the first and only line: + * '0.0 0 0.0' + * b) run 'clock -au' or 'clock -a', depending on whether your cmos is in + * universal or local time. This updates the second number. + * c) set your system time using the 'date' command. + * d) update your cmos time using 'clock -wu' or 'clock -w' + * e) replace the first number in /etc/adjtime by your correction. + * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local' + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "shhopt.h" +#include "clock.h" +#include "nls.h" + +#define MYNAME "hwclock" +#define VERSION "2.4c" + +char *progname = MYNAME; + +/* The struct that holds our hardware access routines */ +struct clock_ops *ur; + +#define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1)); + +/* Here the information for time adjustments is kept. */ +#define ADJPATH "/etc/adjtime" + +/* Store the date here when "badyear" flag is set. */ +#define LASTDATE "/var/lib/lastdate" + +struct adjtime { + /* This is information we keep in the adjtime file that tells us how + to do drift corrections. Elements are all straight from the + adjtime file, so see documentation of that file for details. + Exception is , which is an indication that what's in this + structure is not what's in the disk file (because it has been + updated since read from the disk file). + */ + bool dirty; + /* line 1 */ + float drift_factor; + time_t last_adj_time; + float not_adjusted; + /* line 2 */ + time_t last_calib_time; + /* The most recent time that we set the clock from an external + authority (as opposed to just doing a drift adjustment) */ + /* line 3 */ + enum a_local_utc {LOCAL, UTC, UNKNOWN} local_utc; + /* To which time zone, local or UTC, we most recently set the + hardware clock. */ +}; + +bool debug; + /* We are running in debug mode, wherein we put a lot of information about + what we're doing to standard output. */ + +bool badyear; + /* Workaround for Award 4.50g BIOS bug: keep the year in a file. */ + +int epoch_option = -1; + /* User-specified epoch, used when rtc fails to return epoch. */ + +/* + * Almost all Award BIOS's made between 04/26/94 and 05/31/95 + * have a nasty bug limiting the RTC year byte to the range 94-99. + * Any year between 2000 and 2093 gets changed to 2094, every time + * you start the system. + * With the --badyear option, we write the date to file and hope + * that the file is updated at least once a year. + * I recommend putting this command "hwclock --badyear" in the monthly + * crontab, just to be safe. -- Dave Coffin 11/12/98 + */ +static void +write_date_to_file (struct tm *tm) { + FILE *fp; + + if ((fp = fopen(LASTDATE,"w"))) { + fprintf(fp,"%02d.%02d.%04d\n", tm->tm_mday, tm->tm_mon+1, + tm->tm_year+1900); + fclose(fp); + } else + perror(LASTDATE); +} + +static void +read_date_from_file (struct tm *tm) { + int last_mday, last_mon, last_year; + FILE *fp; + + if ((fp = fopen(LASTDATE,"r"))) { + if (fscanf (fp,"%d.%d.%d\n", &last_mday, &last_mon, &last_year) == 3) { + tm->tm_year = last_year-1900; + if ((tm->tm_mon << 5) + tm->tm_mday < ((last_mon-1) << 5) + last_mday) + tm->tm_year ++; + } + fclose(fp); + } + write_date_to_file (tm); +} + +static float +time_diff(struct timeval subtrahend, struct timeval subtractor) { +/*--------------------------------------------------------------------------- + The difference in seconds between two times in "timeval" format. +----------------------------------------------------------------------------*/ + return( (subtrahend.tv_sec - subtractor.tv_sec) + + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6 ); +} + + +static struct timeval +time_inc(struct timeval addend, float increment) { +/*---------------------------------------------------------------------------- + The time, in "timeval" format, which is seconds after + the time . Of course, may be negative. +-----------------------------------------------------------------------------*/ + struct timeval newtime; + + newtime.tv_sec = addend.tv_sec + (int) increment; + newtime.tv_usec = addend.tv_usec + (increment - (int) increment) * 1E6; + + /* Now adjust it so that the microsecond value is between 0 and 1 million */ + if (newtime.tv_usec < 0) { + newtime.tv_usec += 1E6; + newtime.tv_sec -= 1; + } else if (newtime.tv_usec >= 1E6) { + newtime.tv_usec -= 1E6; + newtime.tv_sec += 1; + } + return(newtime); +} + + +static bool +hw_clock_is_utc(const bool utc, const bool local_opt, + const struct adjtime adjtime) { + bool ret; + + if (utc) + ret = TRUE; /* --utc explicitly given on command line */ + else if (local_opt) + ret = FALSE; /* --localtime explicitly given */ + else + /* get info from adjtime file - default is local */ + ret = (adjtime.local_utc == UTC); + if (debug) + printf(_("Assuming hardware clock is kept in %s time.\n"), + ret ? _("UTC") : _("local")); + return ret; +} + + + +static void +read_adjtime(struct adjtime *adjtime_p, int *rc_p) { +/*---------------------------------------------------------------------------- + Read the adjustment parameters out of the /etc/adjtime file. + + Return them as the adjtime structure <*adjtime_p>. + + If there is no /etc/adjtime file, return defaults. + If values are missing from the file, return defaults for them. + + return *rc_p = 0 if all OK, !=0 otherwise. + +-----------------------------------------------------------------------------*/ + FILE *adjfile; + int rc; /* local return code */ + struct stat statbuf; /* We don't even use the contents of this. */ + + rc = stat(ADJPATH, &statbuf); + if (rc < 0 && errno == ENOENT) { + /* He doesn't have a adjtime file, so we'll use defaults. */ + adjtime_p->drift_factor = 0; + adjtime_p->last_adj_time = 0; + adjtime_p->not_adjusted = 0; + adjtime_p->last_calib_time = 0; + adjtime_p->local_utc = UNKNOWN; + + *rc_p = 0; + } else { + adjfile = fopen(ADJPATH, "r"); /* open file for reading */ + if (adjfile == NULL) { + outsyserr("cannot open file " ADJPATH); + *rc_p = 2; + } else { + char line1[81]; /* String: first line of adjtime file */ + char line2[81]; /* String: second line of adjtime file */ + char line3[81]; /* String: third line of adjtime file */ + + line1[0] = '\0'; /* In case fgets fails */ + fgets(line1, sizeof(line1), adjfile); + line2[0] = '\0'; /* In case fgets fails */ + fgets(line2, sizeof(line2), adjfile); + line3[0] = '\0'; /* In case fgets fails */ + fgets(line3, sizeof(line3), adjfile); + + fclose(adjfile); + + /* Set defaults in case values are missing from file */ + adjtime_p->drift_factor = 0; + adjtime_p->last_adj_time = 0; + adjtime_p->not_adjusted = 0; + adjtime_p->last_calib_time = 0; + + sscanf(line1, "%f %d %f", + &adjtime_p->drift_factor, + (int *) &adjtime_p->last_adj_time, + &adjtime_p->not_adjusted); + + sscanf(line2, "%d", (int *) &adjtime_p->last_calib_time); + + if (!strcmp(line3, "UTC\n")) + adjtime_p->local_utc = UTC; + else if (!strcmp(line3, "LOCAL\n")) + adjtime_p->local_utc = LOCAL; + else { + adjtime_p->local_utc = UNKNOWN; + if (line3[0]) { + fprintf(stderr, _("%s: Warning: unrecognized third line in adjtime file\n"), + MYNAME); + fprintf(stderr, _("(Expected: `UTC' or `LOCAL' or nothing.)\n")); + } + } + + *rc_p = 0; + } + adjtime_p->dirty = FALSE; + + if (debug) { + printf(_("Last drift adjustment done at %d seconds after 1969\n"), + (int) adjtime_p->last_adj_time); + printf(_("Last calibration done at %d seconds after 1969\n"), + (int) adjtime_p->last_calib_time); + printf(_("Hardware clock is on %s time\n"), + (adjtime_p->local_utc == LOCAL) ? _("local") : + (adjtime_p->local_utc == UTC) ? _("UTC") : _("unknown")); + } + } +} + + +static void +synchronize_to_clock_tick(int *retcode_p) { +/*----------------------------------------------------------------------------- + Wait until the falling edge of the Hardware Clock's update flag so + that any time that is read from the clock immediately after we + return will be exact. + + The clock only has 1 second precision, so it gives the exact time only + once per second, right on the falling edge of the update flag. + + We wait (up to one second) either blocked waiting for an rtc device + or in a CPU spin loop. The former is probably not very accurate. + + Return *retcode_p == 0 if it worked, nonzero if it didn't. + +-----------------------------------------------------------------------------*/ + if (debug) printf(_("Waiting for clock tick...\n")); + + *retcode_p = ur->synchronize_to_clock_tick(); + + if (debug) printf(_("...got clock tick\n")); +} + + + +static void +mktime_tz(struct tm tm, const bool universal, + bool *valid_p, time_t *systime_p) { +/*----------------------------------------------------------------------------- + Convert a time in broken down format (hours, minutes, etc.) into standard + unix time (seconds into epoch). Return it as *systime_p. + + The broken down time is argument . This broken down time is either in + local time zone or UTC, depending on value of logical argument "universal". + True means it is in UTC. + + If the argument contains values that do not constitute a valid time, + and mktime() recognizes this, return *valid_p == false and + *systime_p undefined. However, mktime() sometimes goes ahead and + computes a fictional time "as if" the input values were valid, + e.g. if they indicate the 31st day of April, mktime() may compute + the time of May 1. In such a case, we return the same fictional + value mktime() does as *systime_p and return *valid_p == true. + +-----------------------------------------------------------------------------*/ + time_t mktime_result; /* The value returned by our mktime() call */ + char *zone; /* Local time zone name */ + + /* We use the C library function mktime(), but since it only works on + local time zone input, we may have to fake it out by temporarily + changing the local time zone to UTC. + */ + zone = (char *) getenv("TZ"); /* remember original time zone */ + if (universal) { + /* Set timezone to UTC */ + setenv("TZ", "", TRUE); + /* Note: tzset() gets called implicitly by the time code, but only the + first time. When changing the environment variable, better call + tzset() explicitly. + */ + tzset(); + } + mktime_result = mktime(&tm); + if (mktime_result == -1) { + /* This apparently (not specified in mktime() documentation) means + the 'tm' structure does not contain valid values (however, not + containing valid values does _not_ imply mktime() returns -1). + */ + *valid_p = FALSE; + *systime_p = 0; + if (debug) + printf(_("Invalid values in hardware clock: " + "%4d/%.2d/%.2d %.2d:%.2d:%.2d\n"), + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + } else { + *valid_p = TRUE; + *systime_p = mktime_result; + if (debug) + printf(_("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = " + "%ld seconds since 1969\n"), + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, (long) *systime_p); + } + /* now put back the original zone. */ + if (zone) setenv("TZ", zone, TRUE); + else unsetenv("TZ"); + tzset(); +} + + +static void +read_hardware_clock(const bool universal, bool *valid_p, time_t *systime_p){ +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via argument. + + Use the method indicated by argument to access the hardware clock. +-----------------------------------------------------------------------------*/ + struct tm tm; + int err; + + err = ur->read_hardware_clock(&tm); + + if (badyear) + read_date_from_file(&tm); + + if (debug) + printf (_("Time read from Hardware Clock: %4d/%.2d/%.2d %02d:%02d:%02d\n"), + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + mktime_tz(tm, universal, valid_p, systime_p); +} + + +static void +set_hardware_clock(const time_t newtime, + const bool universal, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time , in local time zone or UTC, + according to . +----------------------------------------------------------------------------*/ + int err; + struct tm new_broken_time; + /* Time to which we will set Hardware Clock, in broken down format, in + the time zone of caller's choice + */ + + if (universal) + new_broken_time = *gmtime(&newtime); + else + new_broken_time = *localtime(&newtime); + + if (debug) + printf(_("Setting Hardware Clock to %.2d:%.2d:%.2d " + "= %d seconds since 1969\n"), + new_broken_time.tm_hour, new_broken_time.tm_min, + new_broken_time.tm_sec, (int) newtime); + + if (testing) + printf(_("Clock not changed - testing only.\n")); + else { + if (badyear) { + /* + * Write the real year to a file, then write a fake year + * between 1995 and 1998 to the RTC. This way, Award BIOS boots + * on 29 Feb 2000 thinking that it's 29 Feb 1996. + */ + write_date_to_file (&new_broken_time); + new_broken_time.tm_year = 95 + ((new_broken_time.tm_year+1) & 3); + } + err = ur->set_hardware_clock(&new_broken_time); + } +} + + + +static void +set_hardware_clock_exact(const time_t settime, + const struct timeval ref_time, + const bool universal, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time "settime", in local time zone or UTC, + according to "universal". + + But correct "settime" and wait for a fraction of a second so that + "settime" is the value of the Hardware Clock as of system time + "ref_time", which is in the past. For example, if "settime" is + 14:03:05 and "ref_time" is 12:10:04.5 and the current system + time is 12:10:06.0: Wait .5 seconds (to make exactly 2 seconds since + "ref_time") and then set the Hardware Clock to 14:03:07, thus + getting a precise and retroactive setting of the clock. + + (Don't be confused by the fact that the system clock and the Hardware + Clock differ by two hours in the above example. That's just to remind + you that there are two independent time scales here). + + This function ought to be able to accept set times as fractional times. + Idea for future enhancement. + +-----------------------------------------------------------------------------*/ + time_t newtime; /* Time to which we will set Hardware Clock */ + struct timeval now_time; /* locally used time */ + + gettimeofday(&now_time, NULL); + newtime = settime + (int) time_diff(now_time, ref_time) + 1; + if (debug) + printf(_("Time elapsed since reference time has been %.6f seconds.\n" + "Delaying further to reach the next full second.\n"), + time_diff(now_time, ref_time)); + + /* Now delay some more until Hardware Clock time newtime arrives */ + do gettimeofday(&now_time, NULL); + while (time_diff(now_time, ref_time) < newtime - settime); + + set_hardware_clock(newtime, universal, testing); +} + + + +static void +display_time(const bool hclock_valid, const time_t systime, + const float sync_duration) { +/*---------------------------------------------------------------------------- + Put the time "systime" on standard output in display format. + Except if hclock_valid == false, just tell standard output that we don't + know what time it is. + + Include in the output the adjustment "sync_duration". +-----------------------------------------------------------------------------*/ + if (!hclock_valid) + fprintf(stderr, _("The Hardware Clock registers contain values that are " + "either invalid (e.g. 50th day of month) or beyond the range " + "we can handle (e.g. Year 2095).\n")); + else { + struct tm *lt; + char *format = "%c"; + char ctime_now[200]; + + lt = localtime(&systime); + strftime(ctime_now, sizeof(ctime_now), format, lt); + printf(_("%s %.6f seconds\n"), ctime_now, -(sync_duration)); + } +} + + + +static int +interpret_date_string(const char *date_opt, time_t * const time_p) { +/*---------------------------------------------------------------------------- + Interpret the value of the --date option, which is something like + "13:05:01". In fact, it can be any of the myriad ASCII strings that specify + a time which the "date" program can understand. The date option value in + question is our "dateopt" argument. + + The specified time is in the local time zone. + + Our output, "*time_p", is a seconds-into-epoch time. + + We use the "date" program to interpret the date string. "date" must be + runnable by issuing the command "date" to the /bin/sh shell. That means + in must be in the current PATH. + + If anything goes wrong (and many things can), we return return code + 10 and arbitrary *time_p. Otherwise, return code is 0 and *time_p + is valid. +----------------------------------------------------------------------------*/ + FILE *date_child_fp; + char date_resp[100]; + const char magic[]="seconds-into-epoch="; + char date_command[100]; + int retcode; /* our eventual return code */ + int rc; /* local return code */ + + if (date_opt == NULL) { + fprintf(stderr, _("No --date option specified.\n")); + retcode = 14; + } else if (strchr(date_opt, '"') != NULL) { + /* Quotation marks in date_opt would ruin the date command we construct. + */ + fprintf(stderr, _("The value of the --date option is not a valid date.\n" + "In particular, it contains quotation marks.\n")); + retcode = 12; + } else { + sprintf(date_command, "date --date=\"%s\" +seconds-into-epoch=%%s", + date_opt); + if (debug) printf(_("Issuing date command: %s\n"), date_command); + + date_child_fp = popen(date_command, "r"); + if (date_child_fp == NULL) { + outsyserr(_("Unable to run 'date' program in /bin/sh shell. " + "popen() failed")); + retcode = 10; + } else { + date_resp[0] = '\0'; /* in case fgets fails */ + fgets(date_resp, sizeof(date_resp), date_child_fp); + if (debug) printf(_("response from date command = %s\n"), date_resp); + if (strncmp(date_resp, magic, sizeof(magic)-1) != 0) { + fprintf(stderr, _("The date command issued by %s returned " + "unexpected results.\n" + "The command was:\n %s\nThe response was:\n %s\n"), + MYNAME, date_command, date_resp); + retcode = 8; + } else { + int seconds_since_epoch; + rc = sscanf(date_resp + sizeof(magic)-1, "%d", &seconds_since_epoch); + if (rc < 1) { + fprintf(stderr, _("The date command issued by %s returned " + "something other than an integer where the converted " + "time value was expected.\n" + "The command was:\n %s\nThe response was:\n %s\n"), + MYNAME, date_command, date_resp); + retcode = 6; + } else { + retcode = 0; + *time_p = seconds_since_epoch; + if (debug) + printf(_("date string %s equates to %d seconds since 1969.\n"), + date_opt, (int) *time_p); + } + } + fclose(date_child_fp); + } + } + return(retcode); +} + + + +static int +set_system_clock(const bool hclock_valid, const time_t newtime, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the System Clock to time 'newtime'. + + Also set the kernel time zone value to the value indicated by the + TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as + tzset() would interpret them. + + EXCEPT: if hclock_valid is false, just issue an error message + saying there is no valid time in the Hardware Clock to which to set + the system time. + + If 'testing' is true, don't actually update anything -- just say we + would have. +-----------------------------------------------------------------------------*/ + int retcode; + + if (!hclock_valid) { + fprintf(stderr,_("The Hardware Clock does not contain a valid time, so " + "we cannot set the System Time from it.\n")); + retcode = 1; + } else { + struct timeval tv; + struct tm *broken; + int minuteswest; + int rc; + + tv.tv_sec = newtime; + tv.tv_usec = 0; + + broken = localtime(&newtime); +#ifdef HAVE_tm_gmtoff + minuteswest = -broken->tm_gmtoff/60; /* GNU extension */ +#else + minuteswest = timezone/60; + if (broken->tm_isdst) + minuteswest -= 60; +#endif + + if (debug) { + printf( _("Calling settimeofday:\n") ); + printf( _("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"), + (long) tv.tv_sec, (long) tv.tv_usec ); + printf( _("\ttz.tz_minuteswest = %d\n"), minuteswest); + } + if (testing) { + printf(_("Not setting system clock because running in test mode.\n")); + retcode = 0; + } else { + const struct timezone tz = { minuteswest, 0 }; + + rc = settimeofday(&tv, &tz); + if (rc != 0) { + if (errno == EPERM) + fprintf(stderr, _("Must be superuser to set system clock.\n")); + else + outsyserr(_("settimeofday() failed")); + retcode = 1; + } else retcode = 0; + } + } + return(retcode); +} + + +static void +adjust_drift_factor(struct adjtime *adjtime_p, + const time_t nowtime, + const bool hclock_valid, const time_t hclocktime ) { +/*--------------------------------------------------------------------------- + Update the drift factor in <*adjtime_p> to reflect the fact that the + Hardware Clock was calibrated to and before that was set + to . + + We assume that the user has been doing regular drift adjustments + using the drift factor in the adjtime file, so if and + are different, that means the adjustment factor isn't + quite right. + + We record in the adjtime file the time at which we last calibrated + the clock so we can compute the drift rate each time we calibrate. + + EXCEPT: if is false, assume Hardware Clock was not set + before to anything meaningful and regular adjustments have not been + done, so don't adjust the drift factor. + +----------------------------------------------------------------------------*/ + if (!hclock_valid) { + if (debug) + printf(_("Not adjusting drift factor because the Hardware Clock " + "previously contained garbage.\n")); + } else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) { + if (debug) + printf(_("Not adjusting drift factor because it has been less than a " + "day since the last calibration.\n")); + } else { + const float factor_adjust = + ((float) (nowtime - hclocktime) + / (hclocktime - adjtime_p->last_calib_time)) + * 24 * 60 * 60; + + if (debug) + printf(_("Clock drifted %d seconds in the past %d seconds " + "in spite of a drift factor of %f seconds/day.\n" + "Adjusting drift factor by %f seconds/day\n"), + (int) (nowtime - hclocktime), + (int) (hclocktime - adjtime_p->last_calib_time), + adjtime_p->drift_factor, + factor_adjust ); + + adjtime_p->drift_factor += factor_adjust; + } + adjtime_p->last_calib_time = nowtime; + + adjtime_p->last_adj_time = nowtime; + + adjtime_p->not_adjusted = 0; + + adjtime_p->dirty = TRUE; +} + + + +static void +calculate_adjustment( + const float factor, + const time_t last_time, + const float not_adjusted, + const time_t systime, + int *adjustment_p, + float *retro_p, + const int debug ) { +/*---------------------------------------------------------------------------- + Do the drift adjustment calculation. + + The way we have to set the clock, we need the adjustment in two parts: + + 1) an integer number of seconds (return as *adjustment_p) + + 2) a positive fraction of a second (less than 1) (return as *retro_p) + + The sum of these two values is the adjustment needed. Positive means to + advance the clock or insert seconds. Negative means to retard the clock + or remove seconds. +----------------------------------------------------------------------------*/ + float exact_adjustment; + + exact_adjustment = ((float) (systime - last_time)) * factor / (24 * 60 * 60) + + not_adjusted; + *adjustment_p = FLOOR(exact_adjustment); + + *retro_p = exact_adjustment - (float) *adjustment_p; + if (debug) { + printf (_("Time since last adjustment is %d seconds\n"), + (int) (systime - last_time)); + printf (_("Need to insert %d seconds and refer time back " + "%.6f seconds ago\n"), + *adjustment_p, *retro_p); + } +} + + + +static void +save_adjtime(const struct adjtime adjtime, const bool testing) { +/*----------------------------------------------------------------------------- + Write the contents of the structure to its disk file. + + But if the contents are clean (unchanged since read from disk), don't + bother. +-----------------------------------------------------------------------------*/ + char newfile[412]; /* Stuff to write to disk file */ + + if (adjtime.dirty) { + /* snprintf is not always available, but this is safe + as long as libc does not use more than 100 positions for %ld or %f */ + sprintf(newfile, "%f %ld %f\n%ld\n%s\n", + adjtime.drift_factor, + (long) adjtime.last_adj_time, + adjtime.not_adjusted, + (long) adjtime.last_calib_time, + (adjtime.local_utc == UTC) ? "UTC" : "LOCAL"); + + if (testing) { + printf(_("Not updating adjtime file because of testing mode.\n")); + printf(_("Would have written the following to %s:\n%s"), + ADJPATH, newfile); + } else { + FILE *adjfile; + int err = 0; + + adjfile = fopen(ADJPATH, "w"); + if (adjfile == NULL) { + outsyserr("Could not open file with the clock adjustment parameters " + "in it (" ADJPATH ") for writing"); + err = 1; + } else { + if (fputs(newfile, adjfile) < 0) { + outsyserr("Could not update file with the clock adjustment " + "parameters (" ADJPATH ") in it"); + err = 1; + } + if (fclose(adjfile) < 0) { + outsyserr("Could not update file with the clock adjustment " + "parameters (" ADJPATH ") in it"); + err = 1; + } + } + if (err) + fprintf(stderr, _("Drift adjustment parameters not updated.\n")); + } + } +} + + + +static void +do_adjustment(struct adjtime *adjtime_p, + const bool hclock_valid, const time_t hclocktime, + const struct timeval read_time, + const bool universal, const bool testing) { +/*--------------------------------------------------------------------------- + Do the adjustment requested, by 1) setting the Hardware Clock (if + necessary), and 2) updating the last-adjusted time in the adjtime + structure. + + Do not update anything if the Hardware Clock does not currently present + a valid time. + + arguments and are current values from the adjtime + file. + + means the Hardware Clock contains a valid time, and that + time is . + + is the current system time (to be precise, it is the system + time at the time was read, which due to computational delay + could be a short time ago). + + : the Hardware Clock is kept in UTC. + + : We are running in test mode (no updating of clock). + + We do not bother to update the clock if the adjustment would be less than + one second. This is to avoid cumulative error and needless CPU hogging + (remember we use an infinite loop for some timing) if the user runs us + frequently. + +----------------------------------------------------------------------------*/ + if (!hclock_valid) { + fprintf(stderr, _("The Hardware Clock does not contain a valid time, " + "so we cannot adjust it.\n")); + } else { + int adjustment; + /* Number of seconds we must insert in the Hardware Clock */ + float retro; + /* Fraction of second we have to remove from clock after inserting + whole seconds. + */ + calculate_adjustment(adjtime_p->drift_factor, + adjtime_p->last_adj_time, + adjtime_p->not_adjusted, + hclocktime, + &adjustment, &retro, + debug ); + if (adjustment > 0 || adjustment < -1) { + set_hardware_clock_exact(hclocktime + adjustment, + time_inc(read_time, -retro), + universal, testing); + adjtime_p->last_adj_time = hclocktime + adjustment; + adjtime_p->not_adjusted = 0; + adjtime_p->dirty = TRUE; + } else + if (debug) + printf(_("Needed adjustment is less than one second, " + "so not setting clock.\n")); + } +} + + + +static void +determine_clock_access_method(const bool user_requests_ISA) { + + ur = NULL; + + if (user_requests_ISA) + ur = probe_for_cmos_clock(); + + if (!ur) + ur = probe_for_rtc_clock(); + + if (!ur) + ur = probe_for_kd_clock(); + + if (!ur && !user_requests_ISA) + ur = probe_for_cmos_clock(); + + if (debug) { + if (ur) + printf(_("Using %s.\n"), ur->interface_name); + else + printf(_("No usable clock interface found.\n")); + } +} + +static void +manipulate_clock(const bool show, const bool adjust, + const bool set, const time_t set_time, + const bool hctosys, const bool systohc, + const struct timeval startup_time, + const bool utc, const bool local_opt, + const bool testing, int *retcode_p) { +/*--------------------------------------------------------------------------- + Do all the normal work of hwclock - read, set clock, etc. + + Issue output to stdout and error message to stderr where appropriate. + + Return rc == 0 if everything went OK, rc != 0 if not. +----------------------------------------------------------------------------*/ + struct adjtime adjtime; + /* Contents of the adjtime file, or what they should be. */ + int rc; /* local return code */ + bool no_auth; /* User lacks necessary authorization to access the clock */ + + no_auth = ur->get_permissions(); + + if (no_auth) *retcode_p = 1; + else { + if (adjust || set || systohc || (!utc && !local_opt)) + read_adjtime(&adjtime, &rc); + else { + /* A little trick to avoid reading the file if we don't have to */ + adjtime.dirty = FALSE; + rc = 0; + } + if (rc != 0) *retcode_p = 2; + else { + const bool universal = hw_clock_is_utc(utc, local_opt, adjtime); + + if ((set || systohc || adjust) && + (adjtime.local_utc == UTC) != universal) { + adjtime.local_utc = universal ? UTC : LOCAL; + adjtime.dirty = TRUE; + } + + synchronize_to_clock_tick(retcode_p); + /* this takes up to 1 second */ + if (*retcode_p == 0) { + struct timeval read_time; + /* The time at which we read the Hardware Clock */ + + bool hclock_valid; + /* The Hardware Clock gives us a valid time, or at least something + close enough to fool mktime(). + */ + + time_t hclocktime; + /* The time the hardware clock had just after we + synchronized to its next clock tick when we started up. + Defined only if hclock_valid is true. + */ + + gettimeofday(&read_time, NULL); + read_hardware_clock(universal, &hclock_valid, &hclocktime); + + if (show) { + display_time(hclock_valid, hclocktime, + time_diff(read_time, startup_time)); + *retcode_p = 0; + } else if (set) { + set_hardware_clock_exact(set_time, startup_time, + universal, testing); + adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime); + *retcode_p = 0; + } else if (adjust) { + do_adjustment(&adjtime, hclock_valid, hclocktime, + read_time, universal, testing); + *retcode_p = 0; + } else if (systohc) { + struct timeval nowtime, reftime; + /* We can only set_hardware_clock_exact to a whole seconds + time, so we set it with reference to the most recent + whole seconds time. + */ + gettimeofday(&nowtime, NULL); + reftime.tv_sec = nowtime.tv_sec; + reftime.tv_usec = 0; + + set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, + universal, testing); + *retcode_p = 0; + adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, + hclocktime); + } else if (hctosys) { + rc = set_system_clock(hclock_valid, hclocktime, testing); + if (rc != 0) { + printf(_("Unable to set system clock.\n")); + *retcode_p = 1; + } else *retcode_p = 0; + } + save_adjtime(adjtime, testing); + } + } + } +} + + +static void +manipulate_epoch(const bool getepoch, const bool setepoch, + const int epoch_opt, const bool testing) { +/*---------------------------------------------------------------------------- + Get or set the Hardware Clock epoch value in the kernel, as appropriate. + , , and are hwclock invocation options. + + == -1 if the user did not specify an "epoch" option. + +-----------------------------------------------------------------------------*/ + /* + Maintenance note: This should work on non-Alpha machines, but the + evidence today (98.03.04) indicates that the kernel only keeps the + epoch value on Alphas. If that is ever fixed, this function should be + changed. + */ + +#ifndef __alpha__ + fprintf(stderr, _("The kernel keeps an epoch value for the Hardware Clock " + "only on an Alpha machine.\nThis copy of hwclock was built for " + "a machine other than Alpha\n(and thus is presumably not running " + "on an Alpha now). No action taken.\n")); +#else + if (getepoch) { + unsigned long epoch; + + if (get_epoch_rtc(&epoch, 0)) + fprintf(stderr, _("Unable to get the epoch value from the kernel.\n")); + else + printf(_("Kernel is assuming an epoch value of %lu\n"), epoch); + } else if (setepoch) { + if (epoch_opt == -1) + fprintf(stderr, _("To set the epoch value, you must use the 'epoch' " + "option to tell to what value to set it.\n")); + else if (testing) + printf(_("Not setting the epoch to %d - testing only.\n"), + epoch_opt); + else if (set_epoch_rtc(epoch_opt)) + printf(_("Unable to set the epoch value in the kernel.\n")); + } +#endif +} + +#if __ia64__ +#define RTC_DEV "/dev/efirtc" +#else +#define RTC_DEV "/dev/rtc" +#endif + +/* + usage - Output (error and) usage information + + This function is called both directly from main to show usage + information and as fatal function from shhopt if some argument is + not understood. In case of normal usage info FMT should be NULL. + In that case the info is printed to stdout. If FMT is given + usage will act like fprintf( stderr, fmt, ... ), show a usage + information and terminate the program afterwards. +*/ +static void +usage( const char *fmt, ... ) { + FILE *usageto; + va_list ap; + + usageto = fmt ? stderr : stdout; + + fprintf( usageto, _( + "hwclock - query and set the hardware clock (RTC)\n\n" + "Usage: hwclock [function] [options...]\n\n" + "Functions:\n" + " --help show this help\n" + " --show read hardware clock and print result\n" + " --set set the rtc to the time given with --date\n" + " --hctosys set the system time from the hardware clock\n" + " --systohc set the hardware clock to the current system time\n" + " --adjust adjust the rtc to account for systematic drift since \n" + " the clock was last set or adjusted\n" + " --getepoch print out the kernel's hardware clock epoch value\n" + " --setepoch set the kernel's hardware clock epoch value to the \n" + " value given with --epoch\n" + " --version print out the version of hwclock to stdout\n" + "\nOptions: \n" + " --utc the hardware clock is kept in coordinated universal time\n" + " --localtime the hardware clock is kept in local time\n" + " --directisa access the ISA bus directly instead of %s\n" + " --badyear ignore rtc's year because the bios is broken\n" + " --date specifies the time to which to set the hardware clock\n" + " --epoch=year specifies the year which is the beginning of the \n" + " hardware clock's epoch value\n" + ),RTC_DEV); +#ifdef __alpha__ + fprintf( usageto, _( + " --jensen, --arc, --srm, --funky-toy\n" + " tell hwclock the type of alpha you have (see hwclock(8))\n" + ) ); +#endif + + + fflush(stdout); + if( fmt ) { + usageto = stderr; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + } + + exit( fmt ? 99 : 0 ); +} + +int +main(int argc, char **argv) { + + struct timeval startup_time; + /* The time we started up, in seconds into the epoch, including fractions. + */ + time_t set_time; /* Time to which user said to set Hardware Clock */ + + bool permitted; /* User is permitted to do the function */ + int retcode; /* Our eventual return code */ + + int rc; /* local return code */ + + /* option_def is the control table for the option parser. These other + variables are the results of parsing the options and their meanings + are given by the option_def. The only exception is , which + may be modified after parsing is complete to effect an implied option. + */ + bool help, show, set, systohc, hctosys, adjust, getepoch, setepoch, version; + bool ARCconsole, utc, testing, directisa, Jensen, SRM, funky_toy; + bool local_opt; + char *date_opt; + + const optStruct option_def[] = { + { 'h', (char *) "help", OPT_FLAG, &help, 0 }, + { 'r', (char *) "show", OPT_FLAG, &show, 0 }, + { 0, (char *) "set", OPT_FLAG, &set, 0 }, + { 'w', (char *) "systohc", OPT_FLAG, &systohc, 0 }, + { 's', (char *) "hctosys", OPT_FLAG, &hctosys, 0 }, + { 0, (char *) "getepoch", OPT_FLAG, &getepoch, 0 }, + { 0, (char *) "setepoch", OPT_FLAG, &setepoch, 0 }, + { 'a', (char *) "adjust", OPT_FLAG, &adjust, 0 }, + { 'v', (char *) "version", OPT_FLAG, &version, 0 }, + { 'V', (char *) "version", OPT_FLAG, &version, 0 }, + { 0, (char *) "date", OPT_STRING, &date_opt, 0 }, + { 0, (char *) "epoch", OPT_UINT, &epoch_option,0 }, + { 'u', (char *) "utc", OPT_FLAG, &utc, 0 }, + { 0, (char *) "localtime", OPT_FLAG, &local_opt, 0 }, + { 0, (char *) "badyear", OPT_FLAG, &badyear, 0 }, + { 0, (char *) "directisa", OPT_FLAG, &directisa, 0 }, + { 0, (char *) "test", OPT_FLAG, &testing, 0 }, + { 'D', (char *) "debug", OPT_FLAG, &debug, 0 }, +#ifdef __alpha__ + { 'A', (char *) "ARC", OPT_FLAG, &ARCconsole,0 }, + { 'J', (char *) "Jensen", OPT_FLAG, &Jensen, 0 }, + { 'S', (char *) "SRM", OPT_FLAG, &SRM, 0 }, + { 'F', (char *) "funky-toy", OPT_FLAG, &funky_toy, 0 }, +#endif + { 0, (char *) NULL, OPT_END, NULL, 0 } + }; + int argc_parse; /* argc, except we modify it as we parse */ + char **argv_parse; /* argv, except we modify it as we parse */ + + gettimeofday(&startup_time, NULL); /* Remember what time we were invoked */ + + setlocale(LC_ALL, ""); +#ifdef LC_NUMERIC + /* We need LC_CTYPE and LC_TIME and LC_MESSAGES, but must avoid + LC_NUMERIC since it gives problems when we write to /etc/adjtime. + - gqueri@mail.dotcom.fr */ + setlocale(LC_NUMERIC, "C"); +#endif + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* set option defaults */ + help = show = set = systohc = hctosys = adjust = getepoch = setepoch = + version = utc = local_opt = ARCconsole = SRM = funky_toy = + directisa = badyear = Jensen = testing = debug = FALSE; + date_opt = NULL; + + argc_parse = argc; argv_parse = argv; + optParseOptions(&argc_parse, argv_parse, option_def, 0); + /* Uses and sets argc_parse, argv_parse. + Sets show, systohc, hctosys, adjust, utc, local_opt, version, + testing, debug, set, date_opt, getepoch, setepoch, epoch_option + */ + /* This is an ugly routine - for example, if I give an incorrect + option, it only says "unrecognized option" without telling + me what options are recognized. Rewrite with standard + getopt() and usage() and throw shhopt out. */ + + if (argc_parse - 1 > 0) { + usage( _("%s takes no non-option arguments. " + "You supplied %d.\n"), + MYNAME, argc_parse - 1); + } + + if (help) + usage( NULL ); + + if (show + set + systohc + hctosys + adjust + + getepoch + setepoch + version > 1) { + fprintf(stderr, _("You have specified multiple function options.\n" + "You can only perform one function at a time.\n")); + exit(100); + } + + if (utc && local_opt) { + fprintf(stderr, _("%s: The --utc and --localtime options are mutually " + "exclusive. You specified both.\n"), MYNAME); + exit(100); + } + +#ifdef __alpha__ + set_cmos_epoch(ARCconsole, SRM); + set_cmos_access(Jensen, funky_toy); +#endif + + if (set) { + rc = interpret_date_string(date_opt, &set_time); /* (time-consuming) */ + if (rc != 0) { + fprintf(stderr, _("No usable set-to time. Cannot set clock.\n")); + exit(100); + } + } + + if (!(show | set | systohc | hctosys | adjust | getepoch | setepoch | + version)) + show = 1; /* default to show */ + + + if (getuid() == 0) permitted = TRUE; + else { + /* program is designed to run setuid (in some situations) -- be secure! */ + if (set || hctosys || systohc || adjust) { + fprintf(stderr, + _("Sorry, only the superuser can change the Hardware Clock.\n")); + permitted = FALSE; + } else if (hctosys) { + fprintf(stderr, + _("Sorry, only the superuser can change the System Clock.\n")); + permitted = FALSE; + } else if (setepoch) { + fprintf(stderr, + _("Sorry, only the superuser can change " + "the Hardware Clock epoch in the kernel.\n")); + permitted = FALSE; + } else + permitted = TRUE; + } + + if (!permitted) retcode = 2; + else { + retcode = 0; + if (version) { + printf(MYNAME " " VERSION "/%s\n",util_linux_version); + } else if (getepoch || setepoch) { + manipulate_epoch(getepoch, setepoch, epoch_option, testing); + } else { + if (debug) + printf(MYNAME " " VERSION "/%s\n",util_linux_version); + determine_clock_access_method(directisa); + if (!ur) { + fprintf(stderr, + _("Cannot access the Hardware Clock via any known method.\n")); + if (!debug) + fprintf(stderr, + _("Use the --debug option to see the details of our " + "search for an access method.\n")); + } else + manipulate_clock(show, adjust, set, set_time, hctosys, systohc, + startup_time, utc, local_opt, testing, &rc); + } + } + exit(retcode); +} + +/* A single routine for greater uniformity */ +void +outsyserr(char *msg, ...) { + va_list args; + int errsv = errno; + + fprintf(stderr, "%s: ", progname); + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, ", errno=%d: %s.\n", + errsv, strerror(errsv)); +} + +/**************************************************************************** + + History of this program: + + 98.08.12 BJH Version 2.4 + + Don't use century byte from Hardware Clock. Add comments telling why. + + + 98.06.20 BJH Version 2.3. + + Make --hctosys set the kernel timezone from TZ environment variable + and/or /usr/lib/zoneinfo. From Klaus Ripke (klaus@ripke.com). + + 98.03.05 BJH. Version 2.2. + + Add --getepoch and --setepoch. + + Fix some word length things so it works on Alpha. + + Make it work when /dev/rtc doesn't have the interrupt functions. + In this case, busywait for the top of a second instead of blocking and + waiting for the update complete interrupt. + + Fix a bunch of bugs too numerous to mention. + + 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte + 50) of the ISA Hardware Clock when using direct ISA I/O. Problem + discovered by job (jei@iclnl.icl.nl). + + Use the rtc clock access method in preference to the KDGHWCLK method. + Problem discovered by Andreas Schwab . + + November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt + (janl@math.uio.no) to make it compile on linux 1.2 machines as well + as more recent versions of the kernel. Introduced the NO_CLOCK + access method and wrote feature test code to detect absense of rtc + headers. + + +************************************************************************** + Maintenance notes + + To compile this, you must use GNU compiler optimization (-O option) + in order to make the "extern inline" functions from asm/io.h (inb(), + etc.) compile. If you don't optimize, which means the compiler + will generate no inline functions, the references to these functions + in this program will be compiled as external references. Since you + probably won't be linking with any functions by these names, you will + have unresolved external references when you link. + + The program is designed to run setuid superuser, since we need to be + able to do direct I/O. (More to the point: we need permission to + execute the iopl() system call). (However, if you use one of the + methods other than direct ISA I/O to access the clock, no setuid is + required). + + Here's some info on how we must deal with the time that elapses while + this program runs: There are two major delays as we run: + + 1) Waiting up to 1 second for a transition of the Hardware Clock so + we are synchronized to the Hardware Clock. + + 2) Running the "date" program to interpret the value of our --date + option. + + Reading the /etc/adjtime file is the next biggest source of delay and + uncertainty. + + The user wants to know what time it was at the moment he invoked us, + not some arbitrary time later. And in setting the clock, he is + giving us the time at the moment we are invoked, so if we set the + clock some time later, we have to add some time to that. + + So we check the system time as soon as we start up, then run "date" + and do file I/O if necessary, then wait to synchronize with a + Hardware Clock edge, then check the system time again to see how + much time we spent. We immediately read the clock then and (if + appropriate) report that time, and additionally, the delay we measured. + + If we're setting the clock to a time given by the user, we wait some + more so that the total delay is an integral number of seconds, then + set the Hardware Clock to the time the user requested plus that + integral number of seconds. N.B. The Hardware Clock can only be set + in integral seconds. + + If we're setting the clock to the system clock value, we wait for + the system clock to reach the top of a second, and then set the + Hardware Clock to the system clock's value. + + Here's an interesting point about setting the Hardware Clock: On my + machine, when you set it, it sets to that precise time. But one can + imagine another clock whose update oscillator marches on a steady one + second period, so updating the clock between any two oscillator ticks + is the same as updating it right at the earlier tick. To avoid any + complications that might cause, we set the clock as soon as possible + after an oscillator tick. + + + About synchronizing to the Hardware Clock when reading the time: The + precision of the Hardware Clock counters themselves is one second. + You can't read the counters and find out that is 12:01:02.5. But if + you consider the location in time of the counter's ticks as part of + its value, then its precision is as infinite as time is continuous! + What I'm saying is this: To find out the _exact_ time in the + hardware clock, we wait until the next clock tick (the next time the + second counter changes) and measure how long we had to wait. We + then read the value of the clock counters and subtract the wait time + and we know precisely what time it was when we set out to query the + time. + + hwclock uses this method, and considers the Hardware Clock to have + infinite precision. + + + Enhancements needed: + + - When waiting for whole second boundary in set_hardware_clock_exact, + fail if we miss the goal by more than .1 second, as could happen if + we get pre-empted (by the kernel dispatcher). + +****************************************************************************/ + diff --git a/hwclock/kd.c b/hwclock/kd.c new file mode 100644 index 000000000..fd4fdd5a1 --- /dev/null +++ b/hwclock/kd.c @@ -0,0 +1,167 @@ +/* kd.c - KDGHWCLK stuff, possibly m68k only */ +#include /* for close() */ +#include /* for O_RDONLY */ +#include + +#include "../defines.h" /* for HAVE_nanosleep */ +#include "clock.h" +#include "nls.h" + +static int con_fd = -1; /* opened by probe_for_kd_clock() */ + /* never closed */ + +/* Get defines for KDGHWCLK and KDSHWCLK (m68k) */ +#include +#ifndef KDGHWCLK +#define KDGHWCLK 0x4B50 /* get hardware clock */ +#define KDSHWCLK 0x4B51 /* set hardware clock */ +struct hwclk_time { + unsigned sec; /* 0..59 */ + unsigned min; /* 0..59 */ + unsigned hour; /* 0..23 */ + unsigned day; /* 1..31 */ + unsigned mon; /* 0..11 */ + unsigned year; /* 70... */ + int wday; /* 0..6, 0 is Sunday, -1 means unknown/don't set */ +}; +#endif + +static int +synchronize_to_clock_tick_kd(void) { +/*---------------------------------------------------------------------------- + Wait for the top of a clock tick by calling KDGHWCLK in a busy loop until + we see it. +-----------------------------------------------------------------------------*/ + int i; + + /* The time when we were called (and started waiting) */ + struct hwclk_time start_time, nowtime; + + if (debug) + printf(_("Waiting in loop for time from KDGHWCLK to change\n")); + + if (ioctl(con_fd, KDGHWCLK, &start_time) == -1) { + outsyserr(_("KDGHWCLK ioctl to read time failed")); + return 3; + } + + i = 0; + do { + /* Added by Roman Hodek */ + /* "The culprit is the fast loop with KDGHWCLK ioctls. It seems + the kernel gets confused by those on Amigas with A2000 RTCs + and simply hangs after some time. Inserting a nanosleep helps." */ + /* Christian T. Steigies: 1 instead of 1000000 is still sufficient + to keep the machine from freezing. */ + +#ifdef HAVE_nanosleep + struct timespec xsleep = { 0, 1 }; + nanosleep( &xsleep, NULL ); +#else + usleep(1); +#endif + + if (i++ >= 1000000) { + fprintf(stderr, _("Timed out waiting for time change.\n")); + return 2; + } + if (ioctl(con_fd, KDGHWCLK, &nowtime) == -1) { + outsyserr(_("KDGHWCLK ioctl to read time failed in loop")); + return 3; + } + } while (start_time.sec == nowtime.sec); + + return 0; +} + + +static int +read_hardware_clock_kd(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via + argument. Use ioctls to /dev/tty1 on what we assume is an m68k + machine. + + Note that we don't use /dev/console here. That might be a serial + console. +-----------------------------------------------------------------------------*/ + struct hwclk_time t; + + if (ioctl(con_fd, KDGHWCLK, &t) == -1) { + outsyserr(_("ioctl() failed to read time from /dev/tty1")); + exit(5); + } + + tm->tm_sec = t.sec; + tm->tm_min = t.min; + tm->tm_hour = t.hour; + tm->tm_mday = t.day; + tm->tm_mon = t.mon; + tm->tm_year = t.year; + tm->tm_wday = t.wday; + tm->tm_isdst = -1; /* Don't know if it's Daylight Savings Time */ + + return 0; +} + + +static int +set_hardware_clock_kd(const struct tm *new_broken_time) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time . Use ioctls to + /dev/tty1 on what we assume is an m68k machine. + + Note that we don't use /dev/console here. That might be a serial console. +----------------------------------------------------------------------------*/ + struct hwclk_time t; + + t.sec = new_broken_time->tm_sec; + t.min = new_broken_time->tm_min; + t.hour = new_broken_time->tm_hour; + t.day = new_broken_time->tm_mday; + t.mon = new_broken_time->tm_mon; + t.year = new_broken_time->tm_year; + t.wday = new_broken_time->tm_wday; + + if (ioctl(con_fd, KDSHWCLK, &t ) == -1) { + outsyserr(_("ioctl() to open /dev/tty1 failed")); + exit(1); + } + return 0; +} + +static int +get_permissions_kd(void) { + return 0; +} + +static struct clock_ops kd = { + "KDGHWCLK interface to m68k clock", + get_permissions_kd, + read_hardware_clock_kd, + set_hardware_clock_kd, + synchronize_to_clock_tick_kd, +}; + +/* return &kd if KDGHWCLK works, NULL otherwise */ +struct clock_ops * +probe_for_kd_clock() { + struct clock_ops *ret = NULL; + struct hwclk_time t; + + if (con_fd < 0) + con_fd = open("/dev/tty1", O_RDONLY); + if (con_fd >= 0) { + if (ioctl( con_fd, KDGHWCLK, &t ) == -1) { + if (errno != EINVAL) + outsyserr(_("KDGHWCLK ioctl failed")); + } else + ret = &kd; + } else { + /* probably KDGHWCLK exists on m68k only */ +#ifdef __m68k__ + outsyserr(_("Can't open /dev/tty1")); +#endif + } + return ret; +} diff --git a/hwclock/rtc.c b/hwclock/rtc.c new file mode 100644 index 000000000..2874bfa14 --- /dev/null +++ b/hwclock/rtc.c @@ -0,0 +1,396 @@ +/* rtc.c - Use /dev/rtc for clock access */ +#include /* for close() */ +#include /* for O_RDONLY */ +#include + +#include "clock.h" +#include "nls.h" + +/* + * Get defines for rtc stuff. + * + * Getting the rtc defines is nontrivial. + * The obvious way is by including + * but that again includes which again includes ... + * and on sparc and alpha this gives compilation errors for + * many kernel versions. So, we give the defines ourselves here. + * Moreover, some Sparc person decided to be incompatible, and + * used a struct rtc_time different from that used in mc146818rtc.h. + */ + +/* ia64 uses /dev/efirtc (char 10,136) */ +#if __ia64__ +#define RTC_DEV "/dev/efirtc" +#else +#define RTC_DEV "/dev/rtc" +#endif + +/* On Sparcs, there is a that defines different ioctls + (that are required on my machine). However, this include file + does not exist on other architectures. */ +/* One might do: +#ifdef __sparc__ +#include +#endif + */ +/* The following is roughly equivalent */ +struct sparc_rtc_time +{ + int sec; /* Seconds (0-59) */ + int min; /* Minutes (0-59) */ + int hour; /* Hour (0-23) */ + int dow; /* Day of the week (1-7) */ + int dom; /* Day of the month (1-31) */ + int month; /* Month of year (1-12) */ + int year; /* Year (0-99) */ +}; + +#define RTCGET _IOR('p', 20, struct sparc_rtc_time) +#define RTCSET _IOW('p', 21, struct sparc_rtc_time) + + +/* non-sparc stuff */ +#if 0 +#include +/* Check if the /dev/rtc interface is available in this version of + the system headers. 131072 is linux 2.0.0. */ +#if LINUX_VERSION_CODE >= 131072 +#include +#endif +#endif + +/* struct rtc_time is present since 1.3.99 */ +/* Earlier (since 1.3.89), a struct tm was used. */ +struct linux_rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +/* RTC_RD_TIME etc have this definition since 1.99.9 (pre2.0-9) */ +#ifndef RTC_RD_TIME +#define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time) +#define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time) +#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */ +#define RTC_UIE_OFF _IO('p', 0x04) /* Update int. enable off */ +#endif +/* RTC_EPOCH_READ and RTC_EPOCH_SET are present since 2.0.34 and 2.1.89 */ +#ifndef RTC_EPOCH_READ +#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ +#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ +#endif + + +static int +do_rtc_read_ioctl(int rtc_fd, struct tm *tm) { + int rc; + char *ioctlname; +#ifdef __sparc__ + struct sparc_rtc_time stm; + + ioctlname = "RTCGET"; + rc = ioctl(rtc_fd, RTCGET, &stm); +#else + ioctlname = "RTC_RD_TIME"; + rc = ioctl(rtc_fd, RTC_RD_TIME, tm); +#endif + if (rc == -1) { + perror(ioctlname); + fprintf(stderr, _("ioctl() to %s to read the time failed.\n"),RTC_DEV); + exit(5); + } +#ifdef __sparc__ + tm->tm_sec = stm.sec; + tm->tm_min = stm.min; + tm->tm_hour = stm.hour; + tm->tm_mday = stm.dom; + tm->tm_mon = stm.month - 1; + tm->tm_year = stm.year - 1900; + tm->tm_wday = stm.dow - 1; + tm->tm_yday = -1; /* day in the year */ +#endif + tm->tm_isdst = -1; /* don't know whether it's daylight */ + return 0; +} + + +static int +busywait_for_rtc_clock_tick(const int rtc_fd) { +/*---------------------------------------------------------------------------- + Wait for the top of a clock tick by reading /dev/rtc in a busy loop until + we see it. +-----------------------------------------------------------------------------*/ + struct tm start_time; + /* The time when we were called (and started waiting) */ + struct tm nowtime; + int i; /* local loop index */ + int rc; + + if (debug) + printf(_("Waiting in loop for time from %s to change\n"),RTC_DEV); + + rc = do_rtc_read_ioctl(rtc_fd, &start_time); + if (rc) + return 1; + + /* Wait for change. Should be within a second, but in case something + weird happens, we have a limit on this loop to reduce the impact + of this failure. + */ + for (i = 0; + (rc = do_rtc_read_ioctl(rtc_fd, &nowtime)) == 0 + && start_time.tm_sec == nowtime.tm_sec; + i++) + if (i >= 1000000) { + fprintf(stderr, _("Timed out waiting for time change.\n")); + return 2; + } + + if (rc) + return 3; + return 0; +} + + + +static int +synchronize_to_clock_tick_rtc(void) { +/*---------------------------------------------------------------------------- + Same as synchronize_to_clock_tick(), but just for /dev/rtc. +-----------------------------------------------------------------------------*/ +int rtc_fd; /* File descriptor of /dev/rtc */ +int ret; + + rtc_fd = open(RTC_DEV,O_RDONLY); + if (rtc_fd == -1) { + outsyserr(_("open() of %s failed"),RTC_DEV); + ret = 1; + } else { + int rc; /* Return code from ioctl */ + /* Turn on update interrupts (one per second) */ +#if defined(__alpha__) || defined(__sparc__) + /* Not all alpha kernels reject RTC_UIE_ON, but probably they should. */ + rc = -1; + errno = EINVAL; +#else + rc = ioctl(rtc_fd, RTC_UIE_ON, 0); +#endif + if (rc == -1 && errno == EINVAL) { + /* This rtc device doesn't have interrupt functions. This is typical + on an Alpha, where the Hardware Clock interrupts are used by the + kernel for the system clock, so aren't at the user's disposal. + */ + if (debug) + printf(_("%s does not have interrupt functions. "),RTC_DEV); + ret = busywait_for_rtc_clock_tick(rtc_fd); + } else if (rc == 0) { + unsigned long dummy; + + /* this blocks until the next update interrupt */ + rc = read(rtc_fd, &dummy, sizeof(dummy)); + if (rc == -1) { + outsyserr(_("read() to %s to wait for clock tick failed"),RTC_DEV); + ret = 1; + } else { + ret = 0; + } + /* Turn off update interrupts */ + rc = ioctl(rtc_fd, RTC_UIE_OFF, 0); + if (rc == -1) + outsyserr(_("ioctl() to %s to turn off update interrupts " + "failed"),RTC_DEV); + } else { + outsyserr(_("ioctl() to %s to turn on update interrupts " + "failed unexpectedly"),RTC_DEV); + ret = 1; + } + close(rtc_fd); + } + return ret; +} + + +static int +read_hardware_clock_rtc(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via + argument. Use ioctls to "rtc" device /dev/rtc. +-----------------------------------------------------------------------------*/ + int rtc_fd; /* File descriptor of /dev/rtc */ + + rtc_fd = open(RTC_DEV,O_RDONLY); + if (rtc_fd == -1) { + outsyserr(_("open() of %s failed"),RTC_DEV); + exit(5); + } + + /* Read the RTC time/date */ + do_rtc_read_ioctl(rtc_fd, tm); + + close(rtc_fd); + return 0; +} + + +static int +set_hardware_clock_rtc(const struct tm *new_broken_time) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the broken down time . + Use ioctls to "rtc" device /dev/rtc. +----------------------------------------------------------------------------*/ + int rc; + int rtc_fd; + + rtc_fd = open(RTC_DEV, O_RDONLY); + if (rtc_fd < 0) { + outsyserr(_("Unable to open %s"),RTC_DEV); + exit(5); + } else { + char *ioctlname; +#ifdef __sparc__ + struct sparc_rtc_time stm; + + stm.sec = new_broken_time->tm_sec; + stm.min = new_broken_time->tm_min; + stm.hour = new_broken_time->tm_hour; + stm.dom = new_broken_time->tm_mday; + stm.month = new_broken_time->tm_mon + 1; + stm.year = new_broken_time->tm_year + 1900; + stm.dow = new_broken_time->tm_wday + 1; + + ioctlname = "RTCSET"; + rc = ioctl(rtc_fd, RTCSET, &stm); +#else + ioctlname = "RTC_SET_TIME"; + rc = ioctl(rtc_fd, RTC_SET_TIME, new_broken_time); +#endif + if (rc == -1) { + perror(ioctlname); + fprintf(stderr, _("ioctl() to %s to set the time failed.\n"),RTC_DEV); + exit(5); + } else { + if (debug) + printf(_("ioctl(%s) was successful.\n"), ioctlname); + } + close(rtc_fd); + } + return 0; +} + + +static int +get_permissions_rtc(void) { + return 0; +} + +static struct clock_ops rtc = { + "/dev/rtc interface to clock", + get_permissions_rtc, + read_hardware_clock_rtc, + set_hardware_clock_rtc, + synchronize_to_clock_tick_rtc, +}; + +/* return &rtc if /dev/rtc can be opened, NULL otherwise */ +struct clock_ops * +probe_for_rtc_clock(){ + int rtc_fd = open(RTC_DEV, O_RDONLY); + if (rtc_fd > 0) { + close(rtc_fd); + return &rtc; + } + if (debug) + outsyserr(_("Open of %s failed"),RTC_DEV); + return NULL; +} + + + +int +get_epoch_rtc(unsigned long *epoch_p, int silent) { +/*---------------------------------------------------------------------------- + Get the Hardware Clock epoch setting from the kernel. +----------------------------------------------------------------------------*/ + int rtc_fd; + + rtc_fd = open(RTC_DEV, O_RDONLY); + if (rtc_fd < 0) { + if (!silent) { + if (errno == ENOENT) + fprintf(stderr, _( + "To manipulate the epoch value in the kernel, we must " + "access the Linux 'rtc' device driver via the device special " + "file %s. This file does not exist on this system.\n"),RTC_DEV); + else + outsyserr(_("Unable to open %s"),RTC_DEV); + } + return 1; + } + + if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) { + if (!silent) + outsyserr(_("ioctl(RTC_EPOCH_READ) to %s failed"),RTC_DEV); + close(rtc_fd); + return 1; + } + + if (debug) + printf(_("we have read epoch %ld from %s " + "with RTC_EPOCH_READ ioctl.\n"), *epoch_p,RTC_DEV); + + close(rtc_fd); + return 0; +} + + + +int +set_epoch_rtc(unsigned long epoch) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock epoch in the kernel. +----------------------------------------------------------------------------*/ + int rtc_fd; + + if (epoch < 1900) { + /* kernel would not accept this epoch value */ + /* Hmm - bad habit, deciding not to do what the user asks + just because one believes that the kernel might not like it. */ + fprintf(stderr, _("The epoch value may not be less than 1900. " + "You requested %ld\n"), epoch); + return 1; + } + + rtc_fd = open(RTC_DEV, O_RDONLY); + if (rtc_fd < 0) { + if (errno == ENOENT) + fprintf(stderr, _("To manipulate the epoch value in the kernel, we must " + "access the Linux 'rtc' device driver via the device special " + "file %s. This file does not exist on this system.\n"),RTC_DEV); + else + outsyserr(_("Unable to open %s"),RTC_DEV); + return 1; + } + + if (debug) + printf(_("setting epoch to %ld " + "with RTC_EPOCH_SET ioctl to %s.\n"), epoch, RTC_DEV); + + if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) { + if (errno == EINVAL) + fprintf(stderr, _("The kernel device driver for %s " + "does not have the RTC_EPOCH_SET ioctl.\n"),RTC_DEV); + else + outsyserr(_("ioctl(RTC_EPOCH_SET) to %s failed"),RTC_DEV); + close(rtc_fd); + return 1; + } + + close(rtc_fd); + return 0; +} diff --git a/hwclock/shhopt-1.1.lsm b/hwclock/shhopt-1.1.lsm new file mode 100644 index 000000000..a61a26969 --- /dev/null +++ b/hwclock/shhopt-1.1.lsm @@ -0,0 +1,17 @@ +Begin3 +Title: shhopt - library for parsing command line options. +Version: 1.1 +Entered-date: 06JUN96 +Description: C-functions for parsing command line options, both + traditional one-character options, and GNU'ish + --long-options. +Keywords: programming, library, lib, commandline +Author: sverrehu@ifi.uio.no (Sverre H. Huseby) +Primary-site: sunsite.unc.edu /pub/Linux/libs + shhopt-1.1.tar.gz +Platforms: Requires ANSI C-compiler. +Copying-policy: BeerWare: If you have the time and money, send me a bottle + of your favourite beer. If not, just send me a mail or + something. Copy and use as you wish; just leave the + author's name where you find it. +End diff --git a/hwclock/shhopt.c b/hwclock/shhopt.c new file mode 100644 index 000000000..ac3412829 --- /dev/null +++ b/hwclock/shhopt.c @@ -0,0 +1,468 @@ +/* $Id: shhopt.c,v 2.2 1997/07/06 23:11:55 aebr Exp $ */ +/************************************************************************** + * + * FILE shhopt.c + * + * DESCRIPTION Functions for parsing command line arguments. Values + * of miscellaneous types may be stored in variables, + * or passed to functions as specified. + * + * REQUIREMENTS Some systems lack the ANSI C -function strtoul. If your + * system is one of those, you'll ned to write one yourself, + * or get the GNU liberty-library (from prep.ai.mit.edu). + * + * WRITTEN BY Sverre H. Huseby + * + **************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "shhopt.h" +#include "nls.h" + +/************************************************************************** + * * + * P R I V A T E D A T A * + * * + **************************************************************************/ + +static void optFatalFunc(const char *, ...); +static void (*optFatal)(const char *format, ...) = optFatalFunc; + + + +/************************************************************************** + * * + * P R I V A T E F U N C T I O N S * + * * + **************************************************************************/ + +/*------------------------------------------------------------------------- + * + * NAME optFatalFunc + * + * FUNCTION Show given message and abort the program. + * + * INPUT format, ... + * Arguments used as with printf(). + * + * RETURNS Never returns. The program is aborted. + * + */ +void optFatalFunc(const char *format, ...) +{ + va_list ap; + + fflush(stdout); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + exit(99); +} + + + +/*------------------------------------------------------------------------- + * + * NAME optStructCount + * + * FUNCTION Get number of options in a optStruct. + * + * INPUT opt array of possible options. + * + * RETURNS Number of options in the given array. + * + * DESCRIPTION Count elements in an optStruct-array. The strcture must + * be ended using an element of type OPT_END. + * + */ +static int optStructCount(const optStruct opt[]) +{ + int ret = 0; + + while (opt[ret].type != OPT_END) + ++ret; + return ret; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optMatch + * + * FUNCTION Find a matching option. + * + * INPUT opt array of possible options. + * s string to match, without `-' or `--'. + * lng match long option, otherwise short. + * + * RETURNS Index to the option if found, -1 if not found. + * + * DESCRIPTION Short options are matched from the first character in + * the given string. + * + */ +static int optMatch(const optStruct opt[], const char *s, int lng) +{ + int nopt, q, matchlen = 0; + char *p; + + nopt = optStructCount(opt); + if (lng) { + if ((p = strchr(s, '=')) != NULL) + matchlen = p - s; + else + matchlen = strlen(s); + } + for (q = 0; q < nopt; q++) { + if (lng) { + if (!opt[q].longName) + continue; + if (strncmp(s, opt[q].longName, matchlen) == 0) + return q; + } else { + if (!opt[q].shortName) + continue; + if (*s == opt[q].shortName) + return q; + } + } + return -1; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optString + * + * FUNCTION Return a (static) string with the option name. + * + * INPUT opt the option to stringify. + * lng is it a long option? + * + * RETURNS Pointer to static string. + * + */ +static char *optString(const optStruct *opt, int lng) +{ + static char ret[31]; + + if (lng) { + strcpy(ret, "--"); + strncpy(ret + 2, opt->longName, 28); + } else { + ret[0] = '-'; + ret[1] = opt->shortName; + ret[2] = '\0'; + } + return ret; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optNeedsArgument + * + * FUNCTION Check if an option requires an argument. + * + * INPUT opt the option to check. + * + * RETURNS Boolean value. + * + */ +static int optNeedsArgument(const optStruct *opt) +{ + return opt->type == OPT_STRING + || opt->type == OPT_INT + || opt->type == OPT_UINT + || opt->type == OPT_LONG + || opt->type == OPT_ULONG; +} + + + +/*------------------------------------------------------------------------- + * + * NAME argvRemove + * + * FUNCTION Remove an entry from an argv-array. + * + * INPUT argc pointer to number of options. + * argv array of option-/argument-strings. + * i index of option to remove. + * + * OUTPUT argc new argument count. + * argv array with given argument removed. + * + */ +static void argvRemove(int *argc, char *argv[], int i) +{ + if (i >= *argc) + return; + while (i++ < *argc) + argv[i - 1] = argv[i]; + --*argc; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optExecute + * + * FUNCTION Perform the action of an option. + * + * INPUT opt array of possible options. + * arg argument to option, if it applies. + * lng was the option given as a long option? + * + * RETURNS Nothing. Aborts in case of error. + * + */ +static void optExecute(const optStruct *opt, char *arg, int lng) +{ + switch (opt->type) { + case OPT_FLAG: + if (opt->flags & OPT_CALLFUNC) + ((void (*)(void)) opt->arg)(); + else + *((int *) opt->arg) = 1; + break; + + case OPT_STRING: + if (opt->flags & OPT_CALLFUNC) + ((void (*)(char *)) opt->arg)(arg); + else + *((char **) opt->arg) = arg; + break; + + case OPT_INT: + case OPT_LONG: { + long tmp; + char *e; + + tmp = strtol(arg, &e, 10); + if (*e) + optFatal(_("invalid number `%s'\n"), arg); + if (errno == ERANGE + || (opt->type == OPT_INT && (tmp > INT_MAX || tmp < INT_MIN))) + optFatal(_("number `%s' to `%s' out of range\n"), + arg, optString(opt, lng)); + if (opt->type == OPT_INT) { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(int)) opt->arg)((int) tmp); + else + *((int *) opt->arg) = (int) tmp; + } else /* OPT_LONG */ { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(long)) opt->arg)(tmp); + else + *((long *) opt->arg) = tmp; + } + break; + } + + case OPT_UINT: + case OPT_ULONG: { + unsigned long tmp; + char *e; + + tmp = strtoul(arg, &e, 10); + if (*e) + optFatal(_("invalid number `%s'\n"), arg); + if (errno == ERANGE + || (opt->type == OPT_UINT && tmp > UINT_MAX)) + optFatal(_("number `%s' to `%s' out of range\n"), + arg, optString(opt, lng)); + if (opt->type == OPT_UINT) { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(unsigned)) opt->arg)((unsigned) tmp); + else + *((unsigned *) opt->arg) = (unsigned) tmp; + } else /* OPT_ULONG */ { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(unsigned long)) opt->arg)(tmp); + else + *((unsigned long *) opt->arg) = tmp; + } + break; + } + + default: + break; + } +} + + + +/************************************************************************** + * * + * P U B L I C F U N C T I O N S * + * * + **************************************************************************/ + +/*------------------------------------------------------------------------- + * + * NAME optSetFatalFunc + * + * FUNCTION Set function used to display error message and exit. + * + * SYNOPSIS #include "shhmsg.h" + * void optSetFatalFunc(void (*f)(const char *, ...)); + * + * INPUT f function accepting printf()'like parameters, + * that _must_ abort the program. + * + */ +void optSetFatalFunc(void (*f)(const char *, ...)) +{ + optFatal = f; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optParseOptions + * + * FUNCTION Parse commandline options. + * + * SYNOPSIS #include "shhopt.h" + * void optParseOptions(int *argc, char *argv[], + * const optStruct opt[], int allowNegNum); + * + * INPUT argc Pointer to number of options. + * argv Array of option-/argument-strings. + * opt Array of possible options. + * allowNegNum + * a negative number is not to be taken as + * an option. + * + * OUTPUT argc new argument count. + * argv array with arguments removed. + * + * RETURNS Nothing. Aborts in case of error. + * + * DESCRIPTION This function checks each option in the argv-array + * against strings in the opt-array, and `executes' any + * matching action. Any arguments to the options are + * extracted and stored in the variables or passed to + * functions pointed to by entries in opt. + * + * Options and arguments used are removed from the argv- + * array, and argc is decreased accordingly. + * + * Any error leads to program abortion. + * + */ +void optParseOptions(int *argc, char *argv[], + const optStruct opt[], int allowNegNum) +{ + int ai, /* argv index. */ + optarg, /* argv index of option argument, or -1 if none. */ + mi, /* Match index in opt. */ + done; + char *arg, /* Pointer to argument to an option. */ + *o, /* pointer to an option character */ + *p; + + /* + * Loop through all arguments. + */ + for (ai = 0; ai < *argc; ) { + /* + * "--" indicates that the rest of the argv-array does not + * contain options. + */ + if (strcmp(argv[ai], "--") == 0) { + argvRemove(argc, argv, ai); + break; + } + + if (allowNegNum && argv[ai][0] == '-' && isdigit(argv[ai][1])) { + ++ai; + continue; + } else if (strncmp(argv[ai], "--", 2) == 0) { + /* long option */ + /* find matching option */ + if ((mi = optMatch(opt, argv[ai] + 2, 1)) < 0) + optFatal(_("unrecognized option `%s'\n"), argv[ai]); + + /* possibly locate the argument to this option. */ + arg = NULL; + if ((p = strchr(argv[ai], '=')) != NULL) + arg = p + 1; + + /* does this option take an argument? */ + optarg = -1; + if (optNeedsArgument(&opt[mi])) { + /* option needs an argument. find it. */ + if (!arg) { + if ((optarg = ai + 1) == *argc) + optFatal(_("option `%s' requires an argument\n"), + optString(&opt[mi], 1)); + arg = argv[optarg]; + } + } else { + if (arg) + optFatal(_("option `%s' doesn't allow an argument\n"), + optString(&opt[mi], 1)); + } + /* perform the action of this option. */ + optExecute(&opt[mi], arg, 1); + /* remove option and any argument from the argv-array. */ + if (optarg >= 0) + argvRemove(argc, argv, ai); + argvRemove(argc, argv, ai); + } else if (*argv[ai] == '-') { + /* A dash by itself is not considered an option. */ + if (argv[ai][1] == '\0') { + ++ai; + continue; + } + /* Short option(s) following */ + o = argv[ai] + 1; + done = 0; + optarg = -1; + while (*o && !done) { + /* find matching option */ + if ((mi = optMatch(opt, o, 0)) < 0) + optFatal(_("unrecognized option `-%c'\n"), *o); + + /* does this option take an argument? */ + optarg = -1; + arg = NULL; + if (optNeedsArgument(&opt[mi])) { + /* option needs an argument. find it. */ + arg = o + 1; + if (!*arg) { + if ((optarg = ai + 1) == *argc) + optFatal(_("option `%s' requires an argument\n"), + optString(&opt[mi], 0)); + arg = argv[optarg]; + } + done = 1; + } + /* perform the action of this option. */ + optExecute(&opt[mi], arg, 0); + ++o; + } + /* remove option and any argument from the argv-array. */ + if (optarg >= 0) + argvRemove(argc, argv, ai); + argvRemove(argc, argv, ai); + } else { + /* a non-option argument */ + ++ai; + } + } +} diff --git a/hwclock/shhopt.h b/hwclock/shhopt.h new file mode 100644 index 000000000..ca8501ef5 --- /dev/null +++ b/hwclock/shhopt.h @@ -0,0 +1,33 @@ +/* $Id: shhopt.h,v 2.2 1997/07/06 23:11:58 aebr Exp $ */ +#ifndef SHHOPT_H +#define SHHOPT_H + +/* constants for recognized option types. */ +typedef enum { + OPT_END, /* nothing. used as ending element. */ + OPT_FLAG, /* no argument following. sets variable to 1. */ + OPT_STRING, /* string argument. */ + OPT_INT, /* signed integer argument. */ + OPT_UINT, /* unsigned integer argument. */ + OPT_LONG, /* signed long integer argument. */ + OPT_ULONG, /* unsigned long integer argument. */ +} optArgType; + +/* flags modifying the default way options are handeled. */ +#define OPT_CALLFUNC 1 /* pass argument to a function. */ + +typedef struct { + char shortName; /* Short option name. */ + char *longName; /* Long option name, no including '--'. */ + optArgType type; /* Option type. */ + void *arg; /* Pointer to variable to fill with argument, + * or pointer to function if Type == OPT_FUNC. */ + int flags; /* Modifier flags. */ +} optStruct; + + +void optSetFatalFunc(void (*f)(const char *, ...)); +void optParseOptions(int *argc, char *argv[], + const optStruct opt[], int allowNegNum); + +#endif diff --git a/kbd/kbdrate.c b/kbd/kbdrate.c index 747757daf..df116e1e0 100644 --- a/kbd/kbdrate.c +++ b/kbd/kbdrate.c @@ -273,7 +273,8 @@ int main( int argc, char **argv ) close( fd ); - if (!silent) printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"), + if (!silent) + printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"), valid_rates[value & 0x1f] / 10.0, valid_delays[ (value & 0x60) >> 5 ] ); diff --git a/lib/Makefile b/lib/Makefile index a9f8596d1..31e953ce7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,9 +1,7 @@ include ../make_include include ../MCONFIG -CFLAGS=-I$(LIB) $(OPT) - -all: err.o my_reboot.o setproctitle.o env.o +all: err.o my_reboot.o setproctitle.o env.o carefulputc.o err.o: err.c @@ -13,6 +11,8 @@ env.o: env.h setproctitle.o: setproctitle.h +carefulputc.o: carefulputc.h + .PHONY: clean clean: -rm -f *.o *~ core diff --git a/lib/carefulputc.c b/lib/carefulputc.c new file mode 100644 index 000000000..932233772 --- /dev/null +++ b/lib/carefulputc.c @@ -0,0 +1,26 @@ +/* putc() for use in write and wall (that sometimes are sgid tty) */ +/* Avoid control characters in our locale, and also ASCII control characters. + Note that the locale of the recipient is unknown. */ +#include +#include +#include "carefulputc.h" + +#define iso8859x_iscntrl(c) \ + (((c) & 0x7f) < 0x20 || (c) == 0x7f) + +int +carefulputc(int c, FILE *fp) { + int ret; + + if (c == '\007' || c == '\t' || c == '\r' || c == '\n' || + (!iso8859x_iscntrl(c) && (isprint(c) || isspace(c)))) + ret = putc(c, fp); + else if ((c & 0x80) || !isprint(c^0x40)) + ret = fprintf(fp, "\\%3o", (unsigned char) c); + else { + ret = putc('^', fp); + if (ret != EOF) + ret = putc(c^0x40, fp); + } + return (ret < 0) ? EOF : 0; +} diff --git a/lib/carefulputc.h b/lib/carefulputc.h new file mode 100644 index 000000000..29cc75da0 --- /dev/null +++ b/lib/carefulputc.h @@ -0,0 +1 @@ +extern int carefulputc(int c, FILE *fp); diff --git a/lib/nls.h b/lib/nls.h index 67b42a999..d36a5bc88 100644 --- a/lib/nls.h +++ b/lib/nls.h @@ -1,3 +1,4 @@ +int main(int argc, char *argv[]); #include "../defines.h" /* for HAVE_locale_h */ diff --git a/lib/pathnames.h b/lib/pathnames.h index 60797f94e..672b58e92 100644 --- a/lib/pathnames.h +++ b/lib/pathnames.h @@ -128,7 +128,7 @@ Libc5 and glibc 2.0-2.1 have /var/spool/mail, but glibc 2.1.1 has /var/mail. /* used in login-utils/shutdown.c */ #define _PATH_MTAB "/etc/mtab" #define _PATH_UMOUNT "/bin/umount" -#define UMOUNT_ARGS "umount", "-a" +#define UMOUNT_ARGS "umount", "-a", "-t", "nodevfs" #define SWAPOFF_ARGS "swapoff", "-a" /* used in login-utils/setpwnam.h and login-utils/islocal.c */ diff --git a/lib/widechar.h b/lib/widechar.h index a8d288298..c440006f7 100644 --- a/lib/widechar.h +++ b/lib/widechar.h @@ -38,4 +38,6 @@ # define wcsdup strdup # define wcslen strlen +# define wcwidth(c) 1 + #endif diff --git a/login-utils/Makefile b/login-utils/Makefile index 0960854ec..d986501e1 100644 --- a/login-utils/Makefile +++ b/login-utils/Makefile @@ -19,7 +19,7 @@ MAN1.PASSWD= passwd.1 MAN8.GETTY= agetty.8 MAN8.INIT= fastboot.8 fasthalt.8 halt.8 reboot.8 simpleinit.8 shutdown.8 \ - need.8 + initctl.8 MAN8.PUTILS= vipw.8 vigr.8 @@ -28,7 +28,7 @@ MAN8.PUTILS= vipw.8 vigr.8 SBIN.GETTY= agetty -SBIN.INIT= simpleinit shutdown need +SBIN.INIT= simpleinit shutdown initctl BIN.PUTILS= login @@ -84,14 +84,22 @@ all-misc: $(USRBIN.MISC) # Rules for everything else -agetty.o: $(LIB)/pathnames.h +checktty.o login.o: login.h +cryptocard.o login.o: cryptocard.h +chfn.o chsh.o islocal.o passwd.o: islocal.h +chfn.o chsh.o passwd.o setpwnam.o vipw.o: setpwnam.h +chfn.o chsh.o login.o newgrp.o passwd.o simpleinit.o: my_crypt.h +initctl.o simpleinit.o: simpleinit.h +agetty.o islocal.o last.o setpwnam.o shutdown.o simpleinit.o \ + vipw.o: $(LIB)/pathnames.h +shutdown.o simpleinit.o: $(LIB)/linux_reboot.h +wall.o: ttymsg.h $(LIB)/carefulputc.h + agetty: agetty.o chfn: chfn.o islocal.o setpwnam.o $(LIB)/env.o $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) chsh: chsh.o islocal.o setpwnam.o $(LIB)/env.o $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) -islocal.o: $(LIB)/pathnames.h -last.o: $(LIB)/pathnames.h last: last.o ifeq "$(HAVE_PAM)" "yes" @@ -107,36 +115,35 @@ mesg: mesg.o $(ERR_O) newgrp: newgrp.o $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) -setpwnam.o: $(LIB)/pathnames.h -shutdown.o: $(LIB)/pathnames.h $(LIB)/linux_reboot.h shutdown: shutdown.o $(LIB)/my_reboot.o -simpleinit.o: $(LIB)/pathnames.h $(LIB)/linux_reboot.h simpleinit.h -need.o: simpleinit.h simpleinit: simpleinit.o $(LIB)/my_reboot.o $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) -need: need.o +initctl: initctl.o $(CC) $(LDFLAGS) -o $@ $^ -vipw.o: $(LIB)/pathnames.h vipw: vipw.o newgrp.o: $(LIB)/pathnames.h $(CC) -c $(CFLAGS) $(PAMFL) newgrp.c -wall: wall.o ttymsg.o +wall: wall.o ttymsg.o $(LIB)/carefulputc.o +LOGINFLAGS= ifeq "$(USE_TTY_GROUP)" "yes" + LOGINFLAGS += -DUSE_TTY_GROUP +endif +ifeq "$(ALLOW_VCS_USE)" "yes" + LOGINFLAGS += -DCHOWNVCS +endif + login.o: login.c $(LIB)/pathnames.h $(LIB)/setproctitle.c $(LIB)/setproctitle.h - $(CC) -c $(CFLAGS) $(PAMFL) -DUSE_TTY_GROUP login.c + $(CC) -c $(CFLAGS) $(PAMFL) $(LOGINFLAGS) login.c + +# LOGINFLAGS here only for -DUSE_TTY_GROUP mesg.o: mesg.c $(LIB)/errs.h - $(CC) -c $(CFLAGS) -DUSE_TTY_GROUP mesg.c -else -login.o: $(LIB)/pathnames.h - $(CC) -c $(CFLAGS) $(PAMFL) login.c -mesg.o: $(LIB)/errs.h -endif + $(CC) -c $(CFLAGS) $(LOGINFLAGS) mesg.c passwd: passwd.o islocal.o setpwnam.o $(LIB)/env.o $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) @@ -159,7 +166,7 @@ install: all $(WHAT_TO_INSTALL) install-putils: $(BIN.PUTILS) $(USRBIN.PUTILS) $(USRSBIN.PUTILS) $(INSTALLDIR) $(BINDIR) $(USRBINDIR) $(USRSBINDIR) - $(INSTALLSUID) $(BIN.PUTILS) $(BINDIR) + $(INSTALLBIN) $(BIN.PUTILS) $(BINDIR) $(INSTALLSUID) $(USRBIN.PUTILS) $(USRBINDIR) $(INSTALLBIN) $(USRSBIN.PUTILS) $(USRSBINDIR) (cd $(USRSBINDIR); ln -sf vipw vigr) @@ -183,7 +190,12 @@ install-init: $(SBIN.INIT) (cd $(SHUTDOWNDIR); ln -sf shutdown fastboot) (cd $(SHUTDOWNDIR); ln -sf shutdown halt) (cd $(SHUTDOWNDIR); ln -sf shutdown fasthalt) - (cd $(SHUTDOWNDIR); ln -sf need display-services) + (cd $(SHUTDOWNDIR); ln -sf initctl need) + (cd $(SHUTDOWNDIR); ln -sf initctl display-services) + (cd $(SHUTDOWNDIR); ln -sf initctl provide) + (cd $(MAN8DIR); ln -sf initctl.8 need.8) + (cd $(MAN8DIR); ln -sf initctl.8 display-services.8) + (cd $(MAN8DIR); ln -sf initctl.8 provide.8) install-getty: $(SBIN.GETTY) diff --git a/login-utils/agetty.c b/login-utils/agetty.c index 6ae4e8335..63f4adfa6 100644 --- a/login-utils/agetty.c +++ b/login-utils/agetty.c @@ -489,6 +489,38 @@ parse_args(argc, argv, op) if (argc > optind && argv[optind]) setenv ("TERM", argv[optind], 1); +#ifdef DO_DEVFS_FIDDLING + /* + * some devfs junk, following Goswin Brederlow: + * turn ttyS into tts/ + * turn tty into vc/ + */ + if (op->tty && strlen(op->tty) < 90) { + char dev_name[100]; + struct stat st; + + if (strncmp(op->tty, "ttyS", 4) == 0) { + strcpy(dev_name, "/dev/"); + strcat(dev_name, op->tty); + if (stat(dev_name, &st) < 0) { + strcpy(dev_name, "/dev/tts/"); + strcat(dev_name, op->tty + 4); + if (stat(dev_name, &st) == 0) + op->tty = strdup(dev_name + 5); + } + } else if (strncmp(op->tty, "tty", 3) == 0) { + strcpy(dev_name, "/dev/"); + strncat(dev_name, op->tty, 90); + if (stat(dev_name, &st) < 0) { + strcpy(dev_name, "/dev/vc/"); + strcat(dev_name, op->tty + 3); + if (stat(dev_name, &st) == 0) + op->tty = strdup(dev_name + 5); + } + } + } +#endif + debug(_("exiting parseargs\n")); } @@ -505,7 +537,7 @@ parse_speeds(op, arg) for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) { if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0) error(_("bad speed: %s"), cp); - if (op->numspeed > MAX_SPEED) + if (op->numspeed >= MAX_SPEED) error(_("too many alternate speeds")); } debug(_("exiting parsespeeds\n")); @@ -847,8 +879,11 @@ do_prompt(op, tp) case 'o': { char domainname[256]; - +#ifdef HAVE_getdomainname getdomainname(domainname, sizeof(domainname)); +#else + strcpy(domainname, "unknown_domain"); +#endif domainname[sizeof(domainname)-1] = '\0'; printf ("%s", domainname); } diff --git a/login-utils/checktty.c b/login-utils/checktty.c index 66fee7338..6269b6b07 100644 --- a/login-utils/checktty.c +++ b/login-utils/checktty.c @@ -29,12 +29,7 @@ #endif #include "pathnames.h" - -/* functions in login.c */ -void badlogin(const char *s); -void sleepexit(int); -extern struct hostent hostaddress; -extern char *hostname; +#include "login.h" #ifdef TESTING struct hostent hostaddress; @@ -43,13 +38,13 @@ char *hostname; void badlogin(const char *s) { - printf(_("badlogin: %s\n"), s); + printf("badlogin: %s\n", s); } void sleepexit(int x) { - printf(_("sleepexit %d\n"), x); + printf("sleepexit %d\n", x); exit(1); } #endif @@ -315,7 +310,7 @@ in_class(const char *tty, char *class) } /* start JDS - SBA */ -void +static void free_group(struct grplist *ge) { if (ge) { @@ -326,7 +321,7 @@ free_group(struct grplist *ge) } } -void +static void free_class(struct ttyclass *tc) { if (tc) { @@ -339,7 +334,7 @@ free_class(struct ttyclass *tc) } } -void +static void free_all(void) { free_class(ttyclasses); diff --git a/login-utils/chfn.c b/login-utils/chfn.c index 73a9b8918..de228241b 100644 --- a/login-utils/chfn.c +++ b/login-utils/chfn.c @@ -34,6 +34,8 @@ #include #include #include "my_crypt.h" +#include "islocal.h" +#include "setpwnam.h" #include "nls.h" #include "env.h" @@ -42,15 +44,6 @@ #include #endif -extern int is_local(char *); - -#undef P -#if __STDC__ -#define P(foo) foo -#else -#define P(foo) () -#endif - typedef unsigned char boolean; #define false 0 #define true 1 @@ -69,17 +62,15 @@ struct finfo { char *other; }; -static boolean parse_argv P((int argc, char *argv[], struct finfo *pinfo)); -static void usage P((FILE *fp)); -static void parse_passwd P((struct passwd *pw, struct finfo *pinfo)); -static void ask_info P((struct finfo *oldfp, struct finfo *newfp)); -static char *prompt P((char *question, char *def_val)); -static int check_gecos_string P((char *msg, char *gecos)); -static boolean set_changed_data P((struct finfo *oldfp, struct finfo *newfp)); -static int save_new_data P((struct finfo *pinfo)); -static void *xmalloc P((int bytes)); - -extern int setpwnam P((struct passwd *pwd)); +static boolean parse_argv (int argc, char *argv[], struct finfo *pinfo); +static void usage (FILE *fp); +static void parse_passwd (struct passwd *pw, struct finfo *pinfo); +static void ask_info (struct finfo *oldfp, struct finfo *newfp); +static char *prompt (char *question, char *def_val); +static int check_gecos_string (char *msg, char *gecos); +static boolean set_changed_data (struct finfo *oldfp, struct finfo *newfp); +static int save_new_data (struct finfo *pinfo); +static void *xmalloc (int bytes); #define memzero(ptr, size) memset((char *) ptr, 0, size) diff --git a/login-utils/chsh.c b/login-utils/chsh.c index f17b176fb..d1a3fa820 100644 --- a/login-utils/chsh.c +++ b/login-utils/chsh.c @@ -37,6 +37,8 @@ #include #include #include "my_crypt.h" +#include "islocal.h" +#include "setpwnam.h" #include "nls.h" #include "env.h" @@ -45,15 +47,6 @@ #include #endif -extern int is_local(char *); - -#undef P -#if __STDC__ -#define P(foo) foo -#else -#define P(foo) () -#endif - typedef unsigned char boolean; #define false 0 #define true 1 @@ -71,19 +64,17 @@ struct sinfo { char *shell; }; -static void parse_argv P((int argc, char *argv[], struct sinfo *pinfo)); -static void usage P((FILE *fp)); -static char *prompt P((char *question, char *def_val)); -static int check_shell P((char *shell)); -static boolean get_shell_list P((char *shell)); -static void *xmalloc P((int bytes)); -extern int setpwnam P((struct passwd *pwd)); +static void parse_argv (int argc, char *argv[], struct sinfo *pinfo); +static void usage (FILE *fp); +static char *prompt (char *question, char *def_val); +static int check_shell (char *shell); +static boolean get_shell_list (char *shell); +static void *xmalloc (int bytes); + #define memzero(ptr, size) memset((char *) ptr, 0, size) -int main (argc, argv) - int argc; - char *argv[]; -{ +int +main (int argc, char *argv[]) { char *cp, *shell, *oldshell; uid_t uid; struct sinfo info; diff --git a/login-utils/cryptocard.c b/login-utils/cryptocard.c index 1195b2eb8..9e221cbe6 100644 --- a/login-utils/cryptocard.c +++ b/login-utils/cryptocard.c @@ -54,9 +54,7 @@ #include "../libdes/des.h" #endif /* EAY_LIBDES */ -extern char *getpass(const char *prompt); -extern struct passwd *pwd; -extern int timeout; +#include "cryptocard.h" static char * generate_challenge(void) diff --git a/login-utils/cryptocard.h b/login-utils/cryptocard.h new file mode 100644 index 000000000..a967137f9 --- /dev/null +++ b/login-utils/cryptocard.h @@ -0,0 +1,7 @@ +/* defined in cryptocard.c */ +extern int cryptocard (void); + +/* defined in login.c */ +extern struct passwd *pwd; +extern int timeout; + diff --git a/login-utils/initctl.8 b/login-utils/initctl.8 new file mode 100644 index 000000000..1aa421a02 --- /dev/null +++ b/login-utils/initctl.8 @@ -0,0 +1,106 @@ +.\" Copyright (C) 2000 Richard Gooch +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +.\" +.\" Richard Gooch may be reached by email at rgooch@atnf.csiro.au +.\" The postal address is: +.\" Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. +.\" +.\" initctl.8 Richard Gooch 6-NOV-2000 +.\" +.TH INITCTL 8 "6 Nov 2000" "Util-Linux Package" +.SH NAME +initctl \- utility to control simpleinit(8) +.SH SYNOPSIS +.nf +\fBneed\fP [\fB-r\fP] \fBservice\fP +.BR display-services +\fBprovide service\fP +.fi +.SH OVERVIEW +The \fBneed\fP programme is designed to help improve the robustness, +scalability and readability of system boot scripts. It is now possible +to write a modularised set of boot scripts without the complex and +fragile numbered symlink scheme used in SysV-style boot scripts. Each +script can simply declare, using \fBneed\fP(8), what must run before +them. +.SH DESCRIPTION for need +The \fBneed\fP programme is a utility that tells \fBsimpleinit\fP(8) +to start a \fIservice\fP (usually a script in \fI/sbin/init.d\fP) and +will wait for the service to become available. If the service is +already available, it will not be started again. + +The \fB-r\fP option is used to tell \fBsimpleinit\fP(8) to "roll back" +(stop) services up to (but not including) \fIservice\fP. If +\fIservice\fP is not specified, all services are stopped. The \fB-r\fP +option thus allows the system to be partially or wholly shut down in +an orderly fashion. The \fBshutdown\fP(8) programme still needs to be +run. + +.SH DESCRIPTION for display-services +When invoked as \fBdisplay-services\fP it will write the list of +currently available services and the list of failed services to the +standard output. + +.SH DESCRIPTION for provide +When invoked as \fBprovide\fP it tells \fBsimpleinit\fP(8) that the +parent (calling) process will be providing a service with name +\fIservice\fP. If the calling process exits successfully (status 0) +the service is deemed to be available. Only one instance of +\fIservice\fP may be started, so alternate providers will block and +may fail. + +Using \fBprovide\fP it is possible to have multiple potential +providers for the same (generic) service (e.g. \fBsendmail\fP and +\fBqmail\fP both provide a \fBmta\fP service), where only one actually +provides the service. This may be used by service startup scripts +which check for configuration files. +.SH EXIT CODE +The exit code from \fBneed\fP is 0 if the service was successfully +started, 1 if the service failed badly, and 2 if the service is +unavailable (i.e. disabled in configuration files). These exit codes +reflect the exit codes from the service startup scripts. + +The exit code from \fBneed -r\fP is 0 if the service was successfully +stopped, 1 if the service could not be stopped, and 2 if the service +was not available to start with. The service shutdown scripts may only +return 0 (for success) or 1 (for failure). + +The exit code from \fBprovide\fP is 0 if the service may be provided, +1 if it may not, and 2 if the parent process is not a child of +init. It may block waiting for another provider which is initialising +the service. +.SH SIGNALS +\fBneed\fP(8) uses \fBSIGUSR1\fP, \fBSIGUSR2\fP and \fBSIGPOLL\fP for +communication with \fBsimpleinit\fP(8). Don't send these signals to +it. +.SH FILES +.PD 0 +.TP 20 +.BI /dev/initctl +This is the control FIFO, created by \fBsimpleinit\fP(8), which +\fBneed\fP(8) writes commands to. +.SH SEE ALSO +.BR simpleinit (8), +.BR init (8) +.PP +A more complete discussion of the new boot script system, based on +\fBneed\fP(8), is available from: +http://www.atnf.csiro.au/~rgooch/linux/boot-scripts/ +.SH AUTHOR +Richard Gooch (rgooch@atnf.csiro.au) +.SH AVAILABILITY +The Util-Linux package is available from: +ftp://ftp.??.kernel.org/pub/linux/utils/util-linux/ diff --git a/login-utils/initctl.c b/login-utils/initctl.c new file mode 100644 index 000000000..6fb8d097f --- /dev/null +++ b/login-utils/initctl.c @@ -0,0 +1,210 @@ +/* initctl.c + + Source file for initctl (init(8) control tool). + + Copyright (C) 2000 Richard Gooch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Richard Gooch may be reached by email at rgooch@atnf.csiro.au + The postal address is: + Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. +*/ + +/* + This tool will send control messages to init(8). For example, it may + request init(8) to start a service and will wait for that service to be + available. If the service is already available, init(8) will not start it + again. + This tool may also be used to inspect the list of currently available + services. + + + Written by Richard Gooch 28-FEB-2000 + + Updated by Richard Gooch 11-OCT-2000: Added provide support. + + Last updated by Richard Gooch 6-NOV-2000: Renamed to initctl.c + + +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "simpleinit.h" + + +static void signal_handler (int sig); + + +static int caught_signal = 0; + + +int main (int argc, char **argv) +{ + int fd, nbytes; + struct sigaction sa; + sigset_t ss; + char *ptr; + long buffer[COMMAND_SIZE / sizeof (long) + 1]; + struct command_struct *command = (struct command_struct *) buffer; + + sigemptyset (&ss); + sigaddset (&ss, SIG_PRESENT); + sigaddset (&ss, SIG_NOT_PRESENT); + sigaddset (&ss, SIG_FAILED); + sigprocmask (SIG_BLOCK, &ss, NULL); + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = signal_handler; + sigaction (SIG_PRESENT, &sa, NULL); + sigaction (SIG_NOT_PRESENT, &sa, NULL); + sigaction (SIG_FAILED, &sa, NULL); + command->pid = getpid (); + command->ppid = getppid (); + if ( ( ptr = strrchr (argv[0], '/') ) == NULL ) ptr = argv[0]; + else ++ptr; + /* First generate command number by looking at invocation name */ + if (strcmp (ptr, "display-services") == 0) + command->command = COMMAND_DUMP_LIST; + else if (strcmp (ptr, "need") == 0) command->command = COMMAND_NEED; + else if (strcmp (ptr, "provide") == 0) command->command = COMMAND_PROVIDE; + else command->command = COMMAND_TEST; + /* Now check for switches */ + if ( (argc > 1) && (argv[1][0] == '-') ) + { + switch (argv[1][1]) + { + case 'n': + command->command = COMMAND_NEED; + break; + case 'r': + command->command = COMMAND_ROLLBACK; + break; + case 'd': + command->command = COMMAND_DUMP_LIST; + break; + case 'p': + command->command = COMMAND_PROVIDE; + break; + default: + fprintf (stderr, "Illegal switch: \"%s\"\n", argv[1]); + exit (1); + /*break;*/ + } + --argc; + ++argv; + } + switch (command->command) + { + case COMMAND_NEED: + case COMMAND_PROVIDE: + if (argc < 2) + { + fprintf (stderr, "Usage:\tneed|provide programme\n"); + exit (1); + } + /* Fall through */ + case COMMAND_ROLLBACK: + if (argc > 1) strcpy (command->name, argv[1]); + else command->name[0] = '\0'; + break; + case COMMAND_DUMP_LIST: + if (tmpnam (command->name) == NULL) + { + fprintf (stderr, "Unable to create a unique filename\t%s\n", + ERRSTRING); + exit (1); + } + if (mkfifo (command->name, S_IRUSR) != 0) + { + fprintf (stderr, "Unable to create FIFO: \"%s\"\t%s\n", + command->name, ERRSTRING); + exit (1); + } + break; + } + if ( ( fd = open ("/dev/initctl", O_WRONLY, 0) ) < 0 ) + { + fprintf (stderr, "Error opening\t%s\n", ERRSTRING); + exit (1); + } + if (write (fd, buffer, COMMAND_SIZE) < COMMAND_SIZE) + { + fprintf (stderr, "Error writing\t%s\n", ERRSTRING); + exit (1); + } + close (fd); + if (command->command != COMMAND_DUMP_LIST) + { + sigemptyset (&ss); + while (caught_signal == 0) sigsuspend (&ss); + switch (command->command) + { + case COMMAND_PROVIDE: + switch (caught_signal) + { + case SIG_PRESENT: + return 1; + case SIG_NOT_PRESENT: + return 0; + case SIG_NOT_CHILD: + fprintf (stderr, "Error\n"); + return 2; + default: + return 3; + } + break; + default: + switch (caught_signal) + { + case SIG_PRESENT: + return 0; + case SIG_NOT_PRESENT: + return 2; + case SIG_FAILED: + return 1; + default: + return 3; + } + break; + } + return 3; + } + /* Read back the data and display it */ + if ( ( fd = open (command->name, O_RDONLY, 0) ) < 0 ) + { + fprintf (stderr, "Error opening:\"%s\"\t%s\n", + command->name, ERRSTRING); + exit (1); + } + unlink (command->name); + fflush (stdout); + while ( ( nbytes = read (fd, buffer, COMMAND_SIZE) ) > 0 ) + write (1, buffer, nbytes); + close (fd); + return (0); +} /* End Function main */ + +static void signal_handler (int sig) +{ + caught_signal = sig; +} /* End Function signal_handler */ diff --git a/login-utils/islocal.c b/login-utils/islocal.c index 10a709b56..87f8f1cb2 100644 --- a/login-utils/islocal.c +++ b/login-utils/islocal.c @@ -17,10 +17,12 @@ */ #include +#include #include #include "nls.h" #include "pathnames.h" +#include "islocal.h" #define MAX_LENGTH 1024 diff --git a/login-utils/islocal.h b/login-utils/islocal.h new file mode 100644 index 000000000..305bc57c6 --- /dev/null +++ b/login-utils/islocal.h @@ -0,0 +1 @@ +extern int is_local(char *user); diff --git a/login-utils/last.c b/login-utils/last.c index b78d00b86..8375f9f07 100644 --- a/login-utils/last.c +++ b/login-utils/last.c @@ -90,16 +90,16 @@ static char *file = _PATH_WTMP; /* wtmp file */ static int doyear = 0; /* output year in dates */ static int dolong = 0; /* print also ip-addr */ -static void wtmp(), addarg(), hostconv(); -static int want(); -TTY *addtty(); -static char *ttyconv(); +static void wtmp(void); +static void addarg(int, char *); +static void hostconv(char *); +static void onintr(int); +static int want(struct utmp *, int); +TTY *addtty(char *); +static char *ttyconv(char *); int -main(argc, argv) - int argc; - char **argv; -{ +main(int argc, char **argv) { extern int optind; extern char *optarg; int ch; @@ -159,10 +159,8 @@ main(argc, argv) * print_partial_line -- * print the first part of each output line according to specified format */ -void -print_partial_line(bp) - struct utmp *bp; -{ +static void +print_partial_line(struct utmp *bp) { char *ct; ct = ctime(&bp->ut_time); @@ -193,12 +191,10 @@ print_partial_line(bp) * read through the wtmp file */ static void -wtmp() -{ +wtmp(void) { register struct utmp *bp; /* current structure */ register TTY *T; /* tty list entry */ long delta; /* time difference */ - void onintr(); char *crmsg = NULL; char *ct = NULL; struct utmp **utmplist = NULL; @@ -310,10 +306,7 @@ wtmp() * see if want this entry */ static int -want(bp, check) - register struct utmp *bp; - int check; -{ +want(struct utmp *bp, int check) { register ARG *step; if (check) { @@ -357,10 +350,7 @@ want(bp, check) * add an entry to a linked list of arguments */ static void -addarg(type, arg) - int type; - char *arg; -{ +addarg(int type, char *arg) { register ARG *cur; if (!(cur = (ARG *)malloc((unsigned int)sizeof(ARG)))) { @@ -378,9 +368,7 @@ addarg(type, arg) * add an entry to a linked list of ttys */ TTY * -addtty(ttyname) - char *ttyname; -{ +addtty(char *ttyname) { register TTY *cur; if (!(cur = (TTY *)malloc((unsigned int)sizeof(TTY)))) { @@ -400,9 +388,7 @@ addtty(ttyname) * off the domain suffix since that's what login(1) does. */ static void -hostconv(arg) - char *arg; -{ +hostconv(char *arg) { static int first = 1; static char *hostdot, name[MAXHOSTNAMELEN]; @@ -427,9 +413,7 @@ hostconv(arg) * convert tty to correct name. */ static char * -ttyconv(arg) - char *arg; -{ +ttyconv(char *arg) { char *mval; /* @@ -459,10 +443,8 @@ ttyconv(arg) * onintr -- * on interrupt, we inform the user how far we've gotten */ -void -onintr(signo) - int signo; -{ +static void +onintr(int signo) { char *ct; ct = ctime(&utmpbuf.ut_time); diff --git a/login-utils/login.c b/login-utils/login.c index eaaf1a520..3ad3b219c 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -116,7 +116,9 @@ #include #include #include +#include "pathnames.h" #include "my_crypt.h" +#include "login.h" #include "nls.h" #ifdef __linux__ @@ -188,25 +190,22 @@ struct lastlog }; #endif -#include "pathnames.h" -#define P_(s) () -void opentty P_((const char *tty)); -void getloginname P_((void)); -void timedout P_((void)); -int rootterm P_((char *ttyn)); -void motd P_((void)); -void sigint P_((void)); -void checknologin P_((void)); -void dolastlog P_((int quiet)); -void badlogin P_((const char *name)); -char *stypeof P_((char *ttyid)); -void checktty P_((char *user, char *tty, struct passwd *pwd)); -void sleepexit P_((int eval)); +static void getloginname (void); +static void timedout (int); +static void sigint (int); +static int rootterm (char *ttyn); +static void motd (void); +static void checknologin (void); +static void dolastlog (int quiet); + +#ifndef __linux__ +static char *stypeof (char *ttyid); +#endif + #ifdef CRYPTOCARD -int cryptocard P_((void)); +#include "cryptocard.h" #endif -#undef P_ #ifdef KERBEROS #include @@ -235,14 +234,14 @@ int kerror = KSUCCESS, notickets = 1; #ifndef __linux__ int timeout = 300; #else -int timeout = 60; +int timeout = 60; /* used in cryptocard.c */ #endif -struct passwd *pwd; -int failures = 1; +struct passwd *pwd; /* used in cryptocard.c */ +struct hostent hostaddress; /* used in checktty.c */ char term[64], *hostname, *username, *tty; -struct hostent hostaddress; -char thishost[100]; +static char thishost[100]; +static int failures = 1; #ifndef __linux__ struct sgttyb sgttyb; @@ -266,7 +265,7 @@ const char *months[] = connection. I believe login should open the line in the non-blocking mode leaving the decision to make a connection to getty (where it actually belongs). */ -void +static void opentty(const char * tty) { int i; @@ -313,11 +312,7 @@ main(int argc, char **argv) int quietlog, passwd_req; char *domain, *ttyn; char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; - char *ctime(), *ttyname(), *stypeof(); - time_t time(); - void timedout(); char *termenv; - char vcsn[20], vcsan[20]; char * childArgv[10]; char * buff; int childArgc = 0; @@ -329,6 +324,9 @@ main(int argc, char **argv) #else char *salt, *pp; #endif +#ifdef CHOWNVCS + char vcsn[20], vcsan[20]; +#endif #ifndef __linux__ int ioctlval; #endif @@ -446,6 +444,7 @@ main(int argc, char **argv) ttyn = tname; } +#ifdef CHOWNVCS /* find names of Virtual Console devices, for later mode change */ { char *p = ttyn; @@ -455,6 +454,7 @@ main(int argc, char **argv) strcpy(vcsn, "/dev/vcs"); strcat(vcsn, p); strcpy(vcsan, "/dev/vcsa"); strcat(vcsan, p); } +#endif setpgrp(); @@ -464,8 +464,8 @@ main(int argc, char **argv) tcgetattr(0, &tt); ttt = tt; ttt.c_cflag &= ~HUPCL; - - if((chown(ttyn, 0, 0) == 0) && (chmod(ttyn, 0622) == 0)) { + + if((chown(ttyn, 0, 0) == 0) && (chmod(ttyn, TTY_MODE) == 0)) { tcsetattr(0,TCSAFLUSH,&ttt); signal(SIGHUP, SIG_IGN); /* so vhangup() wont kill us */ vhangup(); @@ -816,8 +816,8 @@ main(int argc, char **argv) else if (tp.tv_sec - pwd->pw_change < TWOWEEKS && !quietlog) { struct tm *ttp; ttp = localtime(&pwd->pw_change); - printf(_("Warning: your password expires on %s %d, %d\n"), - months[ttp->tm_mon], ttp->tm_mday, + printf(_("Warning: your password expires on %d %s %d.\n"), + ttp->tm_mday, months[ttp->tm_mon], TM_YEAR_BASE + ttp->tm_year); } } @@ -830,8 +830,8 @@ main(int argc, char **argv) else if (tp.tv_sec - pwd->pw_expire < TWOWEEKS && !quietlog) { struct tm *ttp; ttp = localtime(&pwd->pw_expire); - printf(_("Warning: your account expires on %s %d, %d\n"), - months[ttp->tm_mon], ttp->tm_mday, + printf(_("Warning: your account expires on %d %s %d.\n"), + ttp->tm_mday, months[ttp->tm_mon], TM_YEAR_BASE + ttp->tm_year); } } @@ -970,6 +970,7 @@ Michael Riepe (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); chmod(ttyn, TTY_MODE); +#ifdef CHOWNVCS /* if tty is one of the VC's then change owner and mode of the special /dev/vcs devices as well */ if (consoletty(0)) { @@ -978,6 +979,7 @@ Michael Riepe chmod(vcsn, TTY_MODE); chmod(vcsan, TTY_MODE); } +#endif setgid(pwd->pw_gid); @@ -1184,12 +1186,10 @@ Michael Riepe } void -getloginname() -{ - register int ch; - register char *p; +getloginname(void) { + int ch, cnt, cnt2; + char *p; static char nbuf[UT_NAMESIZE + 1]; - int cnt, cnt2; cnt2 = 0; for (;;) { @@ -1231,8 +1231,7 @@ getloginname() } void -timedout() -{ +timedout(int sig) { struct termio ti; fprintf(stderr, _("Login timed out after %d seconds\n"), timeout); @@ -1245,8 +1244,7 @@ timedout() } int -rootterm(ttyn) - char *ttyn; +rootterm(char * ttyn) #ifndef __linux__ { struct ttyent *t; @@ -1286,10 +1284,9 @@ rootterm(ttyn) jmp_buf motdinterrupt; void -motd() -{ - register int fd, nchars; - void (*oldint)(), sigint(); +motd(void) { + int fd, nchars; + void (*oldint)(int); char tbuf[8192]; if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) @@ -1303,15 +1300,13 @@ motd() } void -sigint() -{ +sigint(int sig) { longjmp(motdinterrupt, 1); } #ifndef USE_PAM /* PAM takes care of this */ void -checknologin() -{ +checknologin(void) { register int fd, nchars; char tbuf[8192]; @@ -1324,9 +1319,7 @@ checknologin() #endif void -dolastlog(quiet) - int quiet; -{ +dolastlog(int quiet) { struct lastlog ll; int fd; @@ -1385,9 +1378,7 @@ badlogin(const char *name) #ifndef __linux__ char * -stypeof(ttyid) - char *ttyid; -{ +stypeof(char *ttyid) { struct ttyent *t; return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); @@ -1396,9 +1387,7 @@ stypeof(ttyid) /* should not be called from PAM code... Why? */ void -sleepexit(eval) - int eval; -{ +sleepexit(int eval) { sleep(SLEEP_EXIT_TIMEOUT); exit(eval); } diff --git a/login-utils/login.h b/login-utils/login.h new file mode 100644 index 000000000..14b698e32 --- /dev/null +++ b/login-utils/login.h @@ -0,0 +1,8 @@ +/* defined in login.c */ +extern void badlogin(const char *s); +extern void sleepexit(int); +extern struct hostent hostaddress; +extern char *hostname; + +/* defined in checktty.c */ +extern void checktty(const char *user, const char *tty, struct passwd *pwd); diff --git a/login-utils/need.8 b/login-utils/need.8 deleted file mode 100644 index cc3712d74..000000000 --- a/login-utils/need.8 +++ /dev/null @@ -1,85 +0,0 @@ -.\" Copyright (C) 2000 Richard Gooch -.\" -.\" This program is free software; you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation; either version 2 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program; if not, write to the Free Software -.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -.\" -.\" Richard Gooch may be reached by email at rgooch@atnf.csiro.au -.\" The postal address is: -.\" Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. -.\" -.\" need.8 Richard Gooch 28-FEB-2000 -.\" -.TH NEED 8 "28 Feb 2000" "Util-Linux Package" -.SH NAME -need \- utility to tell simpleinit(8) to start a service -.SH SYNOPSIS -.nf -\fBneed\fP [\fB-r\fP] [\fBservice\fP] -.BR display-services -.fi -.SH DESCRIPTION -The \fBneed\fP programme is a utility that tells \fBsimpleinit\fP(8) -to start a \fIservice\fP (usually a script in \fI/sbin/init.d\fP) and -will wait for the service to become available. If the service is -already available, it will not be started again. - -When invoked as \fBdisplay-services\fP it will write the list of -currently available services and the list of failed services to the -standard output. - -The \fB-r\fP option is used to tell \fBsimpleinit\fP(8) to "roll back" -(stop) services up to (but not including) \fIservice\fP. If -\fIservice\fP is not specified, all services are stopped. The \fB-r\fP -option thus allows the system to be partially or wholly shut down in -an orderly fashion. The \fBshutdown\fP(8) programme still needs to be -run. - -The \fBneed\fP programme is designed to help improve the robustness, -scalability and readability of system boot scripts. It is now possible -to write a modularised set of boot scripts without the complex and -fragile numbered symlink scheme used in SysV-style boot scripts. Each -script can simply declare, using \fBneed\fP(8), what must run before -them. -.SH EXIT CODE -The exit code from \fBneed\fP is 0 if the service was successfully -started, 1 if the service failed badly, and 2 if the service is -unavailable (i.e. disabled in configuration files). These exit codes -reflect the exit codes from the service startup scripts. - -The exit code from \fBneed -r\fP is 0 if the service was successfully -stopped, 1 if the service could not be stopped, and 2 if the service -was not available to start with. The service shutdown scripts may only -return 0 (for success) or 1 (for failure). -.SH SIGNALS -\fBneed\fP(8) uses \fBSIGUSR1\fP, \fBSIGUSR2\fP and \fBSIGPOLL\fP for -communication with \fBsimpleinit\fP(8). Don't send these signals to -it. -.SH FILES -.PD 0 -.TP 20 -.BI /dev/initctl -This is the control FIFO, created by \fBsimpleinit\fP(8), which -\fBneed\fP(8) writes commands to. -.SH SEE ALSO -.BR simpleinit (8), -.BR init (8) -.PP -A more complete discussion of the new boot script system, based on -\fBneed\fP(8), is available from: -http://www.atnf.csiro.au/~rgooch/linux/boot-scripts/ -.SH AUTHOR -Richard Gooch (rgooch@atnf.csiro.au) -.SH AVAILABILITY -The Util-Linux package is available from: -ftp://ftp.??.kernel.org/pub/linux/utils/util-linux/ diff --git a/login-utils/need.c b/login-utils/need.c deleted file mode 100644 index 97690c461..000000000 --- a/login-utils/need.c +++ /dev/null @@ -1,160 +0,0 @@ -/* need.c - - Source file for need (init(8) dependency tool). - - Copyright (C) 2000 Richard Gooch - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Richard Gooch may be reached by email at rgooch@atnf.csiro.au - The postal address is: - Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. -*/ - -/* - This tool will request init(8) to start a service and will wait for that - service to be available. If the service is already available, init(8) will - not start it again. - This tool may also be used to inspect the list of currently available - services. - - - Written by Richard Gooch 28-FEB-2000 - - Last updated by Richard Gooch 28-FEB-2000 - - -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include "simpleinit.h" - - -static void signal_handler (int sig); - - -static int caught_signal = 0; - - -int main (int argc, char **argv) -{ - int fd, nbytes; - struct sigaction sa; - sigset_t ss; - char *ptr; - long buffer[COMMAND_SIZE / sizeof (long)]; - struct command_struct *command = (struct command_struct *) buffer; - - sigemptyset (&ss); - sigaddset (&ss, SIG_PRESENT); - sigaddset (&ss, SIG_NOT_PRESENT); - sigaddset (&ss, SIG_FAILED); - sigprocmask (SIG_BLOCK, &ss, NULL); - sigemptyset (&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = signal_handler; - sigaction (SIG_PRESENT, &sa, NULL); - sigaction (SIG_NOT_PRESENT, &sa, NULL); - sigaction (SIG_FAILED, &sa, NULL); - command->pid = getpid (); - if ( ( ptr = strrchr (argv[0], '/') ) == NULL ) ptr = argv[0]; - else ++ptr; - if (strcmp (ptr, "display-services") == 0) - { - command->command = COMMAND_DUMP_LIST; - if (tmpnam (command->name) == NULL) - { - fprintf (stderr, "Unable to create a unique filename\t%s\n", - ERRSTRING); - exit (1); - } - if (mkfifo (command->name, S_IRUSR) != 0) - { - fprintf (stderr, "Unable to create FIFO: \"%s\"\t%s\n", - command->name, ERRSTRING); - exit (1); - } - } - else - { - if ( (argc > 1) && (strcmp (argv[1], "-r") == 0) ) - { - command->command = COMMAND_ROLLBACK; - --argc; - ++argv; - } - else command->command = COMMAND_NEED; - if (argc == 2) strcpy (command->name, argv[1]); - else - { - if (command->command == COMMAND_ROLLBACK) command->name[0] = '\0'; - else - { - fprintf (stderr, "Usage:\tneed programme\n"); - exit (1); - } - } - } - if ( ( fd = open ("/dev/initctl", O_WRONLY, 0) ) < 0 ) - { - fprintf (stderr, "Error opening\t%s\n", ERRSTRING); - exit (1); - } - if (write (fd, buffer, COMMAND_SIZE) < COMMAND_SIZE) - { - fprintf (stderr, "Error writing\t%s\n", ERRSTRING); - exit (1); - } - close (fd); - if (command->command != COMMAND_DUMP_LIST) - { - sigemptyset (&ss); - while (caught_signal == 0) sigsuspend (&ss); - switch (caught_signal) - { - case SIG_PRESENT: - return 0; - case SIG_NOT_PRESENT: - return 2; - case SIG_FAILED: - return 1; - } - return 3; - } - /* Read back the data and display it */ - if ( ( fd = open (command->name, O_RDONLY, 0) ) < 0 ) - { - fprintf (stderr, "Error opening:\"%s\"\t%s\n", - command->name, ERRSTRING); - exit (1); - } - unlink (command->name); - fflush (stdout); - while ( ( nbytes = read (fd, buffer, COMMAND_SIZE) ) > 0 ) - write (1, buffer, nbytes); - close (fd); - return (0); -} /* End Function main */ - -static void signal_handler (int sig) -{ - caught_signal = sig; -} /* End Function signal_handler */ diff --git a/login-utils/newgrp.c b/login-utils/newgrp.c index 1f8be95f2..ade173e53 100644 --- a/login-utils/newgrp.c +++ b/login-utils/newgrp.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "pathnames.h" #include "my_crypt.h" diff --git a/login-utils/passwd.c b/login-utils/passwd.c index ba679cd23..6741ee210 100644 --- a/login-utils/passwd.c +++ b/login-utils/passwd.c @@ -64,7 +64,10 @@ #include #include #include +#include #include "my_crypt.h" +#include "setpwnam.h" +#include "islocal.h" #include "nls.h" #include "env.h" @@ -79,9 +82,6 @@ #include #endif /* LOGALL */ -extern int is_local(char *); /* islocal.c */ -extern int setpwnam(struct passwd *); /* setpwnam.c */ - #define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.') #define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') @@ -104,9 +104,8 @@ pexit(char *str, ...) * This would probably be the best place for checking against * dictionaries. :-) */ - -int check_passwd_string(char *passwd, char *string) -{ +static int +check_passwd_string(char *passwd, char *string) { int r; char *p, *q; @@ -152,8 +151,8 @@ int check_passwd_string(char *passwd, char *string) return 1; } -int check_passwd(char *passwd, char *oldpasswd, char *user, char *gecos) -{ +static int +check_passwd(char *passwd, char *oldpasswd, char *user, char *gecos) { int ucase, lcase, digit, other; char *c, *g, *p; @@ -216,17 +215,16 @@ int check_passwd(char *passwd, char *oldpasswd, char *user, char *gecos) return 1; /* fine */ } -void usage() -{ +#if 0 +static void +usage(void) { printf (_("Usage: passwd [username [password]]\n")); printf(_("Only root may use the one and two argument forms.\n")); } +#endif int -main(argc, argv) - int argc; - char *argv[]; -{ +main(int argc, char *argv[]) { struct passwd *pe; uid_t gotuid = getuid(); char *pwdstr = NULL, *cryptstr, *oldstr; diff --git a/login-utils/setpwnam.c b/login-utils/setpwnam.c index 8631e7adc..62d47a51c 100644 --- a/login-utils/setpwnam.c +++ b/login-utils/setpwnam.c @@ -64,6 +64,11 @@ #include "setpwnam.h" +#define false 0 +#define true 1 + +typedef int boolean; + static void pw_init(void); /* diff --git a/login-utils/setpwnam.h b/login-utils/setpwnam.h index b4790f7ab..84d1c208f 100644 --- a/login-utils/setpwnam.h +++ b/login-utils/setpwnam.h @@ -14,11 +14,6 @@ #include "pathnames.h" -#define false 0 -#define true 1 - -typedef int boolean; - #ifndef DEBUG #define PASSWD_FILE _PATH_PASSWD #define PTMP_FILE _PATH_PTMP @@ -36,3 +31,5 @@ typedef int boolean; #define GTMP_FILE "/tmp/gtmp" #define GTMPTMP_FILE "/tmp/gtmptmp" #endif + +extern int setpwnam (struct passwd *pwd); diff --git a/login-utils/shutdown.c b/login-utils/shutdown.c index e3ec93c1e..d1034d5eb 100644 --- a/login-utils/shutdown.c +++ b/login-utils/shutdown.c @@ -33,6 +33,19 @@ * * 2000-03-02 Richard Gooch * - pause forever if (pid == 1) and send SIGQUIT to pid = 1 + * + * 2000-11-04 Richard Gooch + * - continue reaping if (pid == 1) + * + * 2000-11-06 Richard Gooch + * - shut down "finalprog" from /etc/inittab + * - kill normal user (non-root and non-daemon) processes first with SIGTERM + * + * 2000-11-08 Richard Gooch + * - rollback services + * - do not unmount devfs (otherwise get harmless but annoying messages) + * - created syncwait() for faster shutting down + * - kill getty processes */ #include @@ -52,13 +65,22 @@ #include #include #include +#include +#include +#include +#include #include "linux_reboot.h" #include "pathnames.h" #include "nls.h" -static void usage(), int_handler(), write_user(struct utmp *); -static void wall(), write_wtmp(), unmount_disks(), unmount_disks_ourselves(); -static void swap_off(), do_halt(char *); +static void usage(void), int_handler(int), write_user(struct utmp *); +static void wall(void), write_wtmp(void), unmount_disks(void); +static void unmount_disks_ourselves(void); +static void swap_off(void), do_halt(char *); +static void kill_mortals (int sig); +static void stop_finalprog (void); +static void syncwait (int timeval); + char *prog; /* name of the program */ int opt_reboot; /* true if -r option or reboot command */ @@ -81,14 +103,14 @@ char halt_action[256]; /* to find out what to do upon halt */ void -usage() +usage(void) { fprintf(stderr, _("Usage: shutdown [-h|-r] [-fqs] [now|hh:ss|+mins]\n")); exit(1); } -void +static void my_puts(char *s) { /* Use a fresh stdout after forking */ @@ -98,7 +120,7 @@ my_puts(char *s) } void -int_handler() +int_handler(int sig) { unlink(_PATH_NOLOGIN); signal(SIGINT, SIG_DFL); @@ -106,7 +128,7 @@ int_handler() exit(1); } -int +static int iswhitespace(int a) { return (a == ' ' || a == '\t'); } @@ -120,14 +142,14 @@ main(int argc, char *argv[]) if (getpid () == 1) { for (i = 0; i < getdtablesize (); i++) close (i); - while (1) pause (); + while (1) wait (NULL); /* Grim reaper never stops */ } setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #ifndef DEBUGGING - if(geteuid()) { + if(setreuid (0, 0)) { fprintf(stderr, _("%s: Only root can shut a system down.\n"), argv[0]); exit(1); @@ -350,6 +372,15 @@ main(int argc, char *argv[]) #ifndef DEBUGGING /* a gentle kill of all other processes except init */ + kill_mortals (SIGTERM); + stop_finalprog (); + sleep (1); /* Time for saves to start */ + kill (1, SIGTERM); /* Tell init to kill spawned gettys */ + usleep (100000); /* Wait for gettys to die */ + my_puts (""); /* Get past the login prompt */ + system ("/sbin/initctl -r"); /* Roll back services */ + syncwait (1); + my_puts ("Sending SIGTERM to all remaining processes..."); kill(-1, SIGTERM); sleep(2); /* default 2, some people need 5 */ @@ -371,17 +402,16 @@ main(int argc, char *argv[]) required. Need to sleep before remounting root read-only */ kill (1, SIGQUIT); - sync(); - sleep(2); + sleep (1); /* Time for processes to die and close files */ + syncwait (2); /* remove swap files and partitions using swapoff */ swap_off(); /* unmount disks... */ unmount_disks(); - sync(); - sleep(1); - + syncwait (1); + if(opt_reboot) { my_reboot(LINUX_REBOOT_CMD_RESTART); /* RB_AUTOBOOT */ my_puts(_("\nWhy am I still alive after reboot?")); @@ -390,6 +420,7 @@ main(int argc, char *argv[]) /* allow C-A-D now, faith@cs.unc.edu, re-fixed 8-Jul-96 */ my_reboot(LINUX_REBOOT_CMD_CAD_ON); /* RB_ENABLE_CAD */ + sleep (1); /* Wait for devices to finish writing to media */ do_halt(halt_action); } /* NOTREACHED */ @@ -432,6 +463,9 @@ write_user(struct utmp *ut) char msg[100]; minutes = timeout / 60; + hours = minutes / 60; + minutes %= 60; + (void) strncat(term, ut->ut_line, sizeof(ut->ut_line)); /* try not to get stuck on a mangled ut_line entry... */ @@ -443,16 +477,20 @@ write_user(struct utmp *ut) WR(msg); WRCRLF; - if(minutes == 0) { - sprintf(msg, _("System going down IMMEDIATELY!\n")); - } else if(minutes > 60) { - hours = minutes / 60; - sprintf(msg, _("System going down in %d hour%s %d minutes"), - hours, hours == 1 ? "" : _("s"), minutes - 60*hours); - } else { - sprintf(msg, _("System going down in %d minute%s\n"), - minutes, minutes == 1 ? "" : _("s")); - } + if (hours > 1) + sprintf(msg, _("System going down in %d hours %d minutes"), + hours, minutes); + else if (hours == 1) + sprintf(msg, _("System going down in 1 hour %d minutes"), + minutes); + else if (minutes > 1) + sprintf(msg, _("System going down in %d minutes\n"), + minutes); + else if (minutes == 1) + sprintf(msg, _("System going down in 1 minute\n")); + else + sprintf(msg, _("System going down IMMEDIATELY!\n")); + WR(msg); WRCRLF; @@ -464,7 +502,7 @@ write_user(struct utmp *ut) } void -wall() +wall(void) { /* write to all users, that the system is going down. */ struct utmp *ut; @@ -480,7 +518,7 @@ wall() } void -write_wtmp() +write_wtmp(void) { /* write in wtmp that we are dying */ int fd; @@ -500,7 +538,7 @@ write_wtmp() } void -swap_off() +swap_off(void) { /* swapoff esp. swap FILES so the underlying partition can be unmounted. It you don't have swapoff(1) or use mount to @@ -530,7 +568,7 @@ swap_off() } void -unmount_disks() +unmount_disks(void) { /* better to use umount directly because it may be smarter than us */ @@ -563,7 +601,7 @@ unmount_disks() } void -unmount_disks_ourselves() +unmount_disks_ourselves(void) { /* unmount all disks */ @@ -581,8 +619,8 @@ unmount_disks_ourselves() } n = 0; while (n < 100 && (mnt = getmntent(mtab))) { - mntlist[n++] = strdup(mnt->mnt_fsname[0] == '/' ? - mnt->mnt_fsname : mnt->mnt_dir); + if (strcmp (mnt->mnt_type, "devfs") == 0) continue; + mntlist[n++] = strdup(mnt->mnt_dir); } endmntent(mtab); @@ -594,7 +632,96 @@ unmount_disks_ourselves() printf("umount %s\n", filesys); #else if (umount(mntlist[i]) < 0) - printf(_("shutdown: Couldn't umount %s\n"), filesys); + printf(_("shutdown: Couldn't umount %s: %s\n"), + filesys, ERRSTRING); #endif } } + +static void kill_mortals (int sig) +{ + int npids = 0; + int index = 0; + int pid; + struct stat statbuf; + DIR *dp; + struct dirent *de; + pid_t *pids = NULL; + char path[256]; + + if ( ( dp = opendir ("/proc") ) == NULL ) return; + while ( ( de = readdir (dp) ) != NULL ) + { + if ( !isdigit (de->d_name[0]) ) continue; + pid = atoi (de->d_name); + sprintf (path, "/proc/%d", pid); + if (stat (path, &statbuf) != 0) continue; + if (statbuf.st_uid < 100) continue; + if (index <= npids) + { + pids = realloc (pids, npids + 16384); + if (pids == NULL) return; + npids += 16384; + } + pids[index++] = pid; + } + fputs ("Sending SIGTERM to mortals...", stderr); + for (--index; index >= 0; --index) kill (pids[index], sig); + free (pids); + closedir (dp); +} /* End Function kill_mortals */ + +static void stop_finalprog (void) +{ + char *p1, *p2; + FILE *fp; + char line[256]; + + if ( ( fp = fopen (_PATH_INITTAB, "r") ) == NULL ) return; + while (fgets (line, 256, fp) != NULL) + { + pid_t pid; + + line[strlen (line) - 1] = '\0'; + p1 = line; + while ( isspace (*p1) ) ++p1; + if (strncmp (p1, "finalprog", 9) != 0) continue; + if ( ( p1 = strchr (p1 + 9, '=') ) == NULL ) continue; + for (++p1; isspace (*p1); ++p1); + if (*p1 == '\0') continue; + for (p2 = p1; !isspace (*p2); ++p2); + *p2 = '\0'; + switch ( pid = fork () ) + { + case 0: /* Child */ + execl (p1, p1, "stop", NULL); + break; + case -1: /* Error */ + break; + default: /* Parent */ + waitpid (pid, NULL, 0); + break; + } + fclose (fp); + return; + } + fclose (fp); +} /* End Function stop_finalprog */ + +static void syncwait (int timeval) +{ + static int do_wait = 0; + static int first_time = 1; + + sync (); + /* Kernel version 1.3.20 and after are supposed to wait automatically */ + if (first_time) + { + struct utsname uts; + + first_time = 0; + uname (&uts); + if (uts.release[0] < '2') do_wait = 1; + } + if (do_wait) sleep (timeval); +} /* End Function syncwait */ diff --git a/login-utils/simpleinit.8 b/login-utils/simpleinit.8 index 2a2f666ed..f367f2f63 100644 --- a/login-utils/simpleinit.8 +++ b/login-utils/simpleinit.8 @@ -1,7 +1,7 @@ .\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) .\" May be distributed under the GNU General Public License .\" " for emacs's hilit19 mode :-) -.TH SIMPLEINIT 8 "20 November 1993" "Linux 0.99" "Linux Programmer's Manual" +.TH SIMPLEINIT 8 "4 November 2000" "Linux 0.99" "Linux Programmer's Manual" .SH NAME simpleinit \- process control initialization .SH SYNOPSIS @@ -33,7 +33,9 @@ After single user mode is terminated, the .I /etc/rc file is executed, and the information in .I /etc/inittab -will be used to start processes. +will be used to start processes. Alternatively, the \fI/etc/inittab\fP +file may be configured to run a different boot script. See below for +details. .SH "THE INITTAB FILE" Because of the number of init programs which are appearing in the Linux @@ -52,16 +54,21 @@ The format is .B PATH=search path +.B INIT_PATH=search path + .B "ttyline:termcap-entry:getty-command" + +.B finalprog=path .RE An example is as follows: .nf .RS -bootprog = rc -fileprefix = /sbin/ -PATH = /sbin:/bin +bootprog = +fileprefix = /sbin/init.d/ +PATH = /usr/sbin:/usr/bin:/sbin:/bin +INIT_PATH = /sbin/init.d tty1:linux:/sbin/getty 9600 tty1 tty2:linux:/sbin/getty 9600 tty2 @@ -70,6 +77,8 @@ tty4:linux:/sbin/getty 9600 tty4 # tty5:linux:/sbin/getty 9600 tty5 # ttyS1:dumb:/sbin/getty 9600 ttyS1 # ttyS2:dumb:/sbin/getty -m -t60 2400 ttyS2 + +finalprog = /sbin/rc.xdm .RE .fi @@ -79,6 +88,26 @@ character are treated as comments. Please see documentation for the .B getty (8) command that you are using, since there are several of these in the Linux community at this time. + +The \fBbootprog\fP value is appended to the \fBfileprefix\fP value, +and the result specifies the boot programme (script) to run. If +unspecified, the default is \fI/etc/rc\fP. If the boot programme is a +directory, then all scripts in that directory tree are executed, in +parallel. See the \fBneed\fP(8) programme for details on how to +elegantly control order of execution and manage dependencies. + +The \fBPATH\fP value is assigned to the PATH environment variable of +child processes (boot scripts). The \fBINIT_PATH\fP value is used by +simpleinit(8) itself to find the location of scripts to run (if an +absolute path is not given). If unset the default value \fBPATH\fP is +used. This separation allows boot scripts to invoke programmes of the +same name without conflict and without needing to specify absolute +paths. + +The \fBfinalprog\fP value specifies the path of the programme to run +after all \fBgetty\fP(8) instances are spawned. At bootup, it is +passed a single argument: "start". At shutdown, it is called again, +this time with the argument: "stop". .SH SIGNALS \fBsimpleinit\fP(8) responds to signals in a variety of ways: .TP @@ -121,7 +150,8 @@ remount (read-only) the root filesystem, even if the old inode for the .BR termcap (5), .BR getty (8), .BR agetty (8), -.BR shutdown (8) +.BR shutdown (8), +.BR need (8) .SH BUGS This program is called .B simpleinit @@ -135,4 +165,7 @@ for correct functionality. Peter Orbaek (poe@daimi.aau.dk) .br Version 1.20, with patches for singleuser mode by Werner Almesberger - +.br +Richard Gooch +.br +Dependency support diff --git a/login-utils/simpleinit.c b/login-utils/simpleinit.c index 1baf50cd7..9c4b63a5f 100644 --- a/login-utils/simpleinit.c +++ b/login-utils/simpleinit.c @@ -64,8 +64,10 @@ struct initline { struct initline inittab[NUMCMD]; int numcmd; int stopped = 0; /* are we stopped */ -static char boot_script[PATH_SIZE] = _PATH_RC; +static char boot_prog[PATH_SIZE] = _PATH_RC; static char script_prefix[PATH_SIZE] = "\0"; +static char final_prog[PATH_SIZE] = "\0"; +static char init_path[PATH_SIZE] = "\0"; static int caught_sigint = 0; static const char *initctl_name = "/dev/initctl"; static int initctl_fd = -1; @@ -73,23 +75,27 @@ static volatile int do_longjmp = 0; static sigjmp_buf jmp_env; -static void do_single (); +static void do_single (void); static int do_rc_tty (const char *path); static int process_path ( const char *path, int (*func) (const char *path) ); static int preload_file (const char *path); static int run_file (const char *path); -void spawn(), hup_handler(), read_inittab(); -void tstp_handler (); -void int_handler (); +static void spawn (int i), read_inittab (void); +static void hup_handler (int sig); +static void sigtstp_handler (int sig); +static void int_handler (int sig); static void sigchild_handler (int sig); static void sigquit_handler (int sig); -void set_tz(), write_wtmp(); -static pid_t mywaitpid (pid_t pid, int *status, int *rc_status); -static int run_command (const char *path, const char *name, pid_t pid); -static void forget_those_not_present (); +static void sigterm_handler (int sig); +#ifdef SET_TZ +static void set_tz (void); +#endif +static void write_wtmp (void); +static pid_t mywaitpid (pid_t pid, int *status); +static int run_command (const char *file, const char *name, pid_t pid); -void err(char *s) +static void err (char *s) { int fd; @@ -100,8 +106,7 @@ void err(char *s) close(fd); } -void -enter_single() +static void enter_single (void) { pid_t pid; int i; @@ -130,10 +135,13 @@ int main(int argc, char *argv[]) #ifdef SET_TZ set_tz(); #endif + signal (SIGINT, int_handler); sigemptyset (&sa.sa_mask); sa.sa_flags = 0; - signal (SIGTSTP, tstp_handler); - signal (SIGINT, int_handler); + sa.sa_handler = sigtstp_handler; + sigaction (SIGTSTP, &sa, NULL); + sa.sa_handler = sigterm_handler; + sigaction (SIGTERM, &sa, NULL); sa.sa_handler = sigchild_handler; sigaction (SIGCHLD, &sa, NULL); sa.sa_handler = sigquit_handler; @@ -156,7 +164,7 @@ int main(int argc, char *argv[]) strcpy (path, script_prefix); strcat (path, argv[i]); if (access (path, R_OK | X_OK) == 0) - strcpy (boot_script, path); + strcpy (boot_prog, path); } } @@ -172,7 +180,7 @@ int main(int argc, char *argv[]) while(stopped) pause(); - if ( do_rc_tty (boot_script) ) do_single (); + if ( do_rc_tty (boot_prog) ) do_single (); while(stopped) /*Also if /etc/rc fails & we get SIGTSTP*/ pause(); @@ -195,10 +203,26 @@ int main(int argc, char *argv[]) for(i = 0; i < numcmd; i++) spawn(i); - + + if (final_prog[0] != '\0') { + switch ( fork () ) + { + case 0: /* Child */ + execl (final_prog, final_prog, "start", NULL); + err ( _("error running finalprog\n") ); + _exit (1); + break; + case -1: /* Error */ + err ( _("error forking finalprog\n") ); + break; + default: /* Parent */ + break; + } + } + for ever { - pid = mywaitpid (-1, &vec, NULL); - if (pid == 0) continue; + pid = mywaitpid (-1, &vec); + if (pid < 1) continue; /* clear utmp entry, and append to wtmp if possible */ { @@ -249,7 +273,7 @@ int main(int argc, char *argv[]) * return true if singleuser mode is allowed. * If /etc/securesingle exists ask for root password, otherwise always OK. */ -static int check_single_ok () +static int check_single_ok (void) { char *pass, *rootpass = NULL; struct passwd *pwd; @@ -273,7 +297,7 @@ static int check_single_ok () return 0; } -static void do_single () +static void do_single (void) { char path[PATH_SIZE]; @@ -293,15 +317,15 @@ static void do_single () */ static int do_rc_tty (const char *path) { - int status, rc_status = 0; - pid_t pid; + int status; + pid_t pid, child; sigset_t ss; if (caught_sigint) return 0; process_path (path, preload_file); /* Launch off a subprocess to start a new session (required for frobbing the TTY) and capture control-C */ - switch ( pid = fork () ) + switch ( child = fork () ) { case 0: /* Child */ for (status = 1; status < NSIG; status++) signal (status, SIG_DFL); @@ -312,7 +336,7 @@ static int do_rc_tty (const char *path) setsid (); ioctl (0, TIOCSCTTY, 0); /* I want my control-C */ sigsuspend (&ss); /* Should never return, should just be killed */ - break; /* No-one is controlled by this TTY now */ + break; /* No-one else is controlled by this TTY now */ case -1: /* Error */ return (1); /*break;*/ @@ -321,13 +345,15 @@ static int do_rc_tty (const char *path) } /* Parent */ process_path (path, run_file); - while (rc_status == 0) - if (mywaitpid (-1, &status, &rc_status) == pid) + while (1) + { + if ( ( pid = mywaitpid (-1, &status) ) == child ) return (WTERMSIG (status) == SIGINT) ? 0 : 1; - forget_those_not_present (); - kill (pid, SIGKILL); - while (waitpid (pid, NULL, 0) != pid) /* Nothing */; - return (rc_status < 0) ? 1 : 0; + if (pid < 0) break; + } + kill (child, SIGKILL); + while (waitpid (child, NULL, 0) != child) /* Nothing */; + return 0; } /* End Function do_rc_tty */ static int process_path ( const char *path, int (*func) (const char *path) ) @@ -368,7 +394,7 @@ static int preload_file (const char *path) char ch; if ( ( fd = open (path, O_RDONLY, 0) ) < 0) return 0; - while (read (fd, &ch, 1) == 1) lseek (fd, 1023, SEEK_CUR); + while (read (fd, &ch, 1) == 1) lseek (fd, 1024, SEEK_CUR); close (fd); return 0; } /* End Function preload_file */ @@ -380,9 +406,9 @@ static int run_file (const char *path) if ( ( ptr = strrchr ( (char *) path, '/' ) ) == NULL ) ptr = path; else ++ptr; return (run_command (path, ptr, 0) == SIG_FAILED) ? 1 : 0; -} /* End Function preload_file */ +} /* End Function run_file */ -void spawn(int i) +static void spawn (int i) { pid_t pid; int j; @@ -419,6 +445,7 @@ void spawn(int i) /* this is the parent */ inittab[i].pid = pid; inittab[i].last_start = ct; + sched_yield (); return; } else { /* this is the child */ @@ -448,7 +475,7 @@ void spawn(int i) } } -void read_inittab() +static void read_inittab (void) { FILE *f; char buf[CMDSIZ]; @@ -460,7 +487,7 @@ void read_inittab() char tty[50]; struct stat stb; #endif - char *termenv, *getenv(); + char *termenv; termenv = getenv("TERM"); /* set by kernel */ /* termenv = "vt100"; */ @@ -502,6 +529,16 @@ void read_inittab() setenv ("PATH", ptr, 1); continue; } + if ( !strncmp (buf, "INIT_PATH", 9) ) { + while ( isspace (*ptr) ) ++ptr; + strcpy (init_path, ptr); + continue; + } + if ( !strncmp (buf, "finalprog", 8) ) { + while ( isspace (*ptr) ) ++ptr; + strcpy (final_prog, ptr); + continue; + } } @@ -549,11 +586,11 @@ void read_inittab() len = strlen (path); if (path[len - 1] == '/') path[len - 1] = '\0'; if (access (path, R_OK | X_OK) == 0) - strcpy (boot_script, path); + strcpy (boot_prog, path); } } -void hup_handler() +static void hup_handler (int sig) { int i,j; int oldnum; @@ -564,7 +601,7 @@ void hup_handler() memcpy(savetab, inittab, NUMCMD * sizeof(struct initline)); oldnum = numcmd; - read_inittab(); + read_inittab (); for(i = 0; i < numcmd; i++) { had_already = 0; @@ -581,15 +618,21 @@ void hup_handler() (void) signal(SIGHUP, hup_handler); } -void tstp_handler() +static void sigtstp_handler (int sig) { - stopped = ~stopped; - if(!stopped) hup_handler(); + stopped = ~stopped; + if (!stopped) hup_handler (sig); +} /* End Function sigtstp_handler */ - signal(SIGTSTP, tstp_handler); -} +static void sigterm_handler (int sig) +{ + int i; + + for (i = 0; i < numcmd; i++) + if (inittab[i].pid > 0) kill (inittab[i].pid, SIGTERM); +} /* End Function sigterm_handler */ -void int_handler() +static void int_handler (int sig) { pid_t pid; @@ -617,7 +660,8 @@ static void sigquit_handler (int sig) execl (_PATH_REBOOT, _PATH_REBOOT, NULL); /* It knows pid=1 must sleep */ } -void set_tz() +#ifdef SET_TZ +static void set_tz (void) { FILE *f; int len; @@ -629,8 +673,9 @@ void set_tz() tzone[len-1] = 0; /* get rid of the '\n' */ setenv("TZ", tzone, 0); } +#endif -void write_wtmp() +static void write_wtmp (void) { int fd, lf; struct utmp ut; @@ -653,44 +698,66 @@ void write_wtmp() } -struct waiter_struct +struct needer_struct { - struct waiter_struct *next; + struct needer_struct *next; pid_t pid; }; +struct service_struct +{ + struct service_struct *prev, *next; /* Script services chain */ + struct needer_struct *needers; /* Needers waiting for service */ + struct script_struct *attempting_providers; + int failed; /* TRUE if attempting provider failed badly */ + char name[1]; +}; + struct script_struct { pid_t pid; - struct script_struct *prev, *next; - struct waiter_struct *first_waiter; - char name[1]; + struct script_struct *prev, *next; /* For the list */ + struct service_struct *first_service, *last_service; /*First is true name*/ + struct script_struct *next_attempting_provider; /* Provider chain */ }; struct list_head { struct script_struct *first, *last; + unsigned int num_entries; }; -static struct list_head available_list = {NULL, NULL}; -static struct list_head starting_list = {NULL, NULL}; -static struct list_head failed_list = {NULL, NULL}; -static struct list_head unavailable_list = {NULL, NULL}; +static struct list_head available_list = {NULL, NULL, 0}; +static struct list_head starting_list = {NULL, NULL, 0}; +static struct service_struct *unavailable_services = NULL; /* For needers */ +static int num_needers = 0; -static void process_pidstat (pid_t pid, int status, int *rc_status); -static struct script_struct *find_script (const char *name, - struct list_head *head); +static int process_pidstat (pid_t pid, int status); +static void process_command (const struct command_struct *command); +static struct service_struct *find_service_in_list (const char *name, + struct service_struct *sv); +static struct script_struct *find_script_byname + (const char *name,struct list_head *head, struct service_struct **service); +static struct script_struct *find_script_bypid (pid_t pid, + struct list_head *head); static void insert_entry (struct list_head *head, struct script_struct *entry); static void remove_entry (struct list_head *head, struct script_struct *entry); -static void signal_waiters (struct script_struct *script, int sig); - - -static pid_t mywaitpid (pid_t pid, int *status, int *rc_status) +static void signal_needers (struct service_struct *service, int sig); +static void handle_nonworking (struct script_struct *script); +static int force_progress (void); +static void show_scripts (FILE *fp, const struct script_struct *script, + const char *type); +static const char *get_path (const char *file); + + +static pid_t mywaitpid (pid_t pid, int *status) +/* [RETURNS] The pid for a process to be reaped, 0 if no process is to be + reaped, and less than 0 if the boot scripts appear to have finished. +*/ { int ival; - struct script_struct *script; sigset_t ss_new, ss_old; long buffer[COMMAND_SIZE / sizeof (long)]; struct command_struct *command = (struct command_struct *) buffer; @@ -699,8 +766,7 @@ static pid_t mywaitpid (pid_t pid, int *status, int *rc_status) if (status == NULL) status = &ival; if ( ( pid = waitpid (pid, status, WNOHANG) ) > 0 ) { - process_pidstat (pid, *status, rc_status); - return pid; + return process_pidstat (pid, *status); } /* Some magic to avoid races */ command->command = -1; @@ -717,23 +783,76 @@ static pid_t mywaitpid (pid_t pid, int *status, int *rc_status) } if (command->command < 0) read (initctl_fd, buffer, COMMAND_SIZE); do_longjmp = 0; + process_command (command); + return 0; +} /* End Function mywaitpid */ + +static pid_t process_pidstat (pid_t pid, int status) +/* [RETURNS] The pid for a process to be reaped, 0 if no process is to be + reaped, and less than 0 if the boot scripts appear to have finished. +*/ +{ + int failed; + struct script_struct *script; + struct service_struct *service; + + if ( ( script = find_script_bypid (pid, &starting_list) ) == NULL ) + return pid; + remove_entry (&starting_list, script); + if ( WIFEXITED (status) && (WEXITSTATUS (status) == 0) ) + { + struct script_struct *provider; + + /* Notify needers and other providers */ + for (service = script->first_service; service != NULL; + service = service->next) + { + signal_needers (service, SIG_PRESENT); + for (provider = service->attempting_providers; provider != NULL; + provider = provider->next_attempting_provider) + kill (provider->pid, SIG_PRESENT); + service->attempting_providers = NULL; + } + insert_entry (&available_list, script); + return force_progress (); + } + failed = ( WIFEXITED (status) && (WEXITSTATUS (status) == 2) ) ? 0 : 1; + for (service = script->first_service; service != NULL; + service = service->next) + service->failed = failed; + handle_nonworking (script); + return force_progress (); +} /* End Function process_pidstat */ + +static void process_command (const struct command_struct *command) +{ + int ival; + struct script_struct *script; + struct service_struct *service; + switch (command->command) { case COMMAND_TEST: kill (command->pid, - (find_script (command->name, &available_list) == NULL) ? + (find_script_byname (command->name, &available_list, + NULL) == NULL) ? SIG_NOT_PRESENT : SIG_PRESENT); break; case COMMAND_NEED: ival = run_command (command->name, command->name, command->pid); - if (ival != 0) kill (command->pid, ival); + if (ival == 0) + { + ++num_needers; + force_progress (); + } + else kill (command->pid, ival); break; case COMMAND_ROLLBACK: if (command->name[0] == '\0') script = NULL; else { - if ( ( script = find_script (command->name, &available_list) ) - == NULL ) + if ( ( script = find_script_byname (command->name, &available_list, + NULL) ) == NULL ) { kill (command->pid, SIG_NOT_PRESENT); break; @@ -741,7 +860,9 @@ static pid_t mywaitpid (pid_t pid, int *status, int *rc_status) } while (script != available_list.first) { + pid_t pid; struct script_struct *victim = available_list.first; + char txt[256]; if ( ( pid = fork () ) == 0 ) /* Child */ { @@ -749,7 +870,8 @@ static pid_t mywaitpid (pid_t pid, int *status, int *rc_status) open ("/dev/console", O_RDONLY, 0); open ("/dev/console", O_RDWR, 0); dup2 (1, 2); - execlp (victim->name, victim->name, "stop", NULL); + execlp (get_path (victim->first_service->name), + victim->first_service->name, "stop", NULL); err ( _("error running programme\n") ); _exit (SIG_NOT_STOPPED); } @@ -759,8 +881,11 @@ static pid_t mywaitpid (pid_t pid, int *status, int *rc_status) while (waitpid (pid, &ival, 0) != pid) /* Nothing */; if ( WIFEXITED (ival) && (WEXITSTATUS (ival) == 0) ) { + sprintf (txt, "Stopped service: %s\n", + victim->first_service->name); remove_entry (&available_list, victim); free (victim); + err (txt); } else break; } @@ -769,119 +894,187 @@ static pid_t mywaitpid (pid_t pid, int *status, int *rc_status) (script ==available_list.first) ? SIG_STOPPED : SIG_NOT_STOPPED); break; case COMMAND_DUMP_LIST: - if (fork () == 0) + if (fork () == 0) /* Do it in a child process so pid=1 doesn't block */ { FILE *fp; if ( ( fp = fopen (command->name, "w") ) == NULL ) _exit (1); - fputs ("AVAILABLE SERVICES:\n", fp); - for (script = available_list.first; script != NULL; - script = script->next) fprintf (fp, "%s\n", script->name); - fputs ("FAILED SERVICES:\n", fp); - for (script = failed_list.first; script != NULL; - script = script->next) fprintf (fp, "%s\n", script->name); + show_scripts (fp, available_list.first, "AVAILABLE"); + show_scripts (fp, starting_list.first, "STARTING"); + fputs ("UNAVAILABLE SERVICES:\n", fp); + for (service = unavailable_services; service != NULL; + service = service->next) + fprintf (fp, "%s (%s)\n", service->name, + service->failed ? "FAILED" : "not configured"); fclose (fp); _exit (0); } break; + case COMMAND_PROVIDE: + /* Sanity check */ + if ( ( script = find_script_bypid (command->ppid, &starting_list) ) + == NULL ) + { + kill (command->pid, SIG_NOT_CHILD); + break; + } + if (find_script_byname (command->name, &available_list, NULL) != NULL) + { + kill (command->pid, SIG_PRESENT); + break; + } + if (find_script_byname (command->name, &starting_list, &service) + != NULL) + { /* Someone else is trying to provide */ + script->next_attempting_provider = service->attempting_providers; + service->attempting_providers = script; + break; + } + if ( ( service = find_service_in_list (command->name, + unavailable_services) ) + == NULL ) + { /* We're the first to try and provide: create it */ + if ( ( service = + calloc (1, strlen (command->name) + sizeof *service) ) + == NULL ) + { + kill (command->pid, SIG_NOT_CHILD); + break; + } + strcpy (service->name, command->name); + } + else + { /* Orphaned service: unhook and grab it */ + if (service->prev == NULL) unavailable_services = service->next; + else service->prev->next = service->next; + if (service->next != NULL) service->next->prev = service->prev; + service->next = NULL; + } + service->prev = script->last_service; + script->last_service->next = service; + script->last_service = service; + kill (command->pid, SIG_NOT_PRESENT); + break; case -1: default: break; } - return 0; -} /* End Function mywaitpid */ - -static void process_pidstat (pid_t pid, int status, int *rc_status) -{ - struct script_struct *script; - - if (initctl_fd < 0) return; - if (pid < 1) return; - for (script = starting_list.first; script != NULL; script = script->next) - if (script->pid == pid) break; - if (script == NULL) return; - remove_entry (&starting_list, script); - if ( WIFEXITED (status) && (WEXITSTATUS (status) == 0) ) - { - signal_waiters (script, SIG_PRESENT); - insert_entry (&available_list, script); - } - else if ( WIFEXITED (status) && (WEXITSTATUS (status) == 2) ) - { - signal_waiters (script, SIG_NOT_PRESENT); - insert_entry (&unavailable_list, script); - } - else - { - signal_waiters (script, SIG_FAILED); - insert_entry (&failed_list, script); - } - if ( (rc_status == NULL) || (starting_list.first != NULL) ) return; - *rc_status = (failed_list.first == NULL) ? 1 : -1; -} /* End Function process_pidstat */ +} /* End Function process_command */ -static int run_command (const char *path, const char *name, pid_t pid) +static int run_command (const char *file, const char *name, pid_t pid) { struct script_struct *script; - struct waiter_struct *waiter = NULL; + struct needer_struct *needer = NULL; + struct service_struct *service; - if (find_script (name, &available_list) != NULL) return SIG_PRESENT; - if (find_script (name, &failed_list) != NULL) return SIG_FAILED; - if (find_script (name, &unavailable_list) != NULL) return SIG_NOT_PRESENT; + if (find_script_byname (name, &available_list, NULL) != NULL) + return SIG_PRESENT; if (pid != 0) { - waiter = calloc (1, sizeof *waiter); - if (waiter == NULL) return SIG_FAILED; - waiter->pid = pid; + needer = calloc (1, sizeof *needer); + if (needer == NULL) return SIG_FAILED; + needer->pid = pid; } - script = find_script (name, &starting_list); + script = find_script_byname (name, &starting_list, &service); + if (script == NULL) + service = find_service_in_list (name, unavailable_services); if (script == NULL) { int i; + char txt[1024]; - script = calloc (1, strlen (name) + sizeof *script); - if (script == NULL) + if ( ( script = calloc (1, sizeof *script) ) == NULL ) { - if (waiter != NULL) free (waiter); + if (needer != NULL) free (needer); return SIG_FAILED; } - strcpy (script->name, name); + if (service == NULL) + { + service = calloc (1, strlen (name) + sizeof *service); + if (service == NULL) + { + free (script); + return SIG_FAILED; + } + strcpy (service->name, name); + } + else /* Unhook service from unavailable list */ + { + if (service->prev == NULL) unavailable_services = service->next; + else service->prev->next = service->next; + if (service->next != NULL) service->next->prev = service->prev; + service->prev = NULL; + service->next = NULL; + } switch ( script->pid = fork () ) { case 0: /* Child */ for (i = 1; i < NSIG; i++) signal (i, SIG_DFL); - execlp (path, script->name, "start", NULL); - err ( _("error running programme\n") ); + execlp (get_path (file), service->name, "start", NULL); + sprintf (txt, "error running programme: \"%s\"\n", service->name); + err ( _(txt) ); _exit (SIG_FAILED); break; case -1: /* Error */ + service->next = unavailable_services; + if (unavailable_services != NULL) + unavailable_services->prev = service; + unavailable_services = service; free (script); - if (waiter != NULL) free (waiter); + if (needer != NULL) free (needer); return SIG_FAILED; /*break;*/ default: /* Parent */ + script->first_service = service; + script->last_service = service; insert_entry (&starting_list, script); sched_yield (); break; } } - if (waiter == NULL) return 0; - waiter->next = script->first_waiter; - script->first_waiter = waiter; + if (needer == NULL) return 0; + needer->next = service->needers; + service->needers = needer; return 0; } /* End Function run_command */ -static struct script_struct *find_script (const char *name, - struct list_head *head) +static struct service_struct *find_service_in_list (const char *name, + struct service_struct *sv) +{ + for (; sv != NULL; sv = sv->next) + if (strcmp (sv->name, name) == 0) return (sv); + return NULL; +} /* End Function find_service_in_list */ + +static struct script_struct *find_script_byname (const char *name, + struct list_head *head, + struct service_struct **service) { - struct script_struct *entry; + struct script_struct *script; - for (entry = head->first; entry != NULL; entry = entry->next) + for (script = head->first; script != NULL; script = script->next) { - if (strcmp (entry->name, name) == 0) return (entry); + struct service_struct *sv; + + if ( ( sv = find_service_in_list (name, script->first_service) ) + != NULL ) + { + if (service != NULL) *service = sv; + return (script); + } } return NULL; -} /* End Function find_script */ +} /* End Function find_script_byname */ + +static struct script_struct *find_script_bypid (pid_t pid, + struct list_head *head) +{ + struct script_struct *script; + + for (script = head->first; script != NULL; script = script->next) + if (script->pid == pid) return (script); + return NULL; +} /* End Function find_script_bypid */ static void insert_entry (struct list_head *head, struct script_struct *entry) { @@ -891,6 +1084,7 @@ static void insert_entry (struct list_head *head, struct script_struct *entry) if (head->first != NULL) head->first->prev = entry; head->first = entry; if (head->last == NULL) head->last = entry; + ++head->num_entries; } /* End Function insert_entry */ static void remove_entry (struct list_head *head, struct script_struct *entry) @@ -899,37 +1093,96 @@ static void remove_entry (struct list_head *head, struct script_struct *entry) else entry->prev->next = entry->next; if (entry->next == NULL) head->last = entry->prev; else entry->next->prev = entry->prev; + --head->num_entries; } /* End Function remove_entry */ -static void signal_waiters (struct script_struct *script, int sig) +static void signal_needers (struct service_struct *service, int sig) { - struct waiter_struct *waiter, *next_waiter; + struct needer_struct *needer, *next_needer; - for (waiter = script->first_waiter; waiter != NULL; waiter = next_waiter) + for (needer = service->needers; needer != NULL; needer = next_needer) { - kill (waiter->pid, sig); - next_waiter = waiter->next; - free (waiter); + kill (needer->pid, sig); + next_needer = needer->next; + free (needer); + --num_needers; } - script->first_waiter = NULL; -} /* End Function signal_waiters */ + service->needers = NULL; +} /* End Function signal_needers */ -static void forget_those_not_present () +static void handle_nonworking (struct script_struct *script) { - struct script_struct *curr, *next; + struct service_struct *service, *next; - for (curr = failed_list.first; curr != NULL; curr = next) + for (service = script->first_service; service != NULL; service = next) { - next = curr->next; - free (curr); + struct script_struct *provider = service->attempting_providers; + + next = service->next; + if (provider == NULL) + { + service->next = unavailable_services; + if (unavailable_services != NULL) + unavailable_services->prev = service; + unavailable_services = service; + continue; + } + service->attempting_providers = provider->next_attempting_provider; + provider->last_service->next = service; + service->prev = provider->last_service; + provider->last_service = service; + service->next = NULL; + kill (provider->pid, SIG_NOT_PRESENT); } - failed_list.first = NULL; - failed_list.last = NULL; - for (curr = unavailable_list.first; curr != NULL; curr = next) + free (script); +} /* End Function handle_nonworking */ + +static int force_progress (void) +/* [RETURNS] 0 if boot scripts are still running, else -1. +*/ +{ + struct service_struct *service; + + if (starting_list.num_entries > num_needers) return 0; + /* No progress can be made: signal needers */ + for (service = unavailable_services; service != NULL; + service = service->next) + signal_needers (service, + service->failed ? SIG_FAILED : SIG_NOT_PRESENT); + return (starting_list.num_entries < 1) ? -1 : 0; +} /* End Function force_progress */ + +static void show_scripts (FILE *fp, const struct script_struct *script, + const char *type) +{ + fprintf (fp, "%s SERVICES:\n", type); + for (; script != NULL; script = script->next) + { + struct service_struct *service = script->first_service; + + fputs (service->name, fp); + for (service = service->next; service != NULL; service = service->next) + fprintf (fp, " (%s)", service->name); + putc ('\n', fp); + } +} /* End Function show_scripts */ + +static const char *get_path (const char *file) +{ + char *p1, *p2; + static char path[PATH_SIZE]; + + if (file[0] == '/') return file; + if (init_path[0] == '\0') return file; + for (p1 = init_path; *p1 != '\0'; p1 = p2) { - next = curr->next; - free (curr); + if ( ( p2 = strchr (p1, ':') ) == NULL ) + p2 = p1 + strlen (p1); + strncpy (path, p1, p2 - p1); + path[p2 - p1] = '/'; + strcat (path + (p2 - p1) + 1, file); + if (*p2 == ':') ++p2; + if (access (path, X_OK) == 0) return path; } - unavailable_list.first = NULL; - unavailable_list.last = NULL; -} /* End Function forget_those_not_present */ + return file; +} /* End Function get_path */ diff --git a/login-utils/simpleinit.h b/login-utils/simpleinit.h index ff26480f7..1d8762975 100644 --- a/login-utils/simpleinit.h +++ b/login-utils/simpleinit.h @@ -10,16 +10,19 @@ #define COMMAND_NEED 1 /* Wait, signal */ #define COMMAND_ROLLBACK 2 /* Wait, signal */ #define COMMAND_DUMP_LIST 3 /* No wait, no signal */ +#define COMMAND_PROVIDE 4 /* Wait, signal */ #define SIG_PRESENT SIGUSR1 /* Service is available */ #define SIG_STOPPED SIGUSR1 /* Service was stopped OK */ #define SIG_NOT_PRESENT SIGUSR2 /* Not present, but that's OK */ #define SIG_FAILED SIGPOLL /* Startup failed */ #define SIG_NOT_STOPPED SIGPOLL /* Failed to stop */ +#define SIG_NOT_CHILD SIGPOLL /* Not a child of init */ struct command_struct /* Must always be COMMAND_SIZE */ { signed int command; pid_t pid; + pid_t ppid; char name[1]; }; diff --git a/login-utils/ttymsg.c b/login-utils/ttymsg.c index 6bf2f82f6..b422abb85 100644 --- a/login-utils/ttymsg.c +++ b/login-utils/ttymsg.c @@ -53,9 +53,8 @@ #include #include "nls.h" -#ifdef __linux__ #include "pathnames.h" -#endif +#include "ttymsg.h" /* * Display the contents of a uio structure on a terminal. Used by wall(1), @@ -65,12 +64,7 @@ * ignored (exclusive-use, lack of permission, etc.). */ char * -ttymsg(iov, iovcnt, line, tmout) - struct iovec *iov; - int iovcnt; - char *line; - int tmout; -{ +ttymsg(struct iovec *iov, int iovcnt, char *line, int tmout) { static char device[MAXNAMLEN]; static char errbuf[MAXNAMLEN+1024]; register int cnt, fd, left, wret; diff --git a/login-utils/ttymsg.h b/login-utils/ttymsg.h new file mode 100644 index 000000000..5d2795197 --- /dev/null +++ b/login-utils/ttymsg.h @@ -0,0 +1,2 @@ +char *ttymsg(struct iovec *iov, int iovcnt, char *line, int tmout); + diff --git a/login-utils/vipw.c b/login-utils/vipw.c index dfcdca2ed..665d77daa 100644 --- a/login-utils/vipw.c +++ b/login-utils/vipw.c @@ -77,11 +77,9 @@ char tmptmp_file[FILENAMELEN]; /* very tmp file */ void pw_error __P((char *, int, int)); -void -copyfile(from, to) - register int from, to; -{ - register int nr, nw, off; +static void +copyfile(int from, int to) { + int nr, nw, off; char buf[8*1024]; while ((nr = read(from, buf, sizeof(buf))) > 0) @@ -94,9 +92,8 @@ copyfile(from, to) } -void -pw_init() -{ +static void +pw_init(void) { struct rlimit rlim; /* Unlimited resource limits. */ @@ -125,9 +122,8 @@ pw_init() (void)umask(0); } -int -pw_lock() -{ +static int +pw_lock(void) { int lockfd, fd, ret; /* @@ -179,9 +175,8 @@ pw_lock() return(1); } -void -pw_unlock() -{ +static void +pw_unlock(void) { char tmp[FILENAMELEN]; sprintf(tmp, "%s%s", orig_file, ".OLD"); @@ -198,9 +193,8 @@ pw_unlock() } -void -pw_edit(int notsetuid) -{ +static void +pw_edit(int notsetuid) { int pstat; pid_t pid; char *p, *editor; diff --git a/login-utils/wall.c b/login-utils/wall.c index d476edd64..6840015d4 100644 --- a/login-utils/wall.c +++ b/login-utils/wall.c @@ -55,8 +55,11 @@ #include #include #include + #include "nls.h" +#include "ttymsg.h" #include "pathnames.h" +#include "carefulputc.h" void makemsg __P((char *)); @@ -68,17 +71,13 @@ char *mbuf; char *progname = "wall"; -/* ARGSUSED */ int -main(argc, argv) - int argc; - char **argv; -{ +main(int argc, char **argv) { extern int optind; int ch; struct iovec iov; struct utmp *utmpptr; - char *p, *ttymsg(); + char *p; char line[sizeof(utmpptr->ut_line) + 1]; setlocale(LC_ALL, ""); @@ -139,7 +138,7 @@ makemsg(fname) struct tm *lt; struct passwd *pw; struct stat sbuf; - time_t now, time(); + time_t now; FILE *fp; int fd; char *p, *whom, *where, hostname[MAXHOSTNAMELEN], @@ -184,11 +183,26 @@ makemsg(fname) } (void)fprintf(fp, "%79s\r\n", " "); - if (fname && !(freopen(fname, "r", stdin))) { - (void)fprintf(stderr, _("%s: can't read %s.\n"), progname, fname); - exit(1); + if (fname) { + /* + * When we are not root, but suid or sgid, refuse to read files + * (e.g. device files) that the user may not have access to. + * After all, our invoker can easily do "wall < file" + * instead of "wall file". + */ + int uid = getuid(); + if (uid && (uid != geteuid() || getgid() != getegid())) { + fprintf(stderr, _("%s: will not read %s - use stdin.\n"), + progname, fname); + exit(1); + } + if (!freopen(fname, "r", stdin)) { + fprintf(stderr, _("%s: can't read %s.\n"), progname, fname); + exit(1); + } } - while (fgets(lbuf, sizeof(lbuf), stdin)) + + while (fgets(lbuf, sizeof(lbuf), stdin)) { for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) { if (cnt == 79 || ch == '\n') { for (; cnt < 79; ++cnt) @@ -197,15 +211,10 @@ makemsg(fname) putc('\n', fp); cnt = 0; } else { - /* Test for control chars added Fri Mar 10 - 19:49:30 1995, faith@cs.unc.edu */ - if (!isprint(ch) && !isspace(ch) && ch != '\007') { - putc('^', fp); - putc(ch^0x40,fp); /* DEL to ?, others to alpha */ - } else - putc(ch, fp); + carefulputc(ch, fp); } } + } (void)fprintf(fp, "%79s\r\n", " "); rewind(fp); diff --git a/misc-utils/Makefile b/misc-utils/Makefile index 088d2ccee..5b74dd39e 100644 --- a/misc-utils/Makefile +++ b/misc-utils/Makefile @@ -21,6 +21,8 @@ BIN= kill USRBIN= cal chkdupexe ddate logger look mcookie \ namei rename script whereis write +MAYBE= reset setterm tsort + ifeq "$(HAVE_RESET)" "no" USRBIN:=$(USRBIN) reset MAN1:=$(MAN1) reset.1 @@ -79,6 +81,8 @@ mcookie.o: mcookie.c md5.h md5.o: md5.c md5.h reset: reset.sh script: script.o +write.o: $(LIB)/carefulputc.h +write: write.o $(LIB)/carefulputc.o ifeq "$(HAVE_NCURSES)" "yes" setterm: setterm.o @@ -97,4 +101,4 @@ endif .PHONY: clean clean: - -rm -f *.o *~ core $(BIN) $(USRBIN) + -rm -f *.o *~ core $(BIN) $(USRBIN) $(MAYBE) diff --git a/misc-utils/cal.1 b/misc-utils/cal.1 index 6a5ec5ae5..9bade9d0b 100644 --- a/misc-utils/cal.1 +++ b/misc-utils/cal.1 @@ -42,7 +42,7 @@ .Nd displays a calendar .Sh SYNOPSIS .Nm cal -.Op Fl mjy +.Op Fl mjy13 .Op Ar month Op Ar year .Sh DESCRIPTION .Nm Cal @@ -51,6 +51,12 @@ If arguments are not specified, the current month is displayed. The options are as follows: .Bl -tag -width Ds +.It Fl 1 +Display single month output (use if cal was built with -3 as default to get +older traditional output) +.It Fl 3 +Display prev/current/next month output (use if cal was built with traditional +-1 as default to get newer improved output) .It Fl m Display Monday as the first day of the week. (The default is Sunday.) diff --git a/misc-utils/cal.c b/misc-utils/cal.c index bc0c1eff5..aba1b6f06 100644 --- a/misc-utils/cal.c +++ b/misc-utils/cal.c @@ -39,6 +39,12 @@ * 1999-02-22 Arkadiusz Mi¶kiewicz * - added Native Language Support * + * 2000-09-01 Michael Charles Pruznick + * Added "-3" option to print prev/next month with current. + * Added over-ridable default NUM_MONTHS and "-1" option to + * get traditional output when -3 is the default. I hope that + * enough people will like -3 as the default that one day the + * product can be shipped that way. */ #include @@ -60,6 +66,15 @@ # include /* libc4 only */ #endif +/* allow compile-time define to over-ride default */ +#ifndef NUM_MONTHS +#define NUM_MONTHS 1 +#endif + +#if ( NUM_MONTHS != 1 && NUM_MONTHS !=3 ) +#error NUM_MONTHS must be 1 or 3 +#endif + #define THURSDAY 4 /* for reformation */ #define SATURDAY 6 /* 1 Jan 1 was a Saturday */ @@ -102,7 +117,7 @@ int sep1752[MAXDAYS] = { char day_headings[] = " S M Tu W Th F S "; /* week1stday = 1 => " M Tu W Th F S S " */ -char j_day_headings[] = " S M Tu W Th F S "; +char j_day_headings[] = "Sun Mon Tue Wed Thu Fri Sat "; /* week1stday = 1 => " M Tu W Th F S S " */ const char *full_month[12]; @@ -127,13 +142,22 @@ const char *full_month[12]; int week1stday; int julian; +#define FMT_ST_LINES 8 +#define FMT_ST_CHARS 300 /* 90 suffices in most locales */ +struct fmt_st +{ + char s[FMT_ST_LINES][FMT_ST_CHARS]; +}; + void ascii_day __P((char *, int)); void center __P((const char *, int, int)); void day_array __P((int, int, int *)); int day_in_week __P((int, int, int)); int day_in_year __P((int, int, int)); void j_yearly __P((int)); +void do_monthly __P((int, int, struct fmt_st*)); void monthly __P((int, int)); +void monthly3 __P((int, int)); void trim_trailing_spaces __P((char *)); void usage __P((void)); void yearly __P((int)); @@ -146,6 +170,7 @@ main(int argc, char **argv) { time_t now; int ch, month, year, yflag; char *progname, *p; + int num_months = NUM_MONTHS; progname = argv[0]; if ((p = strrchr(progname, '/')) != NULL) @@ -157,8 +182,14 @@ main(int argc, char **argv) { textdomain(PACKAGE); yflag = 0; - while ((ch = getopt(argc, argv, "mjy")) != EOF) + while ((ch = getopt(argc, argv, "13mjyV")) != EOF) switch(ch) { + case '1': + num_months = 1; + break; + case '3': + num_months = 3; + break; case 'm': week1stday = 1; break; @@ -201,8 +232,10 @@ main(int argc, char **argv) { } headers_init(); - if (month) + if (month && num_months == 1) monthly(month, year); + else if (month && num_months == 3) + monthly3(month, year); else if (julian) j_yearly(year); else @@ -233,7 +266,7 @@ void headers_init(void) for(i = 0 ; i < 7 ; i++ ) { wd = (i + week1stday) % 7; strncat(day_headings,weekday(wd),2); - strcat(j_day_headings,weekday(wd)); + strncat(j_day_headings,weekday(wd),3); if (strlen(weekday(wd)) == 2) strcat(j_day_headings," "); strcat(day_headings," "); @@ -252,24 +285,86 @@ void headers_init(void) } void -monthly(month, year) +do_monthly(month, year, out) int month, year; + struct fmt_st* out; { int col, row, len, days[MAXDAYS]; char *p, lineout[300]; day_array(month, year, days); len = sprintf(lineout, "%s %d", full_month[month - 1], year); - (void)printf("%*s%s\n%s\n", - ((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "", - lineout, julian ? j_day_headings : day_headings); + (void)sprintf(out->s[0],"%*s%s", + ((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "", lineout ); + (void)sprintf(out->s[1],"%s", + julian ? j_day_headings : day_headings); for (row = 0; row < 6; row++) { for (col = 0, p = lineout; col < 7; col++, p += julian ? J_DAY_LEN : DAY_LEN) ascii_day(p, days[row * 7 + col]); *p = '\0'; trim_trailing_spaces(lineout); - (void)printf("%s\n", lineout); + (void)sprintf(out->s[row+2],"%s", lineout); + } +} + +void +monthly(month, year) + int month, year; +{ + int i; + struct fmt_st out; + + do_monthly(month, year, &out); + for ( i = 0; i < FMT_ST_LINES; i++ ) + { + printf("%s\n", out.s[i]); + } +} + +void +monthly3(month, year) + int month, year; +{ + int i; + int width; + struct fmt_st out_prev; + struct fmt_st out_curm; + struct fmt_st out_next; + int prev_month, prev_year; + int next_month, next_year; + + if ( month == 1 ) + { + prev_month = 12; + prev_year = year - 1; + } + else + { + prev_month = month - 1; + prev_year = year; + } + if ( month == 12 ) + { + next_month = 1; + next_year = year + 1; + } + else + { + next_month = month + 1; + next_year = year; + } + + do_monthly(prev_month, prev_year, &out_prev); + do_monthly(month, year, &out_curm); + do_monthly(next_month, next_year, &out_next); + width = (julian ? J_WEEK_LEN : WEEK_LEN); + for ( i = 0; i < FMT_ST_LINES; i++ ) + { + printf("%-*.*s %-*.*s %-*.*s\n", + width, width, out_prev.s[i], + width, width, out_curm.s[i], + width, width, out_next.s[i] ); } } diff --git a/misc-utils/ddate.c b/misc-utils/ddate.c index 304c31c60..bf7a37f28 100644 --- a/misc-utils/ddate.c +++ b/misc-utils/ddate.c @@ -153,8 +153,7 @@ struct disc_time convert(int,int); struct disc_time makeday(int,int,int); int -main (int argc, char *argv[]) -{ +main (int argc, char *argv[]) { long t; struct tm *eris; int bob,raw; diff --git a/misc-utils/logger.1 b/misc-utils/logger.1 index b5459ed4c..2c154ec09 100644 --- a/misc-utils/logger.1 +++ b/misc-utils/logger.1 @@ -41,7 +41,7 @@ .Nd make entries in the system log .Sh SYNOPSIS .Nm logger -.Op Fl is +.Op Fl isd .Op Fl f Ar file .Op Fl p Ar pri .Op Fl t Ar tag @@ -80,11 +80,12 @@ Mark every line in the log with the specified Write to socket as specified with .Ar socket instead of builtin syslog routines. +.It Fl d +Use a datagram instead of a stream connection to this socket. .It -- End the argument list. This is to allow the .Ar message -to start with a hyphen (\-). This feature was not present in the -original BSD logger command; it is a GNU-specific extra. +to start with a hyphen (\-). .It Ar message Write the message to log; if not specified, and the .Fl f diff --git a/misc-utils/logger.c b/misc-utils/logger.c index 372fe1ece..ae0ebec00 100644 --- a/misc-utils/logger.c +++ b/misc-utils/logger.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "nls.h" #define SYSLOG_NAMES @@ -54,20 +55,27 @@ int decode __P((char *, CODE *)); int pencode __P((char *)); void usage __P((void)); +static int optd = 0; + static int myopenlog(const char *sock) { int fd; - static struct sockaddr s_addr; /* AF_UNIX address of local logger */ + static struct sockaddr_un s_addr; /* AF_UNIX address of local logger */ + + if (strlen(sock) >= sizeof(s_addr.sun_path)) { + printf ("logger: openlog: pathname too long\n"); + exit(1); + } - s_addr.sa_family = AF_UNIX; - (void)strncpy(s_addr.sa_data, sock, sizeof(s_addr.sa_data)); + s_addr.sun_family = AF_UNIX; + (void)strcpy(s_addr.sun_path, sock); - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + if ((fd = socket(AF_UNIX, optd ? SOCK_DGRAM : SOCK_STREAM, 0)) == -1) { printf ("socket: %s.\n", strerror(errno)); exit (1); } - if (connect(fd, &s_addr, sizeof(s_addr.sa_family)+strlen(s_addr.sa_data)) == -1) { + if (connect(fd, (struct sockaddr *) &s_addr, sizeof(s_addr)) == -1) { printf ("connect: %s.\n", strerror(errno)); exit (1); } @@ -80,7 +88,6 @@ mysyslog(int fd, int logflags, int pri, char *tag, char *msg) { time_t now; if (fd > -1) { - /* there was a gethostname call here, but its output was not used */ /* avoid snprintf - it does not exist on ancient systems */ if (logflags & LOG_PID) sprintf (pid, "[%d]", getpid()); @@ -125,7 +132,7 @@ main(int argc, char **argv) { tag = NULL; pri = LOG_NOTICE; logflags = 0; - while ((ch = getopt(argc, argv, "f:ip:st:u:")) != EOF) + while ((ch = getopt(argc, argv, "f:ip:st:u:d")) != EOF) switch((char)ch) { case 'f': /* file to log */ if (freopen(optarg, "r", stdin) == NULL) { @@ -150,6 +157,9 @@ main(int argc, char **argv) { case 'u': /* unix socket */ usock = optarg; break; + case 'd': + optd = 1; /* use datagrams */ + break; case '?': default: usage(); diff --git a/misc-utils/look.c b/misc-utils/look.c index a8e826fa4..d601e1c97 100644 --- a/misc-utils/look.c +++ b/misc-utils/look.c @@ -137,13 +137,25 @@ main(int argc, char *argv[]) if ((fd = open(file, O_RDONLY, 0)) < 0 || fstat(fd, &sb)) err("%s: %s", file, strerror(errno)); - if ((void *)(front = mmap(NULL, - (size_t)sb.st_size, - PROT_READ, - MAP_FILE|MAP_SHARED, - fd, - (off_t)0)) <= (void *)0) + front = mmap(NULL, (size_t) sb.st_size, PROT_READ, +#ifdef MAP_FILE + MAP_FILE | +#endif + MAP_SHARED, fd, (off_t) 0); + if +#ifdef MAP_FAILED + (front == MAP_FAILED) +#else + ((void *)(front) <= (void *)0) +#endif err("%s: %s", file, strerror(errno)); + +#if 0 + /* workaround for mmap problem (rmiller@duskglow.com) */ + if (front == (void *)0) + return 1; +#endif + back = front + sb.st_size; return look(front, back); } diff --git a/misc-utils/namei.c b/misc-utils/namei.c index 65faad4f3..f77d501c4 100644 --- a/misc-utils/namei.c +++ b/misc-utils/namei.c @@ -47,6 +47,7 @@ chdir to /, or if it encounters an unknown file type. #include #include #include +#include #include #include #include diff --git a/misc-utils/procs.c b/misc-utils/procs.c index 715d9fb09..3f52387de 100644 --- a/misc-utils/procs.c +++ b/misc-utils/procs.c @@ -14,14 +14,14 @@ #define _POSIX_SOURCE 1 +#include +#include #include #include #include #include #include #include -#include -#include #include "kill.h" extern char *mybasename (char *); diff --git a/misc-utils/script.1 b/misc-utils/script.1 index ddc35223d..3edd82d4b 100644 --- a/misc-utils/script.1 +++ b/misc-utils/script.1 @@ -31,15 +31,17 @@ .\" .\" @(#)script.1 6.5 (Berkeley) 7/27/91 .\" -.Dd July 27, 1991 +.Dd July 30, 2000 .Dt SCRIPT 1 -.Os BSD 4 +.Os Linux .Sh NAME .Nm script .Nd make typescript of terminal session .Sh SYNOPSIS .Nm script .Op Fl a +.Op Fl f +.Op Fl q .Op Ar file .Sh DESCRIPTION .Nm Script @@ -58,7 +60,7 @@ saves all dialogue in If no file name is given, the typescript is saved in the file .Pa typescript . .Pp -Option: +Options: .Bl -tag -width Ds .It Fl a Append the output to @@ -66,6 +68,12 @@ Append the output to or .Pa typescript , retaining the prior contents. +.It Fl f +Flush output after each write. This is nice for telecooperation: +One person does `mkfifo foo; script -f foo' and another can +supervise real-time what is being done using `cat foo'. +.It Fl q +Be quiet. .El .Pp The script ends when the forked shell exits (a diff --git a/misc-utils/script.c b/misc-utils/script.c index cb7ae1a96..c3bf142e6 100644 --- a/misc-utils/script.c +++ b/misc-utils/script.c @@ -31,8 +31,11 @@ * SUCH DAMAGE. */ -/* 1999-02-22 Arkadiusz Mi¶kiewicz +/* + * 1999-02-22 Arkadiusz Mi¶kiewicz * - added Native Language Support + * + * 2000-07-30 Per Andreas Buer - added "q"-option */ /* @@ -86,25 +89,65 @@ int l; #ifndef HAVE_openpty char line[] = "/dev/ptyXX"; #endif -int aflg; +int aflg = 0; +int fflg = 0; +int qflg = 0; + +static char *progname; + +static void +die_if_symlink(char *fn) { + struct stat s; + + if (lstat(fn, &s) == 0 && S_ISLNK(s.st_mode)) { + fprintf(stderr, + _("Warning: `%s' is a symlink.\n" + "Use `%s [options] %s' if you really " + "want to use it.\n" + "Script not started.\n"), + fn, progname, fn); + exit(1); + } +} int main(int argc, char **argv) { extern int optind; + char *p; int ch; + progname = argv[0]; + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; + + setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - while ((ch = getopt(argc, argv, "a")) != EOF) + if (argc == 2) { + if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) { + printf(_("%s from %s\n"), + progname, util_linux_version); + return 0; + } + } + + while ((ch = getopt(argc, argv, "afq")) != EOF) switch((char)ch) { case 'a': aflg++; break; + case 'f': + fflg++; + break; + case 'q': + qflg++; + break; case '?': default: - fprintf(stderr, _("usage: script [-a] [file]\n")); + fprintf(stderr, + _("usage: script [-a] [-f] [-q] [file]\n")); exit(1); } argc -= optind; @@ -112,8 +155,10 @@ main(int argc, char **argv) { if (argc > 0) fname = argv[0]; - else + else { fname = "typescript"; + die_if_symlink(fname); + } if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { perror(fname); fail(); @@ -124,7 +169,8 @@ main(int argc, char **argv) { shell = _PATH_BSHELL; getmaster(); - printf(_("Script started, file is %s\n"), fname); + if (!qflg) + printf(_("Script started, file is %s\n"), fname); fixtty(); (void) signal(SIGCHLD, finish); @@ -167,11 +213,11 @@ doinput() { void finish(int dummy) { - union wait status; + int status; register int pid; register int die = 0; - while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0) + while ((pid = wait3(&status, WNOHANG, 0)) > 0) if (pid == child) die = 1; @@ -197,6 +243,8 @@ dooutput() { break; (void) write(1, obuf, cc); (void) fwrite(obuf, 1, cc, fscript); + if (fflg) + (void) fflush(fscript); } done(); } @@ -250,13 +298,17 @@ done() { time_t tvec; if (subchild) { - tvec = time((time_t *)NULL); - fprintf(fscript,_("\nScript done on %s"), ctime(&tvec)); + if (!qflg) { + tvec = time((time_t *)NULL); + fprintf(fscript, _("\nScript done on %s"), + ctime(&tvec)); + } (void) fclose(fscript); (void) close(master); } else { (void) tcsetattr(0, TCSAFLUSH, &tt); - printf(_("Script done, file is %s\n"), fname); + if (!qflg) + printf(_("Script done, file is %s\n"), fname); } exit(0); } diff --git a/misc-utils/whereis.c b/misc-utils/whereis.c index bc505c54f..239b1f4ae 100644 --- a/misc-utils/whereis.c +++ b/misc-utils/whereis.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include "nls.h" @@ -111,6 +112,7 @@ static char *bindirs[] = { static char *mandirs[] = { "/usr/man/*", + "/usr/share/man/*", "/usr/X386/man/*", "/usr/X11/man/*", "/usr/TeX/man/*", diff --git a/misc-utils/write.c b/misc-utils/write.c index 1cf99c7f0..e794a4eee 100644 --- a/misc-utils/write.c +++ b/misc-utils/write.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -60,10 +61,9 @@ #include #include #include -#ifdef __linux__ #include #include "pathnames.h" -#endif +#include "carefulputc.h" #include "nls.h" void search_utmp(char *, char *, char *, uid_t); @@ -73,7 +73,6 @@ static void done(int); int term_chk(char *, int *, time_t *, int); int utmp_chk(char *, char *); - int main(int argc, char **argv) { time_t atime; @@ -289,24 +288,25 @@ int term_chk(char *tty, int *msgsokP, time_t *atimeP, int showerror) * do_write - actually make the connection */ void do_write(char *tty, char *mytty, uid_t myuid) { - register char *login, *nows; - register struct passwd *pwd; + char *login, *pwuid, *nows; + struct passwd *pwd; time_t now; char path[MAXPATHLEN], host[MAXHOSTNAMELEN], line[512]; - /* Determine our login name before the we reopen() stdout */ - if ((login = getlogin()) == NULL) { - if ((pwd = getpwuid(myuid)) != NULL) - login = pwd->pw_name; - else - login = "???"; - } + /* Determine our login name(s) before the we reopen() stdout */ + if ((pwd = getpwuid(myuid)) != NULL) + pwuid = pwd->pw_name; + else + pwuid = "???"; + if ((login = getlogin()) == NULL) + login = pwuid; if (strlen(tty) + 6 > sizeof(path)) exit(1); (void)sprintf(path, "/dev/%s", tty); if ((freopen(path, "w", stdout)) == NULL) { - (void)fprintf(stderr, "write: %s: %s\n", path, strerror(errno)); + (void)fprintf(stderr, "write: %s: %s\n", + path, strerror(errno)); exit(1); } @@ -320,8 +320,12 @@ void do_write(char *tty, char *mytty, uid_t myuid) { nows = ctime(&now); nows[16] = '\0'; printf("\r\n\007\007\007"); - (void)printf(_("Message from %s@%s on %s at %s ..."), - login, host, mytty, nows + 11); + if (strcmp(login, pwuid)) + (void)printf(_("Message from %s@%s (as %s) on %s at %s ..."), + login, host, pwuid, mytty, nows + 11); + else + (void)printf(_("Message from %s@%s on %s at %s ..."), + login, host, mytty, nows + 11); printf("\r\n"); while (fgets(line, sizeof(line), stdin) != NULL) @@ -339,34 +343,24 @@ done(int dummy) { /* * wr_fputs - like fputs(), but makes control characters visible and - * turns \n into \r\n + * turns \n into \r\n. */ -void wr_fputs(char *s) - -{ +void +wr_fputs(char *s) { char c; -#define PUTC(c) if (putchar(c) == EOF) goto err; +#define PUTC(c) if (carefulputc(c,stdout) == EOF) goto err; - for (; *s != '\0'; ++s) { - c = *s; - if (c == '\n') { + while(*s) { + c = *s++; + if (c == '\n') PUTC('\r'); - PUTC('\n'); - } else if (!isprint(c) && !isspace(c) && c != '\007') { - if (c & 0x80) { - /* use some fallback? */ - (void)printf("\\%3o", (unsigned char) c); - } else { - PUTC('^'); - PUTC(c^0x40); /* DEL to ?, others to alpha */ - } - } else - PUTC(c); + PUTC(c); } return; -err: (void)fprintf(stderr, "write: %s\n", strerror(errno)); +err: + fprintf(stderr, "write: %s\n", strerror(errno)); exit(1); #undef PUTC } diff --git a/mount/Makefile b/mount/Makefile index 6f72413db..18e30cde6 100644 --- a/mount/Makefile +++ b/mount/Makefile @@ -1,15 +1,13 @@ include ../make_include include ../MCONFIG -CFLAGS = -I$(LIB) $(OPT) -WARNFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes DEFINES = -DHAVE_NFS RPCSVCDIR = rpcsvc RPC_CFLAGS = -Wno-unused RPCGEN = rpcgen -COMPILE = $(CC) -c $(WARNFLAGS) $(CFLAGS) $(DEFINES) +COMPILE = $(CC) -c $(CFLAGS) $(DEFINES) LINK = $(CC) $(LDFLAGS) SUID_PROGS = mount umount @@ -24,6 +22,8 @@ endif PROGS = $(SUID_PROGS) $(NOSUID_PROGS) +MAYBE = pivot_root swapoff + # comment these out if you are not compiling in NFS support NFS_OBJS = nfsmount.o nfsmount_xdr.o nfsmount_clnt.o # uncomment this if you don't have libc-4.2 but do have the rpclib @@ -59,8 +59,7 @@ swapon: swapon.o version.o $(LINK) $^ -o $@ losetup.o: lomount.c - $(COMPILE) -DMAIN lomount.c - mv lomount.o losetup.o + $(COMPILE) -DMAIN lomount.c -o $@ losetup: losetup.o $(LINK) $^ -o $@ @@ -117,7 +116,7 @@ loop.h: sh mk_loop_h clean: - rm -f a.out core *~ *.o swapargs.h $(PROGS) swapoff + rm -f a.out core *~ *.o swapargs.h $(PROGS) $(MAYBE) rm -f loop.h nfs_mountversion.h clobber distclean realclean: clean diff --git a/mount/README.mount b/mount/README.mount index 2a8fae1c1..f010a1bd8 100644 --- a/mount/README.mount +++ b/mount/README.mount @@ -6,5 +6,5 @@ Rick Sladkey , Stephen Tweedie . Presently maintained by Andries Brouwer . -Ftp site: ftp.win.tue.nl:/pub/linux/util . +Ftp site: ftp.win.tue.nl:/pub/linux/utils/util-linux diff --git a/mount/bind.c b/mount/bind.c new file mode 100644 index 000000000..4af72a9c3 --- /dev/null +++ b/mount/bind.c @@ -0,0 +1,11 @@ +#include +#include + +main(int argc, char **argv) { + int ret; + + ret = mount(argv[1], argv[2], "bind", MS_MGC_VAL, NULL); + if (ret) + perror("bind"); + return ret; +} diff --git a/mount/fstab.c b/mount/fstab.c index aef26d90c..3ee1f36a1 100644 --- a/mount/fstab.c +++ b/mount/fstab.c @@ -99,21 +99,19 @@ read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) { struct mntent *mnt; while ((mnt = my_getmntent (mfp)) != NULL) { - if (!streq (mnt->mnt_type, MNTTYPE_IGNORE)) { - mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc)); - mc->nxt->prev = mc; - mc = mc->nxt; - mc->mnt_fsname = mnt->mnt_fsname; - mc->mnt_dir = mnt->mnt_dir; - mc->mnt_type = mnt->mnt_type; - mc->mnt_opts = mnt->mnt_opts; - mc->nxt = NULL; - } + if (!streq (mnt->mnt_type, MNTTYPE_IGNORE)) { + mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc)); + mc->nxt->prev = mc; + mc = mc->nxt; + mc->m = *mnt; + mc->nxt = mc0; + } } mc0->prev = mc; if (ferror (mfp->mntent_fp)) { int errsv = errno; - error(_("warning: error reading %s: %s"), fnam, strerror (errsv)); + error(_("warning: error reading %s: %s"), + fnam, strerror (errsv)); mc0->nxt = mc0->prev = NULL; } my_endmntent(mfp); @@ -163,7 +161,8 @@ read_fstab() { mfp = my_setmntent (fnam, "r"); if (mfp == NULL || mfp->mntent_fp == NULL) { int errsv = errno; - error(_("warning: can't open %s: %s"), _PATH_FSTAB, strerror (errsv)); + error(_("warning: can't open %s: %s"), + _PATH_FSTAB, strerror (errsv)); return; } read_mntentchn(mfp, fnam, mc); @@ -173,13 +172,14 @@ read_fstab() { /* Given the name NAME, try to find it in mtab. */ struct mntentchn * getmntfile (const char *name) { - struct mntentchn *mc; - - for (mc = mtab_head()->nxt; mc; mc = mc->nxt) - if (streq (mc->mnt_dir, name) || (streq (mc->mnt_fsname, name))) - break; - - return mc; + struct mntentchn *mc, *mc0; + + mc0 = mtab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if (streq (mc->m.mnt_dir, name) || + streq (mc->m.mnt_fsname, name)) + return mc; + return NULL; } /* @@ -188,110 +188,108 @@ getmntfile (const char *name) { */ struct mntentchn * getmntfilesbackward (const char *name, struct mntentchn *mcprev) { - struct mntentchn *mc, *mh; - - mh = mtab_head(); - if (!mcprev) - mcprev = mh; - for (mc = mcprev->prev; mc && mc != mh; mc = mc->prev) - if (streq (mc->mnt_dir, name) || (streq (mc->mnt_fsname, name))) - return mc; - - return NULL; + struct mntentchn *mc, *mc0; + + mc0 = mtab_head(); + if (!mcprev) + mcprev = mc0; + for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev) + if (streq (mc->m.mnt_dir, name) || + streq (mc->m.mnt_fsname, name)) + return mc; + return NULL; } /* Given the name FILE, try to find the option "loop=FILE" in mtab. */ struct mntentchn * -getmntoptfile (const char *file) -{ - struct mntentchn *mc; - char *opts, *s; - int l; - - if (!file) - return NULL; - - l = strlen(file); - - for (mc = mtab_head()->nxt; mc; mc = mc->nxt) - if ((opts = mc->mnt_opts) != NULL - && (s = strstr(opts, "loop=")) - && !strncmp(s+5, file, l) - && (s == opts || s[-1] == ',') - && (s[l+5] == 0 || s[l+5] == ',')) - return mc; - - return NULL; +getmntoptfile (const char *file) { + struct mntentchn *mc, *mc0; + char *opts, *s; + int l; + + if (!file) + return NULL; + + l = strlen(file); + + mc0 = mtab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if ((opts = mc->m.mnt_opts) != NULL + && (s = strstr(opts, "loop=")) + && !strncmp(s+5, file, l) + && (s == opts || s[-1] == ',') + && (s[l+5] == 0 || s[l+5] == ',')) + return mc; + return NULL; } /* Find the entry (SPEC,FILE) in fstab */ struct mntentchn * getfsspecfile (const char *spec, const char *file) { - struct mntentchn *mc; - - for (mc = fstab_head()->nxt; mc; mc = mc->nxt) - if (streq (mc->mnt_dir, file) && streq (mc->mnt_fsname, spec)) - return mc; - for (mc = fstab_head()->nxt; mc; mc = mc->nxt) - if ((streq (mc->mnt_dir, file) || - streq (canonicalize(mc->mnt_dir), file)) - && (streq (mc->mnt_fsname, spec) || - streq (canonicalize(mc->mnt_fsname), spec))) - break; - return mc; + struct mntentchn *mc, *mc0; + + mc0 = fstab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if (streq (mc->m.mnt_dir, file) && + streq (mc->m.mnt_fsname, spec)) + return mc; + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if ((streq (mc->m.mnt_dir, file) || + streq (canonicalize(mc->m.mnt_dir), file)) + && (streq (mc->m.mnt_fsname, spec) || + streq (canonicalize(mc->m.mnt_fsname), spec))) + return mc; + return NULL; } /* Find the dir FILE in fstab. */ struct mntentchn * getfsfile (const char *file) { - struct mntentchn *mc; - - for (mc = fstab_head()->nxt; mc; mc = mc->nxt) - if (streq (mc->mnt_dir, file)) - break; + struct mntentchn *mc, *mc0; - return mc; + mc0 = fstab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if (streq (mc->m.mnt_dir, file)) + return mc; + return NULL; } /* Find the device SPEC in fstab. */ struct mntentchn * -getfsspec (const char *spec) -{ - struct mntentchn *mc; - - for (mc = fstab_head()->nxt; mc; mc = mc->nxt) - if (streq (mc->mnt_fsname, spec)) - break; - - return mc; +getfsspec (const char *spec) { + struct mntentchn *mc, *mc0; + + mc0 = fstab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if (streq (mc->m.mnt_fsname, spec)) + return mc; + return NULL; } /* Find the uuid UUID in fstab. */ struct mntentchn * -getfsuuidspec (const char *uuid) -{ - struct mntentchn *mc; - - for (mc = fstab_head()->nxt; mc; mc = mc->nxt) - if (strncmp (mc->mnt_fsname, "UUID=", 5) == 0 - && streq(mc->mnt_fsname + 5, uuid)) - break; - - return mc; +getfsuuidspec (const char *uuid) { + struct mntentchn *mc, *mc0; + + mc0 = fstab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if (strncmp (mc->m.mnt_fsname, "UUID=", 5) == 0 + && streq(mc->m.mnt_fsname + 5, uuid)) + return mc; + return NULL; } /* Find the label LABEL in fstab. */ struct mntentchn * -getfsvolspec (const char *label) -{ - struct mntentchn *mc; - - for (mc = fstab_head()->nxt; mc; mc = mc->nxt) - if (strncmp (mc->mnt_fsname, "LABEL=", 6) == 0 - && streq(mc->mnt_fsname + 6, label)) - break; - - return mc; +getfsvolspec (const char *label) { + struct mntentchn *mc, *mc0; + + mc0 = fstab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if (strncmp (mc->m.mnt_fsname, "LABEL=", 6) == 0 + && streq(mc->m.mnt_fsname + 6, label)) + return mc; + return NULL; } /* Updating mtab ----------------------------------------------*/ @@ -371,7 +369,8 @@ lock_mtab (void) { int errsv = errno; /* linktargetfile does not exist (as a file) and we cannot create it. Read-only filesystem? - Too many files open in the system? Filesystem full? */ + Too many files open in the system? + Filesystem full? */ die (EX_FILEIO, _("can't create lock file %s: %s " "(use -n flag to override)"), linktargetfile, strerror (errsv)); @@ -455,7 +454,7 @@ unlock_mtab (void) { /* * Update the mtab. - * Used by umount with null INSTEAD: remove any DIR entries. + * Used by umount with null INSTEAD: remove the last DIR entry. * Used by mount upon a remount: update option part, * and complain if a wrong device or type was given. * [Note that often a remount will be a rw remount of / @@ -465,90 +464,87 @@ unlock_mtab (void) { void update_mtab (const char *dir, struct mntent *instead) { - struct mntent *mnt; - struct mntent *next; - struct mntent remnt; - int added = 0; - mntFILE *mfp, *mftmp; + mntFILE *mfp, *mftmp; + const char *fnam = MOUNTED; + struct mntentchn mtabhead; /* dummy */ + struct mntentchn *mc, *mc0, absent; - if (mtab_does_not_exist() || mtab_is_a_symlink()) - return; + if (mtab_does_not_exist() || mtab_is_a_symlink()) + return; - lock_mtab(); + lock_mtab(); - mfp = my_setmntent(MOUNTED, "r"); - if (mfp == NULL || mfp->mntent_fp == NULL) { - int errsv = errno; - error (_("cannot open %s (%s) - mtab not updated"), - MOUNTED, strerror (errsv)); - goto leave; - } + /* having locked mtab, read it again */ + mc0 = mc = &mtabhead; + mc->nxt = mc->prev = NULL; - mftmp = my_setmntent (MOUNTED_TEMP, "w"); - if (mftmp == NULL || mfp->mntent_fp == NULL) { - int errsv = errno; - error (_("cannot open %s (%s) - mtab not updated"), - MOUNTED_TEMP, strerror (errsv)); - goto leave; - } - - while ((mnt = my_getmntent (mfp))) { - if (streq (mnt->mnt_dir, dir) -#if 0 - /* Matthew Wilcox */ - /* This is meant for Patch 212 on Jitterbug, - still in incoming, to allow remounting - on a different directory. */ - || (instead && instead->mnt_fsname && - (!streq (instead->mnt_fsname, "none")) && - (streq (mnt->mnt_fsname, instead->mnt_fsname))) -#endif - ) { - added++; - if (instead) { /* a remount */ - remnt = *instead; - next = &remnt; - remnt.mnt_fsname = mnt->mnt_fsname; - remnt.mnt_type = mnt->mnt_type; - if (instead->mnt_fsname - && !streq(mnt->mnt_fsname, instead->mnt_fsname)) - printf(_("mount: warning: cannot change " - "mounted device with a remount\n")); - else if (instead->mnt_type - && !streq(instead->mnt_type, "unknown") - && !streq(mnt->mnt_type, instead->mnt_type)) - printf(_("mount: warning: cannot change " - "filesystem type with a remount\n")); - } else - next = NULL; - } else - next = mnt; - if (next && my_addmntent(mftmp, next) == 1) { - int errsv = errno; - die (EX_FILEIO, _("error writing %s: %s"), - MOUNTED_TEMP, strerror (errsv)); - } - } - if (instead && !added && my_addmntent(mftmp, instead) == 1) { - int errsv = errno; - die (EX_FILEIO, _("error writing %s: %s"), - MOUNTED_TEMP, strerror (errsv)); - } + mfp = my_setmntent(fnam, "r"); + if (mfp == NULL || mfp->mntent_fp == NULL) { + int errsv = errno; + error (_("cannot open %s (%s) - mtab not updated"), + fnam, strerror (errsv)); + goto leave; + } - my_endmntent (mfp); - if (fchmod (fileno (mftmp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { - int errsv = errno; - fprintf(stderr, _("error changing mode of %s: %s\n"), MOUNTED_TEMP, - strerror (errsv)); - } - my_endmntent (mftmp); + read_mntentchn(mfp, fnam, mc); + + /* find last occurrence of dir */ + for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev) + if (streq (mc->m.mnt_dir, dir)) + break; + if (mc && mc != mc0) { + if (instead == NULL) { + /* An umount - remove entry */ + if (mc && mc != mc0) { + mc->prev->nxt = mc->nxt; + mc->nxt->prev = mc->prev; + } + } else { + /* A remount */ + mc->m.mnt_opts = instead->mnt_opts; + } + } else if (instead) { + /* not found, add a new entry */ + absent.m = *instead; + absent.nxt = mc0; + absent.prev = mc0->prev; + mc0->prev = &absent; + if (mc0->nxt == NULL) + mc0->nxt = &absent; + } - if (rename (MOUNTED_TEMP, MOUNTED) < 0) { - int errsv = errno; - fprintf(stderr, _("can't rename %s to %s: %s\n"), MOUNTED_TEMP, MOUNTED, - strerror(errsv)); - } + /* write chain to mtemp */ + mftmp = my_setmntent (MOUNTED_TEMP, "w"); + if (mftmp == NULL || mfp->mntent_fp == NULL) { + int errsv = errno; + error (_("cannot open %s (%s) - mtab not updated"), + MOUNTED_TEMP, strerror (errsv)); + goto leave; + } + + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) { + if (my_addmntent(mftmp, &(mc->m)) == 1) { + int errsv = errno; + die (EX_FILEIO, _("error writing %s: %s"), + MOUNTED_TEMP, strerror (errsv)); + } + } + + if (fchmod (fileno (mftmp->mntent_fp), + S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { + int errsv = errno; + fprintf(stderr, _("error changing mode of %s: %s\n"), + MOUNTED_TEMP, strerror (errsv)); + } + my_endmntent (mftmp); + + /* rename mtemp to mtab */ + if (rename (MOUNTED_TEMP, MOUNTED) < 0) { + int errsv = errno; + fprintf(stderr, _("can't rename %s to %s: %s\n"), + MOUNTED_TEMP, MOUNTED, strerror(errsv)); + } -leave: - unlock_mtab(); + leave: + unlock_mtab(); } diff --git a/mount/fstab.h b/mount/fstab.h index 65bf5dba6..820f418a0 100644 --- a/mount/fstab.h +++ b/mount/fstab.h @@ -1,3 +1,4 @@ +#include #define _PATH_FSTAB "/etc/fstab" #ifdef _PATH_MOUNTED #define MOUNTED_LOCK _PATH_MOUNTED "~" @@ -13,11 +14,8 @@ int mtab_does_not_exist(void); int mtab_is_a_symlink(void); struct mntentchn { - struct mntentchn *nxt, *prev; - char *mnt_fsname; - char *mnt_dir; - char *mnt_type; - char *mnt_opts; + struct mntentchn *nxt, *prev; + struct mntent m; }; struct mntentchn *mtab_head (void); diff --git a/mount/linux_fs.h b/mount/linux_fs.h index 635389a01..043ac16a7 100644 --- a/mount/linux_fs.h +++ b/mount/linux_fs.h @@ -100,3 +100,52 @@ struct fat_super_block { u_char s_label2[11]; /* for Windows? */ u_char s_fs2[8]; /* garbage or "FAT32 " */ }; + +#define XFS_SUPER_MAGIC "XFSB" +#define XFS_SUPER_MAGIC2 "BSFX" +struct xfs_super_block { + u_char s_magic[4]; + u_char s_dummy[28]; + u_char s_uuid[16]; + u_char s_dummy2[60]; + u_char s_fname[12]; +}; + +#define CRAMFS_SUPER_MAGIC 0x28cd3d45 +struct cramfs_super_block { + u_char s_magic[4]; + u_char s_dummy[12]; + u_char s_id[16]; +}; +#define cramfsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \ + (((uint) s.s_magic[2]) << 16) + \ + (((uint) s.s_magic[3]) << 24)) + +#define HFS_SUPER_MAGIC 0x4244 +struct hfs_super_block { + u_char s_magic[2]; + u_char s_dummy[18]; + u_char s_blksize[4]; +}; +#define hfsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8)) +#define hfsblksize(s) ((uint) s.s_blksize[0] + \ + (((uint) s.s_blksize[1]) << 8) + \ + (((uint) s.s_blksize[2]) << 16) + \ + (((uint) s.s_blksize[3]) << 24)) + +#define HPFS_SUPER_MAGIC 0xf995e849 +struct hpfs_super_block { + u_char s_magic[4]; + u_char s_magic2[4]; +}; +#define hpfsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \ + (((uint) s.s_magic[2]) << 16) + \ + (((uint) s.s_magic[3]) << 24)) + +struct adfs_super_block { + u_char s_dummy[448]; + u_char s_blksize[1]; + u_char s_dummy2[62]; + u_char s_checksum[1]; +}; +#define adfsblksize(s) ((uint) s.s_blksize[0]) diff --git a/mount/lomount.c b/mount/lomount.c index 52157a14a..cabc44461 100644 --- a/mount/lomount.c +++ b/mount/lomount.c @@ -68,7 +68,7 @@ crypt_name (int id) { return "undefined"; } -static void +static int show_loop (char *device) { struct loop_info loopinfo; int fd; @@ -77,36 +77,69 @@ show_loop (char *device) { int errsv = errno; fprintf(stderr, _("loop: can't open device %s: %s\n"), device, strerror (errsv)); - return; + return 2; } if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) < 0) { int errsv = errno; fprintf(stderr, _("loop: can't get info on device %s: %s\n"), device, strerror (errsv)); close (fd); - return; + return 1; } printf (_("%s: [%04x]:%ld (%s) offset %d, %s encryption\n"), device, loopinfo.lo_device, loopinfo.lo_inode, loopinfo.lo_name, loopinfo.lo_offset, crypt_name (loopinfo.lo_encrypt_type)); close (fd); + + return 0; } #endif +int +is_loop_device (const char *device) { + struct stat statbuf; + int loopmajor; +#if 1 + loopmajor = 7; +#else + FILE *procdev; + char line[100], *cp; + + loopmajor = 0; + if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) { + while (fgets (line, sizeof(line), procdev)) { + if ((cp = strstr (line, " loop\n")) != NULL) { + *cp='\0'; + loopmajor=atoi(line); + break; + } + } + fclose(procdev); + } +#endif + return (loopmajor && stat(device, &statbuf) == 0 && + S_ISBLK(statbuf.st_mode) && + (statbuf.st_rdev>>8) == loopmajor); +} + +#define SIZE(a) (sizeof(a)/sizeof(a[0])) + char * find_unused_loop_device (void) { /* Just creating a device, say in /tmp, is probably a bad idea - people might have problems with backup or so. So, we just try /dev/loop[0-7]. */ char dev[20]; - int i, fd, somedev = 0, someloop = 0, loop_known = 0; + char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" }; + int i, j, fd, somedev = 0, someloop = 0, loop_known = 0; struct stat statbuf; struct loop_info loopinfo; FILE *procdev; - for(i = 0; i < 256; i++) { - sprintf(dev, "/dev/loop%d", i); + for (j = 0; j < SIZE(loop_formats); j++) { + for(i = 0; i < 256; i++) { + sprintf(dev, loop_formats[j], i); if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) { somedev++; fd = open (dev, O_RDONLY); @@ -121,8 +154,8 @@ find_unused_loop_device (void) { } continue;/* continue trying as long as devices exist */ } - if (i >= 7) - break; + break; + } } /* Nothing found. Why not? */ @@ -393,7 +426,7 @@ main(int argc, char **argv) { if (delete) res = del_loop(argv[optind]); else - show_loop(argv[optind]); + res = show_loop(argv[optind]); } else { if (offset && sscanf(offset,"%d",&off) != 1) usage(); diff --git a/mount/lomount.h b/mount/lomount.h index 00a49f558..1a93c693f 100644 --- a/mount/lomount.h +++ b/mount/lomount.h @@ -1,4 +1,5 @@ extern int verbose; extern int set_loop (const char *, const char *, int, const char *, int *); extern int del_loop (const char *); +extern int is_loop_device (const char *); extern char * find_unused_loop_device (void); diff --git a/mount/losetup.8 b/mount/losetup.8 index c2e41307d..d364f4f1e 100644 --- a/mount/losetup.8 +++ b/mount/losetup.8 @@ -46,6 +46,15 @@ attacks. .IP "\fB\-o \fIoffset\fP" the data start is moved \fIoffset\fP bytes into the specified file or device. +.SH RETURN VALUE +.B losetup +returns 0 on success, nonzero on failure. When +.B losetup +displays the status of a loop device, it returns 1 if the device +is not configured and 2 if an error occurred which prevented +.B losetup +from determining the status of the device. + .SH FILES .nf /dev/loop0,/dev/loop1,... loop devices (major=7) @@ -81,7 +90,5 @@ DES encryption is painfully slow. On the other hand, XOR is terribly weak. .SH AUTHORS .nf Original version: Theodore Ts'o -Maintained by: Werner Almesberger Original DES by: Eric Young -Modularized and updated 28-5-94: Mitch DSouza .fi diff --git a/mount/mount.8 b/mount/mount.8 index 7016ee535..f90341198 100644 --- a/mount/mount.8 +++ b/mount/mount.8 @@ -98,6 +98,14 @@ lists all mounted file systems (of type The option \-l adds the (ext2) labels in this listing. See below. +.\" In fact since 2.3.99. At first the syntax was mount -t bind. +Since Linux 2.4.0 it is possible to remount part of the +file hierarchy somewhere else. The call is +.RS +.br +.B "mount --bind olddir newdir" +.RE + The .I proc file system is not associated with a special device, and when @@ -367,7 +375,8 @@ necessary. The nfs ad hoc code is built in, but smbfs and ncpfs have a separate mount program. In order to make it possible to treat all types in a uniform way, mount will execute the program .I /sbin/mount.TYPE -(if that exists) when called with type smb or ncp. +(if that exists) when called with type +.IR TYPE . Since various versions of the .I smbmount program have different calling conventions, diff --git a/mount/mount.c b/mount/mount.c index b8ee2ebec..39ccd3e63 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -36,6 +36,7 @@ * - added `owner' mount option * 2000-05-11 Mark A. Peloquin * - check_special_mountprog now returns correct status + * 2000-11-08 aeb: accept nonnumeric uid=, gid= options */ #include @@ -45,6 +46,9 @@ #include #include +#include +#include + #include #include #include @@ -58,6 +62,7 @@ #include "lomount.h" #include "loop.h" #include "linux_fs.h" /* for BLKGETSIZE */ +#include "mount_guess_rootdev.h" #include "mount_guess_fstype.h" #include "mount_by_label.h" #include "getusername.h" @@ -96,6 +101,12 @@ static int optfork = 0; /* Add volumelabel in a listing of mounted devices (-l). */ static int list_with_volumelabel = 0; +/* Nonzero for mount --bind */ +static int bind = 0; + +/* Nonzero for mount {--replace|--before|--after|--over} */ +static int mounttype = 0; + /* True if ruid != euid. */ static int suid = 0; @@ -108,8 +119,7 @@ struct opt_map { }; /* Custom mount options for our own purposes. */ -/* We can use the high-order 16 bits, since the mount call - has MS_MGC_VAL there. */ +/* Maybe these should now be freed for kernel use again */ #define MS_NOAUTO 0x80000000 #define MS_USERS 0x40000000 #define MS_USER 0x20000000 @@ -141,6 +151,7 @@ static const struct opt_map opt_map[] = { { "sync", 0, 0, MS_SYNCHRONOUS}, /* synchronous I/O */ { "async", 0, 1, MS_SYNCHRONOUS}, /* asynchronous I/O */ { "remount", 0, 0, MS_REMOUNT}, /* Alter flags of mounted FS */ + { "bind", 0, 0, MS_BIND }, /* Remount part of tree elsewhere */ { "auto", 0, 1, MS_NOAUTO }, /* Can be mounted using -a */ { "noauto", 0, 0, MS_NOAUTO }, /* Can only be mounted explicitly */ { "users", 0, 0, MS_USERS }, /* Allow ordinary user to mount */ @@ -217,17 +228,17 @@ int mount_quiet=0; /* Report on a single mount. */ static void -print_one (const struct mntentchn *mc) { +print_one (const struct mntent *me) { if (mount_quiet) return; - printf ("%s on %s", mc->mnt_fsname, mc->mnt_dir); - if (mc->mnt_type != NULL && *(mc->mnt_type) != '\0') - printf (" type %s", mc->mnt_type); - if (mc->mnt_opts != NULL) - printf (" (%s)", mc->mnt_opts); + printf ("%s on %s", me->mnt_fsname, me->mnt_dir); + if (me->mnt_type != NULL && *(me->mnt_type) != '\0') + printf (" type %s", me->mnt_type); + if (me->mnt_opts != NULL) + printf (" (%s)", me->mnt_opts); if (list_with_volumelabel) { const char *label; - label = get_volume_label_by_spec(mc->mnt_fsname); + label = get_volume_label_by_spec(me->mnt_fsname); if (label) printf (" [%s]", label); } @@ -237,18 +248,22 @@ print_one (const struct mntentchn *mc) { /* Report on everything in mtab (of the specified types if any). */ static int print_all (string_list types) { - struct mntentchn *mc; + struct mntentchn *mc, *mc0; - for (mc = mtab_head()->nxt; mc; mc = mc->nxt) { - if (matching_type (mc->mnt_type, types)) - print_one (mc); + mc0 = mtab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) { + if (matching_type (mc->m.mnt_type, types)) + print_one (&(mc->m)); } exit (0); } -/* Look for OPT in opt_map table and return mask value. If OPT isn't found, - tack it onto extra_opts (which is non-NULL). */ +/* + * Look for OPT in opt_map table and return mask value. + * If OPT isn't found, tack it onto extra_opts (which is non-NULL). + * For the options uid= and gid= replace user or group name by its value. + */ static inline void parse_opt (const char *opt, int *mask, char *extra_opts) { const struct opt_map *om; @@ -272,36 +287,62 @@ parse_opt (const char *opt, int *mask, char *extra_opts) { #endif return; } + if (*extra_opts) strcat(extra_opts, ","); + + /* convert nonnumeric ids to numeric */ + if (!strncmp(opt, "uid=", 4) && !isdigit(opt[4])) { + struct passwd *pw = getpwnam(opt+4); + char uidbuf[20]; + + if (pw) { + sprintf(uidbuf, "uid=%d", pw->pw_uid); + strcat(extra_opts, uidbuf); + return; + } + } + if (!strncmp(opt, "gid=", 4) && !isdigit(opt[4])) { + struct group *gr = getgrnam(opt+4); + char gidbuf[20]; + + if (gr) { + sprintf(gidbuf, "gid=%d", gr->gr_gid); + strcat(extra_opts, gidbuf); + return; + } + } + strcat(extra_opts, opt); } /* Take -o options list and compute 4th and 5th args to mount(2). flags - gets the standard options and extra_opts anything we don't recognize. */ + gets the standard options (indicated by bits) and extra_opts all the rest */ static void parse_opts (char *opts, int *flags, char **extra_opts) { - char *opt; + char *opt; - *flags = 0; - *extra_opts = NULL; + *flags = 0; + *extra_opts = NULL; - clear_string_opts(); + clear_string_opts(); - if (opts != NULL) - { - *extra_opts = xmalloc (strlen (opts) + 1); - **extra_opts = '\0'; + if (opts != NULL) { + *extra_opts = xmalloc (strlen (opts) + 1); + **extra_opts = '\0'; - for (opt = strtok (opts, ","); opt; opt = strtok (NULL, ",")) - if (!parse_string_opt (opt)) - parse_opt (opt, flags, *extra_opts); - } + for (opt = strtok (opts, ","); opt; opt = strtok (NULL, ",")) + if (!parse_string_opt (opt)) + parse_opt (opt, flags, *extra_opts); + } - if (readonly) - *flags |= MS_RDONLY; - if (readwrite) - *flags &= ~MS_RDONLY; + if (readonly) + *flags |= MS_RDONLY; + if (readwrite) + *flags &= ~MS_RDONLY; + *flags |= mounttype; + if (bind) + *flags |= MS_BIND; } /* Try to build a canonical options string. */ @@ -340,10 +381,11 @@ already (const char *spec, const char *node) { if ((mc = getmntfile(node)) != NULL) error (_("mount: according to mtab, %s is already mounted on %s"), - mc->mnt_fsname, node); - else if ((mc = getmntfile(spec)) != NULL) + mc->m.mnt_fsname, node); + else if (spec && strcmp (spec, "none") && + (mc = getmntfile(spec)) != NULL) error (_("mount: according to mtab, %s is mounted on %s"), - spec, mc->mnt_dir); + spec, mc->m.mnt_dir); else ret = 0; return ret; @@ -369,10 +411,10 @@ create_mtab (void) { /* Find the root entry by looking it up in fstab */ if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root"))) { - parse_opts (xstrdup (fstab->mnt_opts), &flags, &extra_opts); + parse_opts (xstrdup (fstab->m.mnt_opts), &flags, &extra_opts); mnt.mnt_dir = "/"; - mnt.mnt_fsname = canonicalize (fstab->mnt_fsname); - mnt.mnt_type = fstab->mnt_type; + mnt.mnt_fsname = canonicalize (fstab->m.mnt_fsname); + mnt.mnt_type = fstab->m.mnt_type; mnt.mnt_opts = fix_opts_string (flags, extra_opts, NULL); mnt.mnt_freq = mnt.mnt_passno = 0; @@ -424,6 +466,9 @@ guess_fstype_and_mount (char *spec, char *node, char **type, if (*type && strcasecmp (*type, "auto") == 0) *type = NULL; + if (!*type && (flags & MS_BIND)) + *type = "none"; /* random, but not "bind" */ + if (!*type && !(flags & MS_REMOUNT)) { *type = guess_fstype_from_superblock(spec); if (*type && !strcmp(*type, "swap")) { @@ -547,21 +592,19 @@ loop_check(char **spec, char **type, int *flags, static void update_mtab_entry(char *spec, char *node, char *type, char *opts, int flags, int freq, int pass) { - struct mntentchn mcn; struct mntent mnt; - mcn.mnt_fsname = mnt.mnt_fsname = canonicalize (spec); - mcn.mnt_dir = mnt.mnt_dir = canonicalize (node); - mcn.mnt_type = mnt.mnt_type = type; - mcn.mnt_opts = mnt.mnt_opts = opts; - mcn.nxt = 0; + mnt.mnt_fsname = canonicalize (spec); + mnt.mnt_dir = canonicalize (node); + mnt.mnt_type = type; + mnt.mnt_opts = opts; mnt.mnt_freq = freq; mnt.mnt_passno = pass; /* We get chatty now rather than after the update to mtab since the mount succeeded, even if the write to /etc/mtab should fail. */ if (verbose) - print_one (&mcn); + print_one (&mnt); if (!nomtab && mtab_is_writable()) { if (flags & MS_REMOUNT) @@ -610,6 +653,8 @@ cdrom_setspeed(char *spec) { * If there is a special mount program for this type, exec it. * returns: 0: no exec was done, 1: exec was done, status has result */ +#define ALWAYS_STAT + static int check_special_mountprog(char *spec, char *node, char *type, int flags, char *extra_opts, int *status) { @@ -708,9 +753,15 @@ try_mount_one (const char *spec0, const char *node0, char *type0, if (opt_speed) cdrom_setspeed(spec); - res = loop_check (&spec, &type, &flags, &loop, &loopdev, &loopfile); - if (res) + if (!(flags & MS_REMOUNT)) { + /* don't set up a (new) loop device if we only remount - this left + * stale assignments of files to loop devices. Nasty when used for + * encryption. + */ + res = loop_check (&spec, &type, &flags, &loop, &loopdev, &loopfile); + if (res) return res; + } /* * Call mount.TYPE for types that require a separate mount program. @@ -836,6 +887,7 @@ retry_nfs: case EINVAL: { int fd; long size; + int warned=0; if (flags & MS_REMOUNT) { error (_("mount: %s not mounted already, or bad option"), node); @@ -846,10 +898,29 @@ retry_nfs: if (stat (spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode) && (fd = open(spec, O_RDONLY | O_NONBLOCK)) >= 0) { - if(ioctl(fd, BLKGETSIZE, &size) == 0 && size <= 2) + if(ioctl(fd, BLKGETSIZE, &size) == 0) { + if (size == 0) { + warned++; + error (" (could this be the IDE device where you in fact use\n" + " ide-scsi so that sr0 or sda or so is needed?)"); + } + if (size && size <= 2) { + warned++; error (" (aren't you trying to mount an extended partition,\n" " instead of some logical partition inside?)"); + } close(fd); + } +#if 0 + /* 0xf for SCSI, 0x3f for IDE. One might check /proc/partitions + to see whether this thing really is partitioned. + Do not suggest partitions for /dev/fd0. */ + if (!warned && (statbuf.st_rdev & 0xf) == 0) { + warned++; + error (" (could this be the whole disk device\n" + " where you need a partition?)"); + } +#endif } } break; @@ -859,9 +930,10 @@ retry_nfs: case EIO: error (_("mount: %s: can't read superblock"), spec); break; case ENODEV: - if (is_in_procfs(type) || !strcmp(type, "guess")) - error(_("mount: %s has wrong major or minor number"), spec); - else if (have_procfs()) { + { int pfs; + if ((pfs = is_in_procfs(type)) == 1 || !strcmp(type, "guess")) + error(_("mount: %s: unknown device"), spec); + else if (pfs == 0) { char *lowtype, *p; int u; @@ -876,15 +948,16 @@ retry_nfs: u++; } } - if (u && is_in_procfs(lowtype)) + if (u && is_in_procfs(lowtype) == 1) error (_("mount: probably you meant %s"), lowtype); - else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660")) + else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660") == 1) error (_("mount: maybe you meant iso9660 ?")); free(lowtype); } else error (_("mount: %s has wrong device number or fs type %s not supported"), spec, type); break; + } case ENOTBLK: if (stat (spec, &statbuf)) /* strange ... */ error (_("mount: %s is not a block device, and stat fails?"), spec); @@ -902,8 +975,8 @@ retry_nfs: case EACCES: /* pre-linux 1.1.38, 1.1.41 and later */ case EROFS: /* linux 1.1.38 and later */ { char *bd = (loop ? "" : _("block device ")); - if (ro) { - error (_("mount: %s%s is not permitted on its filesystem"), + if (ro || (flags & MS_RDONLY)) { + error (_("mount: cannot mount %s%s read-only"), bd, spec); break; } else if (readwrite) { @@ -1011,15 +1084,15 @@ mount_one (const char *spec, const char *node, char *type, const char *opts, if (specset) { if (nspec) { spec = nspec; - if (verbose) - printf(_("mount: consider mounting %s by %s\n"), spec, + if (verbose > 1) + printf(_("mount: going to mount %s by %s\n"), spec, (specset==1) ? _("UUID") : _("label")); } else if(!all) die (EX_USAGE, _("mount: no such partition found")); /* if -a then we may be rescued by a noauto option */ } - if (type == NULL) { + if (type == NULL && !bind) { if (strchr (spec, ':') != NULL) { type = "nfs"; if (verbose) @@ -1057,7 +1130,7 @@ mount_one (const char *spec, const char *node, char *type, const char *opts, /* Check if an fsname/dir pair was already in the old mtab. */ static int mounted (char *spec, char *node) { - struct mntentchn *mc; + struct mntentchn *mc, *mc0; char *nspec = NULL; if (!strncmp(spec, "UUID=", 5)) @@ -1071,8 +1144,9 @@ mounted (char *spec, char *node) { spec = canonicalize (spec); node = canonicalize (node); - for (mc = mtab_head()->nxt; mc; mc = mc->nxt) - if (streq (spec, mc->mnt_fsname) && streq (node, mc->mnt_dir)) + mc0 = mtab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) + if (streq (spec, mc->m.mnt_fsname) && streq (node, mc->m.mnt_dir)) return 1; return 0; } @@ -1085,7 +1159,7 @@ mounted (char *spec, char *node) { static int mount_all (string_list types, char *options) { - struct mntentchn *mc, *mtmp; + struct mntentchn *mc, *mc0, *mtmp; int status = 0; struct stat statbuf; struct child { @@ -1102,28 +1176,29 @@ mount_all (string_list types, char *options) { several chains, one for each major or NFS host */ childhead.nxt = 0; childtail = &childhead; - for (mc = fstab_head()->nxt; mc; mc = mc->nxt) { - if (matching_type (mc->mnt_type, types) - && !streq (mc->mnt_dir, "/") - && !streq (mc->mnt_dir, "root")) { - if (mounted (mc->mnt_fsname, mc->mnt_dir)) { + mc0 = fstab_head(); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) { + if (matching_type (mc->m.mnt_type, types) + && !streq (mc->m.mnt_dir, "/") + && !streq (mc->m.mnt_dir, "root")) { + if (mounted (mc->m.mnt_fsname, mc->m.mnt_dir)) { if (verbose) printf(_("mount: %s already mounted on %s\n"), - mc->mnt_fsname, mc->mnt_dir); + mc->m.mnt_fsname, mc->m.mnt_dir); } else { mtmp = (struct mntentchn *) xmalloc(sizeof(*mtmp)); *mtmp = *mc; mtmp->nxt = 0; g = NULL; if (optfork) { - if (stat(mc->mnt_fsname, &statbuf) == 0 && + if (stat(mc->m.mnt_fsname, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) { sprintf(major, "#%x", DISKMAJOR(statbuf.st_rdev)); g = major; } #ifdef HAVE_NFS - if (strcmp(mc->mnt_type, "nfs") == 0) { - g = xstrdup(mc->mnt_fsname); + if (strcmp(mc->m.mnt_type, "nfs") == 0) { + g = xstrdup(mc->m.mnt_fsname); colon = strchr(g, ':'); if (colon) *colon = '\0'; @@ -1166,8 +1241,8 @@ mount_all (string_list types, char *options) { /* if child, or not forked, do the mounting */ if (p == 0 || p == -1) { for (mc = cp->mec; mc; mc = mc->nxt) - status |= mount_one (mc->mnt_fsname, mc->mnt_dir, - mc->mnt_type, mc->mnt_opts, + status |= mount_one (mc->m.mnt_fsname, mc->m.mnt_dir, + mc->m.mnt_type, mc->m.mnt_opts, options, 0, 0); if (mountcount) status |= EX_SOMEOK; @@ -1198,222 +1273,271 @@ mount_all (string_list types, char *options) { } extern char version[]; -static struct option longopts[] = -{ - { "all", 0, 0, 'a' }, - { "fake", 0, 0, 'f' }, - { "fork", 0, 0, 'F' }, - { "help", 0, 0, 'h' }, - { "no-mtab", 0, 0, 'n' }, - { "read-only", 0, 0, 'r' }, - { "ro", 0, 0, 'r' }, - { "verbose", 0, 0, 'v' }, - { "version", 0, 0, 'V' }, - { "read-write", 0, 0, 'w' }, - { "rw", 0, 0, 'w' }, - { "options", 1, 0, 'o' }, - { "types", 1, 0, 't' }, - { NULL, 0, 0, 0 } +static struct option longopts[] = { + { "all", 0, 0, 'a' }, + { "fake", 0, 0, 'f' }, + { "fork", 0, 0, 'F' }, + { "help", 0, 0, 'h' }, + { "no-mtab", 0, 0, 'n' }, + { "read-only", 0, 0, 'r' }, + { "ro", 0, 0, 'r' }, + { "verbose", 0, 0, 'v' }, + { "version", 0, 0, 'V' }, + { "read-write", 0, 0, 'w' }, + { "rw", 0, 0, 'w' }, + { "options", 1, 0, 'o' }, + { "types", 1, 0, 't' }, + { "bind", 0, 0, 128 }, + { "replace", 0, 0, 129 }, + { "after", 0, 0, 130 }, + { "before", 0, 0, 131 }, + { "over", 0, 0, 132 }, + { NULL, 0, 0, 0 } }; +/* Keep the usage message at max 22 lines, each at most 70 chars long. + The user should not need a pager to read it. */ static void -usage (FILE *fp, int n) -{ - fprintf (fp, _("Usage: mount [-lhV]\n" - " mount -a [-nfFrsvw] [-t vfstypes]\n" - " mount [-nfrsvw] [-o options] special | node\n" - " mount [-nfrsvw] [-t vfstype] [-o options] special node\n" - " A special device can be indicated by -L label or -U uuid .\n")); - unlock_mtab(); - exit (n); +usage (FILE *fp, int n) { + fprintf(fp, _( + "Usage: mount -V : print version\n" + " mount -h : print this help\n" + " mount : list mounted filesystems\n" + " mount -l : idem, including volume labels\n" + "So far the informational part. Next the mounting.\n" + "The command is `mount [-t fstype] something somewhere'.\n" + "Details found in /etc/fstab may be omitted.\n" + " mount -a : mount all stuff from /etc/fstab\n" + " mount device : mount device at the known place\n" + " mount directory : mount known device here\n" + " mount -t type dev dir : ordinary mount command\n" + "Note that one does not really mount a device, one mounts\n" + "a filesystem (of the given type) found on the device.\n" + "One can also mount an already visible directory tree elsewhere:\n" + " mount --bind olddir newdir\n" + "A device can be given by name, say /dev/hda1 or /dev/cdrom,\n" + "or by label, using -L label or by uuid, using -U uuid .\n" + "Union or stack mounts are specified using one of\n" + " --replace, --after, --before, --over\n" + "Other options: [-nfFrsvw] [-o options].\n" + "For many more details, say man 8 mount .\n" + )); + unlock_mtab(); + exit (n); } int main (int argc, char *argv[]) { - int c, result = 0, specseen; - char *options = NULL, *spec, *node; - char *volumelabel = NULL; - char *uuid = NULL; - string_list types = NULL; - struct mntentchn *mc; - int fd; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - /* People report that a mount called from init without console - writes error messages to /etc/mtab - Let us try to avoid getting fd's 0,1,2 */ - while((fd = open("/dev/null", O_RDWR)) == 0 || fd == 1 || fd == 2) ; - if (fd > 2) - close(fd); + int c, result = 0, specseen; + char *options = NULL, *spec, *node; + char *volumelabel = NULL; + char *uuid = NULL; + string_list types = NULL; + struct mntentchn *mc; + int fd; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* People report that a mount called from init without console + writes error messages to /etc/mtab + Let us try to avoid getting fd's 0,1,2 */ + while((fd = open("/dev/null", O_RDWR)) == 0 || fd == 1 || fd == 2) ; + if (fd > 2) + close(fd); #ifdef DO_PS_FIDDLING - initproctitle(argc, argv); + initproctitle(argc, argv); #endif - while ((c = getopt_long (argc, argv, "afFhlL:no:rsU:vVwt:", longopts, NULL)) - != EOF) - switch (c) { - case 'a': /* mount everything in fstab */ - ++all; - break; - case 'f': /* fake (don't actually do mount(2) call) */ - ++fake; - break; - case 'F': - ++optfork; - break; - case 'h': /* help */ - usage (stdout, 0); - break; - case 'l': - list_with_volumelabel = 1; - break; - case 'L': - volumelabel = optarg; - break; - case 'n': /* mount without writing in /etc/mtab */ - ++nomtab; - break; - case 'o': /* specify mount options */ - if (options) - options = xstrconcat3(options, ",", optarg); - else - options = xstrdup(optarg); - break; - case 'r': /* mount readonly */ - readonly = 1; - readwrite = 0; - break; - case 's': /* allow sloppy mount options */ - sloppy = 1; - break; - case 't': /* specify file system types */ - types = parse_list (optarg); - break; - case 'U': - uuid = optarg; - break; - case 'v': /* be chatty - very chatty if repeated */ - ++verbose; - break; - case 'V': /* version */ - printf ("mount: %s\n", version); - exit (0); - case 'w': /* mount read/write */ - readwrite = 1; - readonly = 0; - break; - case 0: - break; - case '?': - default: - usage (stderr, EX_USAGE); - } - - argc -= optind; - argv += optind; - - specseen = (uuid || volumelabel) ? 1 : 0; /* yes, .. i know */ + while ((c = getopt_long (argc, argv, "afFhlL:no:rsU:vVwt:", + longopts, NULL)) != EOF) { + switch (c) { + case 'a': /* mount everything in fstab */ + ++all; + break; + case 'f': /* fake: don't actually call mount(2) */ + ++fake; + break; + case 'F': + ++optfork; + break; + case 'h': /* help */ + usage (stdout, 0); + break; + case 'l': + list_with_volumelabel = 1; + break; + case 'L': + volumelabel = optarg; + break; + case 'n': /* do not write /etc/mtab */ + ++nomtab; + break; + case 'o': /* specify mount options */ + if (options) + options = xstrconcat3(options, ",", optarg); + else + options = xstrdup(optarg); + break; + case 'r': /* mount readonly */ + readonly = 1; + readwrite = 0; + break; + case 's': /* allow sloppy mount options */ + sloppy = 1; + break; + case 't': /* specify file system types */ + types = parse_list (optarg); + break; + case 'U': + uuid = optarg; + break; + case 'v': /* be chatty - more so if repeated */ + ++verbose; + break; + case 'V': /* version */ + printf ("mount: %s\n", version); + exit (0); + case 'w': /* mount read/write */ + readwrite = 1; + readonly = 0; + break; + case 0: + break; + + case 128: /* bind */ + ++bind; + break; + case 129: /* replace */ + mounttype = MS_REPLACE; + break; + case 130: /* after */ + mounttype = MS_AFTER; + break; + case 131: /* before */ + mounttype = MS_BEFORE; + break; + case 132: /* over */ + mounttype = MS_OVER; + break; + + case '?': + default: + usage (stderr, EX_USAGE); + } + } - if (argc+specseen == 0 && !all) { - if (options) - usage (stderr, EX_USAGE); - return print_all (types); - } + argc -= optind; + argv += optind; - if (getuid () != geteuid ()) { - suid = 1; - if (types || options || readwrite || nomtab || all || fake || - (argc + specseen) != 1) - die (EX_USAGE, _("mount: only root can do that")); - } + specseen = (uuid || volumelabel) ? 1 : 0; /* yes, .. i know */ - if (!nomtab && mtab_does_not_exist()) { - if (verbose > 1) - printf(_("mount: no %s found - creating it..\n"), MOUNTED); - create_mtab (); - } + if (argc+specseen == 0 && !all) { + if (options || mounttype || bind) + usage (stderr, EX_USAGE); + return print_all (types); + } - if (specseen) { - if (uuid) - spec = get_spec_by_uuid(uuid); - else - spec = get_spec_by_volume_label(volumelabel); - if (!spec) - die (EX_USAGE, _("mount: no such partition found")); - if (verbose) - printf(_("mount: mounting %s\n"), spec); - } else - spec = NULL; /* just for gcc */ - - switch (argc+specseen) { - case 0: - /* mount -a */ - result = mount_all (types, options); - if (result == 0 && verbose) - error(_("not mounted anything")); - break; + if (getuid () != geteuid ()) { + suid = 1; + if (types || options || readwrite || nomtab || all || fake || + bind || mounttype || (argc + specseen) != 1) + die (EX_USAGE, _("mount: only root can do that")); + } - case 1: - /* mount [-nfrvw] [-o options] special | node */ - if (types != NULL) - usage (stderr, EX_USAGE); - if (specseen) { - /* We know the device. Where shall we mount it? */ - mc = (uuid ? getfsuuidspec (uuid) : getfsvolspec (volumelabel)); - if (mc == NULL) - mc = getfsspec (spec); - if (mc == NULL) - die (EX_USAGE, _("mount: cannot find %s in %s"), - spec, _PATH_FSTAB); - mc->mnt_fsname = spec; - } else { - /* Try to find the other pathname in fstab. */ - spec = canonicalize (*argv); - if ((mc = getfsspec (spec)) == NULL && - (mc = getfsfile (spec)) == NULL && - /* Try noncanonical name in fstab - perhaps /dev/cdrom or /dos is a symlink */ - (mc = getfsspec (*argv)) == NULL && - (mc = getfsfile (*argv)) == NULL && - /* Try mtab - maybe this was a remount */ - (mc = getmntfile (spec)) == NULL) - die (EX_USAGE, _("mount: can't find %s in %s or %s"), - spec, _PATH_FSTAB, MOUNTED); - /* Earlier mtab was tried first, but this would - sometimes try the wrong mount in case mtab had - the root device entry wrong. */ - } + if (!nomtab && mtab_does_not_exist()) { + if (verbose > 1) + printf(_("mount: no %s found - creating it..\n"), + MOUNTED); + create_mtab (); + } - result = mount_one (xstrdup (mc->mnt_fsname), xstrdup (mc->mnt_dir), - xstrdup (mc->mnt_type), mc->mnt_opts, options, 0, 0); - break; + if (specseen) { + if (uuid) + spec = get_spec_by_uuid(uuid); + else + spec = get_spec_by_volume_label(volumelabel); + if (!spec) + die (EX_USAGE, _("mount: no such partition found")); + if (verbose) + printf(_("mount: mounting %s\n"), spec); + } else + spec = NULL; /* just for gcc */ + + switch (argc+specseen) { + case 0: + /* mount -a */ + result = mount_all (types, options); + if (result == 0 && verbose) + error(_("not mounted anything")); + break; + + case 1: + /* mount [-nfrvw] [-o options] special | node */ + if (types != NULL) + usage (stderr, EX_USAGE); + if (specseen) { + /* We know the device. Where shall we mount it? */ + mc = (uuid ? getfsuuidspec (uuid) + : getfsvolspec (volumelabel)); + if (mc == NULL) + mc = getfsspec (spec); + if (mc == NULL) + die (EX_USAGE, + _("mount: cannot find %s in %s"), + spec, _PATH_FSTAB); + mc->m.mnt_fsname = spec; + } else { + /* Try to find the other pathname in fstab. */ + spec = canonicalize (*argv); + if ((mc = getfsspec (spec)) == NULL && + (mc = getfsfile (spec)) == NULL && + /* Try noncanonical name in fstab + perhaps /dev/cdrom or /dos is a symlink */ + (mc = getfsspec (*argv)) == NULL && + (mc = getfsfile (*argv)) == NULL && + /* Try mtab - maybe this was a remount */ + (mc = getmntfile (spec)) == NULL) + die (EX_USAGE, + _("mount: can't find %s in %s or %s"), + spec, _PATH_FSTAB, MOUNTED); + /* Earlier mtab was tried first, but this would + sometimes try the wrong mount in case mtab had + the root device entry wrong. */ + } - case 2: - /* mount [-nfrvw] [-t vfstype] [-o options] special node */ - if (specseen) { - /* we have spec already */ - node = argv[0]; - } else { - spec = argv[0]; - node = argv[1]; - } - if (types == NULL) - result = mount_one (spec, node, NULL, NULL, options, 0, 0); - else if (cdr (types) == NULL) - result = mount_one (spec, node, car (types), NULL, options, 0, 0); - else - usage (stderr, EX_USAGE); - break; + result = mount_one (xstrdup (mc->m.mnt_fsname), + xstrdup (mc->m.mnt_dir), + xstrdup (mc->m.mnt_type), + mc->m.mnt_opts, options, 0, 0); + break; + + case 2: + /* mount [-nfrvw] [-t vfstype] [-o options] special node */ + if (specseen) { + /* we have spec already */ + node = argv[0]; + } else { + spec = argv[0]; + node = argv[1]; + } + if (types == NULL) + result = mount_one (spec, node, NULL, NULL, + options, 0, 0); + else if (cdr (types) == NULL) + result = mount_one (spec, node, car (types), NULL, + options, 0, 0); + else + usage (stderr, EX_USAGE); + break; - default: - usage (stderr, EX_USAGE); - } + default: + usage (stderr, EX_USAGE); + } - if (result == EX_SOMEOK) - result = 0; - exit (result); + if (result == EX_SOMEOK) + result = 0; + exit (result); } diff --git a/mount/mount_by_label.c b/mount/mount_by_label.c index 1567bfb18..e24d880d2 100644 --- a/mount/mount_by_label.c +++ b/mount/mount_by_label.c @@ -7,6 +7,8 @@ * - Added error message if /proc/partitions cannot be opened * 2000-05-09 Erik Troan * - Added cache for UUID and disk labels + * 2000-11-07 Nathan Scott + * - Added XFS support */ #include @@ -29,33 +31,44 @@ static struct uuidCache_s { char *device; } *uuidCache = NULL; -/* for now, only ext2 is supported */ +/* for now, only ext2 and xfs are supported */ static int get_label_uuid(const char *device, char **label, char *uuid) { - /* start with a test for ext2, taken from mount_guess_fstype */ + /* start with ext2 and xfs tests, taken from mount_guess_fstype */ /* should merge these later */ int fd; + int rv = 1; + size_t namesize; struct ext2_super_block e2sb; + struct xfs_super_block xfsb; fd = open(device, O_RDONLY); if (fd < 0) - return 1; - - if (lseek(fd, 1024, SEEK_SET) != 1024 - || read(fd, (char *) &e2sb, sizeof(e2sb)) != sizeof(e2sb) - || (ext2magic(e2sb) != EXT2_SUPER_MAGIC)) { - close(fd); - return 1; + return rv; + + if (lseek(fd, 1024, SEEK_SET) == 1024 + && read(fd, (char *) &e2sb, sizeof(e2sb)) == sizeof(e2sb) + && (ext2magic(e2sb) == EXT2_SUPER_MAGIC)) { + memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid)); + namesize = sizeof(e2sb.s_volume_name); + if ((*label = calloc(namesize + 1, 1)) != NULL) + memcpy(*label, e2sb.s_volume_name, namesize); + rv = 0; + } + else if (lseek(fd, 0, SEEK_SET) == 0 + && read(fd, (char *) &xfsb, sizeof(xfsb)) == sizeof(xfsb) + && (strncmp((char *) &xfsb.s_magic, XFS_SUPER_MAGIC, 4) == 0 || + strncmp((char *) &xfsb.s_magic, XFS_SUPER_MAGIC2,4) == 0)) { + memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid)); + namesize = sizeof(xfsb.s_fname); + if ((*label = calloc(namesize + 1, 1)) != NULL) + memcpy(*label, xfsb.s_fname, namesize); + rv = 0; } close(fd); - - /* superblock is ext2 - now what is its label? */ - memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid)); - *label = strdup(e2sb.s_volume_name); - - return 0; + return rv; } static void @@ -91,8 +104,14 @@ uuidcache_init(void) { return; procpt = fopen(PROC_PARTITIONS, "r"); - if (!procpt) + if (!procpt) { + static int warn = 0; + if (!warn++) + error (_("mount: could not open %s, so UUID and LABEL " + "conversion cannot be done.\n"), + PROC_PARTITIONS); return; + } for (firstPass = 1; firstPass >= 0; firstPass--) { fseek(procpt, 0, SEEK_SET); diff --git a/mount/mount_constants.h b/mount/mount_constants.h index aeb7edfb3..5fd290829 100644 --- a/mount/mount_constants.h +++ b/mount/mount_constants.h @@ -19,12 +19,31 @@ #ifndef MS_MANDLOCK #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ #endif +#ifndef MS_ACTION_MASK +#define MS_ACTION_MASK 0x380 +/* Remount, but new filesystem may be different from old. Atomic + (i.e. there is no interval when nothing is mounted at the mountpoint). + If new fs differs from the old one and old is busy - -EBUSY. */ +#define MS_REPLACE 0x080 /* 128 */ +/* After, Before: as soon as we get unions these will add a new member + in the end or beginning of the chain. Fail if there is a stack + on the mountpoint. */ +#define MS_AFTER 0x100 /* 256 */ +#define MS_BEFORE 0x180 +/* Over: if nothing mounted on a mountpoint - same as if none of these +flags had been set; if we have a union with more than one element - fail; +if we have a stack or plain mount - mount atop of it, forming a stack. */ +#define MS_OVER 0x200 /* 512 */ +#endif #ifndef MS_NOATIME #define MS_NOATIME 1024 /* Do not update access times. */ #endif #ifndef MS_NODIRATIME #define MS_NODIRATIME 2048 /* Do not update directory access times */ #endif +#ifndef MS_BIND +#define MS_BIND 4096 +#endif /* * Magic mount flag number. Has to be or-ed to the flag values. */ diff --git a/mount/mount_guess_fstype.c b/mount/mount_guess_fstype.c index ec39c531a..5a3733f98 100644 --- a/mount/mount_guess_fstype.c +++ b/mount/mount_guess_fstype.c @@ -20,6 +20,9 @@ * 1999-02-22 Arkadiusz Mi¶kiewicz * - added Native Language Support * + * Fri Dec 1 23:31:00 2000: Sepp Wijnands + * added probes for cramfs, hfs, hpfs and adfs. + * * aeb - many changes. * */ @@ -63,24 +66,21 @@ swapped(unsigned short a) { Original routine by ; made into a function for mount(8) by Mike Grupenhoff . Read the superblock only once - aeb - Added a test for iso9660 - aeb + Added iso9660, romfs, qnx4, udf, swap - aeb Added a test for high sierra (iso9660) - quinlan@bucknell.edu Corrected the test for xiafs - aeb - Added romfs - aeb Added ufs from a patch by jj. But maybe there are several types of ufs? Added ntfs from a patch by Richard Russon. Added a very weak heuristic for vfat - aeb - Added qnx4 - aeb - Added swap - aeb Added xfs - 2000-03-21 Martin K. Petersen - - Currently supports: minix, ext, ext2, xiafs, iso9660, romfs, - ufs, ntfs, vfat, qnx4, bfs, xfs + Added cramfs, hfs, hpfs, adfs - Sepp Wijnands */ static char -*magic_known[] = { "minix", "ext", "ext2", "xiafs", "iso9660", "romfs", - "ufs", "ntfs", "qnx4", "bfs", "udf", "xfs", - "swap" /* last - just to warn the user */ +*magic_known[] = { + "adfs", "bfs", "cramfs", "ext", "ext2", + "hfs", "hpfs", "iso9660", "minix", "ntfs", + "qnx4", "romfs", "swap", "udf", "ufs", + "xfs", "xiafs" }; static int @@ -97,7 +97,6 @@ tested(const char *device) { causes a very large kernel delay, almost killing the machine. So, we do not try udf unless there is positive evidence that it might work. Try iso9660 first, it is much more likely. - Strings below taken from ECMA 167. */ static char *udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02", @@ -119,6 +118,20 @@ may_be_swap(const char *s) { strncmp(s-10, "SWAPSPACE2", 10) == 0); } +/* rather weak necessary condition */ +static int +may_be_adfs(const u_char *s) { + u_char *p; + int sum; + + p = (u_char *) s + 511; + sum = 0; + while(--p != s) + sum = (sum >> 8) + (sum & 0xff) + *p; + + return (sum == p[511]); +} + static char * fstype(const char *device) { int fd; @@ -131,17 +144,21 @@ fstype(const char *device) { union { struct xiafs_super_block xiasb; char romfs_magic[8]; - char xfs_magic[4]; char qnx4fs_magic[10]; /* ignore first 4 bytes */ long bfs_magic; struct ntfs_super_block ntfssb; struct fat_super_block fatsb; + struct xfs_super_block xfsb; + struct cramfs_super_block cramfssb; } xsb; struct ufs_super_block ufssb; union { struct iso_volume_descriptor iso; struct hs_volume_descriptor hs; } isosb; + struct hfs_super_block hfssb; + struct hpfs_super_block hpfssb; + struct adfs_super_block adfssb; struct stat statbuf; /* opening and reading an arbitrary unknown path can have @@ -164,7 +181,8 @@ fstype(const char *device) { type = "ext2"; else if (minixmagic(sb.ms) == MINIX_SUPER_MAGIC - || minixmagic(sb.ms) == MINIX_SUPER_MAGIC2) + || minixmagic(sb.ms) == MINIX_SUPER_MAGIC2 + || minixmagic(sb.ms) == swapped(MINIX_SUPER_MAGIC2)) type = "minix"; else if (extmagic(sb.es) == EXT_SUPER_MAGIC) @@ -179,8 +197,8 @@ fstype(const char *device) { type = "xiafs"; else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8)) type = "romfs"; - else if(!strncmp(xsb.xfs_magic, "XFSB", 4) || - !strncmp(xsb.xfs_magic, "BSFX", 4)) + else if(!strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC, 4) || + !strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC2, 4)) type = "xfs"; else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6)) type = "qnx4fs"; @@ -189,6 +207,8 @@ fstype(const char *device) { else if(!strncmp(xsb.ntfssb.s_magic, NTFS_SUPER_MAGIC, sizeof(xsb.ntfssb.s_magic))) type = "ntfs"; + else if(cramfsmagic(xsb.cramfssb) == CRAMFS_SUPER_MAGIC) + type = "cramfs"; else if ((!strncmp(xsb.fatsb.s_os, "MSDOS", 5) || !strncmp(xsb.fatsb.s_os, "MSWIN", 5) || !strncmp(xsb.fatsb.s_os, "MTOOL", 5) || @@ -221,6 +241,43 @@ fstype(const char *device) { type = "udf"; } + if (!type) { + if (lseek(fd, 0x400, SEEK_SET) != 0x400 + || read(fd, (char *) &hfssb, sizeof(hfssb)) != sizeof(hfssb)) + goto io_error; + + /* also check if block size is equal to 512 bytes, + since the hfs driver currently only has support + for block sizes of 512 bytes long, and to be + more accurate (sb magic is only a short int) */ + if ((hfsmagic(hfssb) == HFS_SUPER_MAGIC && + hfsblksize(hfssb) == 0x20000) || + (swapped(hfsmagic(hfssb)) == HFS_SUPER_MAGIC && + hfsblksize(hfssb) == 0x200)) + type = "hfs"; + } + + if (!type) { + if (lseek(fd, 0x2000, SEEK_SET) != 0x2000 + || read(fd, (char *) &hpfssb, sizeof(hpfssb)) != sizeof(hpfssb)) + goto io_error; + + if (hpfsmagic(hpfssb) == HPFS_SUPER_MAGIC) + type = "hpfs"; + } + + if (!type) { + if (lseek(fd, 0xc00, SEEK_SET) != 0xc00 + || read(fd, (char *) &adfssb, sizeof(adfssb)) != sizeof(adfssb)) + goto io_error; + + /* only a weak test */ + if (may_be_adfs((u_char *) &adfssb) + && (adfsblksize(adfssb) >= 8 && + adfsblksize(adfssb) <= 10)) + type = "adfs"; + } + if (!type) { /* perhaps the user tries to mount the swap space on a new disk; warn her before she does mke2fs on it */ @@ -267,46 +324,40 @@ guess_fstype_from_superblock(const char *spec) { return type; } -static FILE *procfs; - -static void -procfsclose(void) { - if (procfs) - fclose (procfs); - procfs = 0; -} - -static int -procfsopen(void) { - procfs = fopen(ETC_FILESYSTEMS, "r"); - if (!procfs) - procfs = fopen(PROC_FILESYSTEMS, "r"); - return (procfs != NULL); -} - static char * -procfsnext(void) { +procfsnext(FILE *procfs) { char line[100]; - static char fsname[100]; + char fsname[100]; while (fgets(line, sizeof(line), procfs)) { if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue; if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue; - return fsname; + return strdup(fsname); } return 0; } +/* Only use /proc/filesystems here, this is meant to test what + the kernel knows about, so /etc/filesystems is irrelevant. + Return: 1: yes, 0: no, -1: cannot open procfs */ int is_in_procfs(const char *type) { + FILE *procfs; char *fsname; - - if (procfsopen()) { - while ((fsname = procfsnext()) != NULL) - if (!strcmp(fsname, type)) - return 1; + int ret = -1; + + procfs = fopen(PROC_FILESYSTEMS, "r"); + if (procfs) { + ret = 0; + while ((fsname = procfsnext(procfs)) != NULL) + if (!strcmp(fsname, type)) { + ret = 1; + break; + } + fclose(procfs); + procfs = NULL; } - return 0; + return ret; } /* return: 0: OK, -1: error in errno, 1: type not found */ @@ -314,12 +365,20 @@ is_in_procfs(const char *type) { int procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, char **type) { + FILE *procfs; char *fsname; + int ret = 1; + int errsv = 0; *type = NULL; - if (!procfsopen()) - return 1; - while ((fsname = procfsnext()) != NULL) { + + procfs = fopen(ETC_FILESYSTEMS, "r"); + if (!procfs) { + procfs = fopen(PROC_FILESYSTEMS, "r"); + if (!procfs) + return 1; + } + while ((fsname = procfsnext(procfs)) != NULL) { if (tested (fsname)) continue; args->type = fsname; @@ -328,20 +387,17 @@ procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, fflush(stdout); } if ((*mount_fn) (args) == 0) { - *type = xstrdup(fsname); - procfsclose(); - return 0; - } else if (errno != EINVAL) { + *type = fsname; + ret = 0; + break; + } else if (errno != EINVAL && is_in_procfs(fsname) == 1) { *type = "guess"; - procfsclose(); - return -1; + ret = -1; + errsv = errno; + break; } } - procfsclose(); - return 1; -} - -int -have_procfs(void) { - return procfs != NULL; + fclose(procfs); + errno = errsv; + return ret; } diff --git a/mount/mount_guess_fstype.h b/mount/mount_guess_fstype.h index 3663f74ca..9c0903b54 100644 --- a/mount/mount_guess_fstype.h +++ b/mount/mount_guess_fstype.h @@ -12,4 +12,4 @@ char *guess_fstype_from_superblock(const char *device); int procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, char **type); int is_in_procfs(const char *fstype); -int have_procfs(void); + diff --git a/mount/mount_guess_rootdev.c b/mount/mount_guess_rootdev.c new file mode 100644 index 000000000..072c09fc4 --- /dev/null +++ b/mount/mount_guess_rootdev.c @@ -0,0 +1,90 @@ +/* + * Having the wrong rootdevice listed in mtab is slightly inconvenient. + * Try to guess what it could be... + * In case /proc/cmdline exists, and has the format + * stuff root=R more stuff... + * and we think we understand the number R, decode it as a root device. + * + * Another possibility: + * Erik Andersen writes: + * I did a similar find_real_root_device_name() in busybox some time back. + * Basically, do a stat("/", &rootstat) then walk /dev stat'ing each file + * and if (statbuf.st_rdev == rootstat.st_rdev) then you have a match. + * Works fine. + */ +#include +#include +#include "mount_guess_rootdev.h" + +#define PROC_CMDLINE "/proc/cmdline" + +static char * +rootdev(char *p) { + unsigned long devno; + char *ep; + char *type = "hd"; + char let; + int ma, mi; + char devname[8]; + + devno = strtoul(p, &ep, 16); + if ((ep == p+3 || ep == p+4) && (*ep == ' ' || *ep == 0)) { + ma = (devno >> 8); + mi = (devno & 0xff); + switch(ma) { + case 8: + type = "sd"; + let = 'a'+(mi/16); + mi = mi%16; + break; + case 3: + let = 'a'; break; + case 0x16: + let = 'c'; break; + case 0x21: + let = 'e'; break; + case 0x22: + let = 'g'; break; + case 0x38: + let = 'i'; break; + case 0x39: + let = 'k'; break; + default: + return NULL; + } + if (mi & 0x40) { + mi -= 0x40; + let++; + } + if (mi == 0) + sprintf(devname, "/dev/%s%c", type, let); + else + sprintf(devname, "/dev/%s%c%d", type, let, mi); + return strdup(devname); + } + return NULL; +} + +char * +mount_guess_rootdev() { + FILE *cf; + char line[1024]; + char *p; + + cf = fopen(PROC_CMDLINE, "r"); + if (cf && fgets(line, sizeof(line), cf)) { + for (p = line; *p; p++) + if (!strncmp(p, " root=", 6)) + return rootdev(p+6); + } + return NULL; +} + +#if 0 +main(){ + char *p = mount_guess_rootdev(); + if (!p) + p = "/dev/root"; + printf("%s\n", p); +} +#endif diff --git a/mount/mount_guess_rootdev.h b/mount/mount_guess_rootdev.h new file mode 100644 index 000000000..41b327037 --- /dev/null +++ b/mount/mount_guess_rootdev.h @@ -0,0 +1 @@ +extern char *mount_guess_rootdev(void); diff --git a/mount/nfs_mount4.h b/mount/nfs_mount4.h index 0e3b052bd..85650773a 100644 --- a/mount/nfs_mount4.h +++ b/mount/nfs_mount4.h @@ -50,4 +50,5 @@ struct nfs_mount_data { #define NFS_MOUNT_VER3 0x0080 /* 3 */ #define NFS_MOUNT_KERBEROS 0x0100 /* 3 */ #define NFS_MOUNT_NONLM 0x0200 /* 3 */ +#define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */ diff --git a/mount/nfsmount.c b/mount/nfsmount.c index bf4be6369..6fc917db5 100644 --- a/mount/nfsmount.c +++ b/mount/nfsmount.c @@ -58,6 +58,13 @@ #include "../defines.h" /* for HAVE_inet_aton */ +#ifndef NFS_PORT +#define NFS_PORT 2049 +#endif +#ifndef NFS_FHSIZE +#define NFS_FHSIZE 32 +#endif + static char *nfs_strerror(int stat); #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) @@ -90,7 +97,6 @@ int nfs_mount_version = NFS_MOUNT_VERSION; * and figure out what version the kernel expects. * * Variables: - * KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time * NFS_MOUNT_VERSION: these nfsmount sources at compile time * nfs_mount_version: version this source and running kernel can handle */ @@ -106,6 +112,10 @@ find_kernel_nfs_mount_version(void) { if (kernel_version) { if (kernel_version < MAKE_VERSION(2,1,32)) nfs_mount_version = 1; + else if (kernel_version < MAKE_VERSION(2,2,18)) + nfs_mount_version = 3; + else if (kernel_version < MAKE_VERSION(2,3,0)) + nfs_mount_version = 4; /* since 2.2.18pre9 */ else if (kernel_version < MAKE_VERSION(2,3,99)) nfs_mount_version = 3; else @@ -201,6 +211,7 @@ int nfsmount(const char *spec, const char *node, int *flags, int nocto; int noac; int nolock; + int broken_suid; int retry; int tcp; int mountprog; @@ -297,6 +308,7 @@ int nfsmount(const char *spec, const char *node, int *flags, posix = 0; nocto = 0; nolock = 0; + broken_suid = 0; noac = 0; retry = 10000; /* 10000 minutes ~ 1 week */ tcp = 0; @@ -407,6 +419,8 @@ int nfsmount(const char *spec, const char *node, int *flags, nolock = !val; else printf(_("Warning: option nolock is not supported.\n")); + } else if (!strcmp(opt, "broken_suid")) { + broken_suid = val; } else { if (!sloppy) { printf(_("unknown nfs mount option: " @@ -430,6 +444,10 @@ int nfsmount(const char *spec, const char *node, int *flags, #if NFS_MOUNT_VERSION >= 3 if (nfs_mount_version >= 3) data.flags |= (nolock ? NFS_MOUNT_NONLM : 0); +#endif +#if NFS_MOUNT_VERSION >= 4 + if (nfs_mount_version >= 4) + data.flags |= (broken_suid ? NFS_MOUNT_BROKEN_SUID : 0); #endif if (nfsvers > MAX_NFSPROT) { fprintf(stderr, "NFSv%d not supported!\n", nfsvers); diff --git a/mount/pivot_root.c b/mount/pivot_root.c index 4ab8be853..fd4bef9df 100644 --- a/mount/pivot_root.c +++ b/mount/pivot_root.c @@ -6,7 +6,7 @@ #include #include - +static _syscall2(int,pivot_root,const char *,new_root,const char *,put_old) diff --git a/mount/umount.8 b/mount/umount.8 index 08d39888d..0b67314c5 100644 --- a/mount/umount.8 +++ b/mount/umount.8 @@ -67,6 +67,10 @@ Unmount without writing in .B \-r In case unmounting fails, try to remount read-only. .TP +.B \-d +In case the unmounted device was a loop device, also +free this loop device. +.TP .B \-a All of the file systems described in .I /etc/mtab @@ -92,7 +96,8 @@ The .B umount command will free the loop device (if any) associated with the mount, in case it finds the option `loop=...' in -.IR /etc/mtab . +.IR /etc/mtab , +or when the \-d option was given. Any pending loop devices can be freed using `losetup -d', see .BR losetup (8). diff --git a/mount/umount.c b/mount/umount.c index 98a1d330a..24622bc98 100644 --- a/mount/umount.c +++ b/mount/umount.c @@ -16,18 +16,21 @@ * 960223: aeb - several minor changes * 960324: aeb - added some changes from Rob Leslie * 960823: aeb - also try umount(spec) when umount(node) fails - * 970307: aeb - canonise names from fstab + * 970307: aeb - canonicalise names from fstab * 970726: aeb - remount read-only in cases where umount fails * 980810: aeb - umount2 support * 981222: aeb - If mount point or special file occurs several times * in mtab, try them all, with last one tried first * - Differentiate "user" and "users" key words in fstab + * 001202: aeb - remove at most one line from /etc/mtab */ +#include #include #include #include #include +#include #include #include #include "mount_constants.h" @@ -88,7 +91,10 @@ int remount = 0; /* Don't write a entry in /etc/mtab (-n). */ int nomtab = 0; -/* Nonzero for chatty (-v). This is a nonstandard flag (not in BSD). */ +/* Call losetup -d for each unmounted loop device. */ +int delloop = 0; + +/* Nonzero for chatty (-v). */ int verbose = 0; /* True if ruid != euid. */ @@ -107,6 +113,7 @@ nfs_umount_rpc_call(const char *spec, const char *opts) struct sockaddr_in saddr; struct timeval pertry, try; enum clnt_stat clnt_stat; + int port = 0; int so = RPC_ANYSOCK; struct hostent *hostp; char *hostname; @@ -131,6 +138,9 @@ nfs_umount_rpc_call(const char *spec, const char *opts) hostname = xstrndup(p,q-p); } + if (opts && (p = strstr(opts, "mountport=")) && isdigit(*(p+10))) + port = atoi(p+10); + if (hostname[0] >= '0' && hostname[0] <= '9') saddr.sin_addr.s_addr = inet_addr(hostname); else { @@ -147,7 +157,7 @@ nfs_umount_rpc_call(const char *spec, const char *opts) } saddr.sin_family = AF_INET; - saddr.sin_port = 0; + saddr.sin_port = htons(port); pertry.tv_sec = 3; pertry.tv_usec = 0; if ((clp = clntudp_create(&saddr, MOUNTPROG, MOUNTVERS, @@ -202,134 +212,147 @@ static void complain(int err, const char *dev) { on a non-fatal error. We lock/unlock around each umount. */ static int umount_one (const char *spec, const char *node, const char *type, - const char *opts, struct mntentchn *mc) -{ - int umnt_err, umnt_err2; - int isroot; - int res; - - /* Special case for root. As of 0.99pl10 we can (almost) unmount root; - the kernel will remount it readonly so that we can carry on running - afterwards. The readonly remount is illegal if any files are opened - for writing at the time, so we can't update mtab for an unmount of - root. As it is only really a remount, this doesn't matter too - much. [sct May 29, 1993] */ - isroot = (streq (node, "/") || streq (node, "root") - || streq (node, "rootfs")); - if (isroot) - nomtab++; + const char *opts, struct mntentchn *mc) { + int umnt_err, umnt_err2; + int isroot; + int res; + const char *loopdev; + + /* Special case for root. As of 0.99pl10 we can (almost) unmount root; + the kernel will remount it readonly so that we can carry on running + afterwards. The readonly remount is illegal if any files are opened + for writing at the time, so we can't update mtab for an unmount of + root. As it is only really a remount, this doesn't matter too + much. [sct May 29, 1993] */ + isroot = (streq (node, "/") || streq (node, "root") + || streq (node, "rootfs")); + if (isroot) + nomtab++; #ifdef HAVE_NFS - /* Ignore any RPC errors, so that you can umount the filesystem - if the server is down. */ - if (strcasecmp(type, "nfs") == 0) - nfs_umount_rpc_call(spec, opts); + /* Ignore any RPC errors, so that you can umount the filesystem + if the server is down. */ + if (strcasecmp(type, "nfs") == 0) + nfs_umount_rpc_call(spec, opts); #endif - umnt_err = umnt_err2 = 0; - if (force) { - /* completely untested - 2.1.116 only has some support in nfs case */ - /* probably this won't work */ - int flags = MNT_FORCE; - - res = umount2 (node, flags); - if (res == -1) { - perror("umount2"); - if (errno == ENOSYS) { - if (verbose) - printf(_("no umount2, trying umount...\n")); - res = umount (node); - } - } - } else - res = umount (node); - if (res < 0) { - umnt_err = errno; - /* A device might have been mounted on a node that has since - been deleted or renamed, so if node fails, also try spec. */ - /* if (umnt_err == ENOENT || umnt_err == EINVAL) */ - if (umnt_err != EBUSY && strcmp(node, spec)) { - if (verbose) - printf (_("could not umount %s - trying %s instead\n"), - node, spec); - res = umount (spec); - if (res < 0) - umnt_err2 = errno; - /* Do not complain about remote NFS mount points */ - if (errno == ENOENT && index(spec, ':')) - umnt_err2 = 0; - } - } - - if (res < 0 && remount && (umnt_err == EBUSY || umnt_err2 == EBUSY)) { - /* Umount failed - let us try a remount */ - res=mount(spec, node, NULL, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); - if (res == 0) { - struct mntent remnt; - fprintf(stderr, _("umount: %s busy - remounted read-only\n"), spec); - remnt.mnt_type = remnt.mnt_fsname = NULL; - remnt.mnt_dir = xstrdup(node); - remnt.mnt_opts = "ro"; - update_mtab(node, &remnt); - return 0; - } else if (errno != EBUSY) { /* hmm ... */ - perror("remount"); - fprintf(stderr, _("umount: could not remount %s read-only\n"), - spec); - } - } - - if (res >= 0) { - /* Umount succeeded, update mtab. */ - if (verbose) - printf (_("%s umounted\n"), spec); - - if (!nomtab && mtab_is_writable()) { - /* Special stuff for loop devices */ - if (mc) { - char *optl; - - /* old style mtab line? */ - if (streq(mc->mnt_type, "loop")) - if (del_loop(spec)) - goto fail; - - /* new style mtab line? */ - optl = mc->mnt_opts ? xstrdup(mc->mnt_opts) : ""; - for (optl = strtok (optl, ","); optl; optl = strtok (NULL, ",")) { - if (!strncmp(optl, "loop=", 5)) { - if (del_loop(optl+5)) - goto fail; - break; - } - } - } else { - /* maybe spec is a loop device? */ - /* no del_loop() - just delete it from mtab */ - if ((mc = getmntoptfile (spec)) != NULL) - node = mc->mnt_dir; - } - - /* Non-loop stuff */ - update_mtab (node, NULL); - } - return 0; - } - -fail: - /* Umount or del_loop failed, complain, but don't die. */ - if (!nomtab) { - /* remove obsolete entry */ - if (umnt_err == EINVAL || umnt_err == ENOENT) - update_mtab (node, NULL); - } + umnt_err = umnt_err2 = 0; + if (force) { + /* completely untested; + 2.1.116 only has some support in nfs case */ + /* probably this won't work */ + int flags = MNT_FORCE; + + res = umount2 (node, flags); + if (res == -1) { + perror("umount2"); + if (errno == ENOSYS) { + if (verbose) + printf(_("no umount2, trying umount...\n")); + res = umount (node); + } + } + } else + res = umount (node); + + if (res < 0) { + umnt_err = errno; + /* A device might have been mounted on a node that has since + been deleted or renamed, so if node fails, also try spec. */ + /* Note that this is incorrect in case spec was mounted + several times. */ + /* if (umnt_err == ENOENT || umnt_err == EINVAL) */ + if (umnt_err != EBUSY && strcmp(node, spec)) { + if (verbose) + printf (_("could not umount %s - trying %s instead\n"), + node, spec); + res = umount (spec); + if (res < 0) + umnt_err2 = errno; + /* Do not complain about remote NFS mount points */ + if (errno == ENOENT && index(spec, ':')) + umnt_err2 = 0; + } + } + + if (res < 0 && remount && (umnt_err == EBUSY || umnt_err2 == EBUSY)) { + /* Umount failed - let us try a remount */ + res = mount(spec, node, NULL, + MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); + if (res == 0) { + struct mntent remnt; + fprintf(stderr, + _("umount: %s busy - remounted read-only\n"), + spec); + remnt.mnt_type = remnt.mnt_fsname = NULL; + remnt.mnt_dir = xstrdup(node); + remnt.mnt_opts = "ro"; + update_mtab(node, &remnt); + return 0; + } else if (errno != EBUSY) { /* hmm ... */ + perror("remount"); + fprintf(stderr, + _("umount: could not remount %s read-only\n"), + spec); + } + } + + loopdev = 0; + if (res >= 0) { + /* Umount succeeded */ + if (verbose) + printf (_("%s umounted\n"), spec); + + /* Free any loop devices that we allocated ourselves */ + if (mc) { + char *optl; + + /* old style mtab line? */ + if (streq(mc->m.mnt_type, "loop")) { + loopdev = spec; + goto gotloop; + } + + /* new style mtab line? */ + optl = mc->m.mnt_opts ? xstrdup(mc->m.mnt_opts) : ""; + for (optl = strtok (optl, ","); optl; + optl = strtok (NULL, ",")) { + if (!strncmp(optl, "loop=", 5)) { + loopdev = optl+5; + goto gotloop; + } + } + } else { + /* + * If option "-o loop=spec" occurs in mtab, + * note the mount point, and delete mtab line. + */ + if ((mc = getmntoptfile (spec)) != NULL) + node = mc->m.mnt_dir; + } + + /* Also free loop devices when -d flag is given */ + if (delloop && is_loop_device(spec)) + loopdev = spec; + } + gotloop: + if (loopdev) + del_loop(loopdev); + + if (!nomtab && mtab_is_writable() && + (umnt_err == 0 || umnt_err == EINVAL || umnt_err == ENOENT)) { + update_mtab (node, NULL); + } + + if (res >= 0) + return 0; - if (umnt_err2) - complain(umnt_err2, spec); - if (umnt_err && umnt_err != umnt_err2) - complain(umnt_err, node); - return 1; + if (umnt_err2) + complain(umnt_err2, spec); + if (umnt_err && umnt_err != umnt_err2) + complain(umnt_err, node); + return 1; } /* @@ -347,8 +370,8 @@ umount_one_bw (const char *file, struct mntentchn *mc) { int res = 1; while (res && mc) { - res = umount_one(mc->mnt_fsname, mc->mnt_dir, - mc->mnt_type, mc->mnt_opts, mc); + res = umount_one(mc->m.mnt_fsname, mc->m.mnt_dir, + mc->m.mnt_type, mc->m.mnt_opts, mc); mc = getmntfilesbackward (file, mc); } return res; @@ -368,9 +391,9 @@ umount_all (string_list types) { if (!hd->prev) die (2, _("umount: cannot find list of filesystems to unmount")); for (mc = hd->prev; mc != hd; mc = mc->prev) { - if (matching_type (mc->mnt_type, types)) { - errors |= umount_one (mc->mnt_fsname, mc->mnt_dir, - mc->mnt_type, mc->mnt_opts, mc); + if (matching_type (mc->m.mnt_type, types)) { + errors |= umount_one (mc->m.mnt_fsname, mc->m.mnt_dir, + mc->m.mnt_type, mc->m.mnt_opts, mc); } } @@ -424,6 +447,10 @@ main (int argc, char *argv[]) case 'a': /* umount everything */ ++all; break; + /* fall through? */ + case 'd': /* do losetup -d for unmounted loop devices */ + ++delloop; + break; case 'f': /* force umount */ ++force; break; @@ -489,7 +516,7 @@ main (int argc, char *argv[]) then "mount /dev/sda4" followed by "umount /mnt/zip" used to fail. So, we must not look for file, but for the pair (spec,file) in fstab. */ - fs = getfsspecfile(mc->mnt_fsname, mc->mnt_dir); + fs = getfsspecfile(mc->m.mnt_fsname, mc->m.mnt_dir); if (!fs) { if (!getfsspec (file) && !getfsfile (file)) die (2, @@ -508,7 +535,7 @@ main (int argc, char *argv[]) /* The option `owner' only allows (un)mounting by the owner. */ /* A convenient side effect is that the user who mounted is visible in mtab. */ - options = parse_list (fs->mnt_opts); + options = parse_list (fs->m.mnt_opts); while (options) { if (streq (car (options), "user") || streq (car (options), "users") || @@ -518,18 +545,18 @@ main (int argc, char *argv[]) } if (!options) die (2, _("umount: only root can unmount %s from %s"), - fs->mnt_fsname, fs->mnt_dir); + fs->m.mnt_fsname, fs->m.mnt_dir); if (streq (car (options), "user") || streq (car (options), "owner")) { char *user = getusername(); - options = parse_list (mc->mnt_opts); + options = parse_list (mc->m.mnt_opts); while (options) { char *co = car (options); if (!strncmp(co, "user=", 5)) { if (!user || !streq(co+5,user)) die(2, _("umount: only %s can unmount %s from %s"), - co+5, fs->mnt_fsname, fs->mnt_dir); + co+5, fs->m.mnt_fsname, fs->m.mnt_dir); break; } options = cdr (options); diff --git a/po/Makefile b/po/Makefile index 3e59fedc8..a93f77553 100644 --- a/po/Makefile +++ b/po/Makefile @@ -13,12 +13,8 @@ INTL = /usr/share/gettext/intl SHELL = /bin/sh -prefix = $(DESTDIR)/usr -exec_prefix = ${prefix} -datadir = $(prefix)/share -localedir = $(datadir)/locale -gnulocaledir = $(prefix)/share/locale -gettextsrcdir = $(prefix)/share/gettext/po +localedir = $(LOCALEDIR) +gnulocaledir = $(LOCALEDIR) # Not giving an explicit path improves the chances of finding this INSTALL = install -c @@ -26,7 +22,7 @@ INSTALL_DATA = ${INSTALL} -m 644 # Not giving an explicit path improves the chances of finding these GENCAT = gencat -MSGFMT = msgfmt +MSGFMT = msgfmt -c # -c: undocumented, but useful option XGETTEXT = xgettext MSGMERGE = msgmerge @@ -38,9 +34,9 @@ INCLUDES = -I.. -I$(INTL) COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) # Enter here all .po files -POFILES = cs.po de.po es.po fr.po it.po ja.po nl.po pt_BR.po +POFILES = cs.po da.po de.po es.po fr.po it.po ja.po nl.po pt_BR.po # the same but with .gmo -GMOFILES = cs.gmo de.gmo es.gmo fr.gmo it.gmo ja.gmo nl.gmo pt_BR.gmo +GMOFILES = cs.gmo da.gmo de.gmo es.gmo fr.gmo it.gmo ja.gmo nl.gmo pt_BR.gmo CATALOGS = $(GMOFILES) CATOBJEXT = .gmo @@ -90,7 +86,6 @@ stamp-cat-id: util-linux.pot install: install-data-$(HAVE_XGETTEXT) install-data-no: all install-data-yes: all - ../mkinstalldirs $(datadir); @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ case "$$cat" in \ @@ -117,7 +112,6 @@ uninstall: rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/util-linux$(INSTOBJEXT); \ rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/util-linux$(INSTOBJEXT).m; \ done - rm -f $(gettextsrcdir)/po-Makefile.in.in cat-id-tbl.o: $(INTL)/libgettext.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 7ea5b8052..6ce99166c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,11 +1,12 @@ -clock/cmos.c -clock/hwclock.c -clock/kd.c -clock/rtc.c -clock/shhopt.c +hwclock/cmos.c +hwclock/hwclock.c +hwclock/kd.c +hwclock/rtc.c +hwclock/shhopt.c disk-utils/blockdev.c disk-utils/fdformat.c disk-utils/fsck.minix.c +disk-utils/isosize.c disk-utils/mkfs.c disk-utils/mkfs.minix.c disk-utils/mkswap.c @@ -20,7 +21,7 @@ fdisk/i386_sys_types.c fdisk/llseek.c fdisk/sfdisk.c games/banner.c -getopt-1.0.3b/getopt.c +getopt-1.1.0a/getopt.c lib/env.c lib/err.c lib/my_reboot.c diff --git a/po/cat-id-tbl.c b/po/cat-id-tbl.c index b5f9b1342..42dc43ade 100644 --- a/po/cat-id-tbl.c +++ b/po/cat-id-tbl.c @@ -126,7 +126,7 @@ Functions:\n\ Options: \n\ --utc the hardware clock is kept in coordinated universal time\n\ --localtime the hardware clock is kept in local time\n\ - --directisa access the ISA bus directly instead of /dev/rtc\n\ + --directisa access the ISA bus directly instead of %s\n\ --badyear ignore rtc's year because the bios is broken\n\ --date specifies the time to which to set the hardware clock\n\ --epoch=year specifies the year which is the beginning of the \n\ @@ -159,29 +159,28 @@ method.\n", 74}, {"ioctl() to open /dev/tty1 failed", 80}, {"KDGHWCLK ioctl failed", 81}, {"Can't open /dev/tty1", 82}, - {"ioctl() to /dev/rtc to read the time failed.\n", 83}, - {"Waiting in loop for time from /dev/rtc to change\n", 84}, - {"open() of /dev/rtc failed", 85}, - {"/dev/rtc does not have interrupt functions. ", 86}, - {"read() to /dev/rtc to wait for clock tick failed", 87}, - {"ioctl() to /dev/rtc to turn off update interrupts failed", 88}, - {"ioctl() to /dev/rtc to turn on update interrupts failed unexpectedly", 89}, - {"Unable to open /dev/rtc", 90}, - {"ioctl() to /dev/rtc to set the time failed.\n", 91}, + {"ioctl() to %s to read the time failed.\n", 83}, + {"Waiting in loop for time from %s to change\n", 84}, + {"open() of %s failed", 85}, + {"%s does not have interrupt functions. ", 86}, + {"read() to %s to wait for clock tick failed", 87}, + {"ioctl() to %s to turn off update interrupts failed", 88}, + {"ioctl() to %s to turn on update interrupts failed unexpectedly", 89}, + {"Unable to open %s", 90}, + {"ioctl() to %s to set the time failed.\n", 91}, {"ioctl(%s) was successful.\n", 92}, - {"Open of /dev/rtc failed", 93}, + {"Open of %s failed", 93}, {"\ To manipulate the epoch value in the kernel, we must access the Linux 'rtc' \ -device driver via the device special file /dev/rtc. This file does not \ -exist on this system.\n", 94}, - {"ioctl(RTC_EPOCH_READ) to /dev/rtc failed", 95}, - {"we have read epoch %ld from /dev/rtc with RTC_EPOCH_READ ioctl.\n", 96}, +device driver via the device special file %s. This file does not exist on \ +this system.\n", 94}, + {"ioctl(RTC_EPOCH_READ) to %s failed", 95}, + {"we have read epoch %ld from %s with RTC_EPOCH_READ ioctl.\n", 96}, {"The epoch value may not be less than 1900. You requested %ld\n", 97}, - {"setting epoch to %ld with RTC_EPOCH_SET ioctl to /dev/rtc.\n", 98}, + {"setting epoch to %ld with RTC_EPOCH_SET ioctl to %s.\n", 98}, {"\ -The kernel device driver for /dev/rtc does not have the RTC_EPOCH_SET \ -ioctl.\n", 99}, - {"ioctl(RTC_EPOCH_SET) to /dev/rtc failed", 100}, +The kernel device driver for %s does not have the RTC_EPOCH_SET ioctl.\n", 99}, + {"ioctl(RTC_EPOCH_SET) to %s failed", 100}, {"invalid number `%s'\n", 101}, {"number `%s' to `%s' out of range\n", 102}, {"unrecognized option `%s'\n", 103}, @@ -311,267 +310,273 @@ namelen=%d\n\ ----------------------------\n\ FILE SYSTEM HAS BEEN CHANGED\n\ ----------------------------\n", 209}, - {"Usage: mkfs [-V] [-t fstype] [fs-options] device [size]\n", 210}, - {"%s: Out of memory!\n", 211}, - {"mkfs version %s (%s)\n", 212}, - {"Usage: %s [-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]\n", 213}, - {"%s is mounted; will not make a filesystem here!", 214}, - {"seek to boot block failed in write_tables", 215}, - {"unable to clear boot sector", 216}, - {"seek failed in write_tables", 217}, - {"unable to write inode map", 218}, - {"unable to write zone map", 219}, - {"unable to write inodes", 220}, - {"write failed in write_block", 221}, - {"too many bad blocks", 222}, - {"not enough good blocks", 223}, - {"unable to allocate buffers for maps", 224}, - {"unable to allocate buffer for inodes", 225}, + {"%s: failed to open: %s\n", 210}, + {"%s: seek error on %s\n", 211}, + {"%s: read error on %s\n", 212}, + {"sector count: %d, sector size: %d\n", 213}, + {"%s: option parse error\n", 214}, + {"Usage: %s [-x] [-d ] iso9660-image\n", 215}, + {"Usage: mkfs [-V] [-t fstype] [fs-options] device [size]\n", 216}, + {"%s: Out of memory!\n", 217}, + {"mkfs version %s (%s)\n", 218}, + {"Usage: %s [-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]\n", 219}, + {"%s is mounted; will not make a filesystem here!", 220}, + {"seek to boot block failed in write_tables", 221}, + {"unable to clear boot sector", 222}, + {"seek failed in write_tables", 223}, + {"unable to write inode map", 224}, + {"unable to write zone map", 225}, + {"unable to write inodes", 226}, + {"write failed in write_block", 227}, + {"too many bad blocks", 228}, + {"not enough good blocks", 229}, + {"unable to allocate buffers for maps", 230}, + {"unable to allocate buffer for inodes", 231}, {"\ Maxsize=%ld\n\ -\n", 226}, - {"seek failed during testing of blocks", 227}, - {"Weird values in do_check: probably bugs\n", 228}, - {"seek failed in check_blocks", 229}, - {"bad blocks before data-area: cannot make fs", 230}, - {"%d bad blocks\n", 231}, - {"one bad block\n", 232}, - {"can't open file of bad blocks", 233}, - {"%s: not compiled with minix v2 support\n", 234}, - {"strtol error: number of blocks not specified", 235}, - {"unable to open %s", 236}, - {"unable to stat %s", 237}, - {"will not try to make filesystem on '%s'", 238}, - {"Bad user-specified page size %d\n", 239}, - {"Using user-specified page size %d, instead of the system values %d/%d\n", 240}, - {"Assuming pages of size %d (not %d)\n", 241}, - {"Usage: %s [-c] [-v0|-v1] [-pPAGESZ] /dev/name [blocks]\n", 242}, - {"too many bad pages", 243}, - {"Out of memory", 244}, - {"one bad page\n", 245}, - {"%d bad pages\n", 246}, - {"%s: error: Nowhere to set up swap on?\n", 247}, - {"%s: error: size %ld is larger than device size %d\n", 248}, - {"%s: error: unknown version %d\n", 249}, - {"%s: error: swap area needs to be at least %ldkB\n", 250}, - {"%s: warning: truncating swap area to %ldkB\n", 251}, - {"Will not try to make swapdevice on '%s'", 252}, - {"fatal: first page unreadable", 253}, +\n", 232}, + {"seek failed during testing of blocks", 233}, + {"Weird values in do_check: probably bugs\n", 234}, + {"seek failed in check_blocks", 235}, + {"bad blocks before data-area: cannot make fs", 236}, + {"%d bad blocks\n", 237}, + {"one bad block\n", 238}, + {"can't open file of bad blocks", 239}, + {"%s: not compiled with minix v2 support\n", 240}, + {"strtol error: number of blocks not specified", 241}, + {"unable to open %s", 242}, + {"unable to stat %s", 243}, + {"will not try to make filesystem on '%s'", 244}, + {"Bad user-specified page size %d\n", 245}, + {"Using user-specified page size %d, instead of the system values %d/%d\n", 246}, + {"Assuming pages of size %d (not %d)\n", 247}, + {"Usage: %s [-c] [-v0|-v1] [-pPAGESZ] /dev/name [blocks]\n", 248}, + {"too many bad pages", 249}, + {"Out of memory", 250}, + {"one bad page\n", 251}, + {"%d bad pages\n", 252}, + {"%s: error: Nowhere to set up swap on?\n", 253}, + {"%s: error: size %ld is larger than device size %d\n", 254}, + {"%s: error: unknown version %d\n", 255}, + {"%s: error: swap area needs to be at least %ldkB\n", 256}, + {"%s: warning: truncating swap area to %ldkB\n", 257}, + {"Will not try to make swapdevice on '%s'", 258}, + {"fatal: first page unreadable", 259}, {"\ %s: Device '%s' contains a valid Sun disklabel.\n\ This probably means creating v0 swap would destroy your partition table\n\ No swap created. If you really want to create swap v0 on that device, use\n\ -the -f option to force it.\n", 254}, - {"Unable to set up swap-space: unreadable", 255}, - {"Setting up swapspace version %d, size = %ld bytes\n", 256}, - {"unable to rewind swap-device", 257}, - {"unable to write signature page", 258}, - {"fsync failed", 259}, - {"Invalid number: %s\n", 260}, - {"Syntax error: '%s'\n", 261}, - {"No such parameter set: '%s'\n", 262}, - {"usage: %s [ -p ] dev name\n", 263}, - {"\ - %s [ -p ] dev size sect heads tracks stretch gap rate spec1 fmt_gap\n", 264}, - {" %s [ -c | -y | -n | -d ] dev\n", 265}, - {" %s [ -c | -y | -n ] dev\n", 266}, - {"Unusable", 267}, - {"Free Space", 268}, - {"Linux ext2", 269}, - {"Linux", 270}, - {"OS/2 HPFS", 271}, - {"OS/2 IFS", 272}, - {"NTFS", 273}, - {"Disk has been changed.\n", 274}, - {"Reboot the system to ensure the partition table is correctly updated.\n", 275}, +the -f option to force it.\n", 260}, + {"Unable to set up swap-space: unreadable", 261}, + {"Setting up swapspace version %d, size = %ld bytes\n", 262}, + {"unable to rewind swap-device", 263}, + {"unable to write signature page", 264}, + {"fsync failed", 265}, + {"Invalid number: %s\n", 266}, + {"Syntax error: '%s'\n", 267}, + {"No such parameter set: '%s'\n", 268}, + {"usage: %s [ -p ] dev name\n", 269}, + {"\ + %s [ -p ] dev size sect heads tracks stretch gap rate spec1 fmt_gap\n", 270}, + {" %s [ -c | -y | -n | -d ] dev\n", 271}, + {" %s [ -c | -y | -n ] dev\n", 272}, + {"Unusable", 273}, + {"Free Space", 274}, + {"Linux ext2", 275}, + {"Linux", 276}, + {"OS/2 HPFS", 277}, + {"OS/2 IFS", 278}, + {"NTFS", 279}, + {"Disk has been changed.\n", 280}, + {"Reboot the system to ensure the partition table is correctly updated.\n", 281}, {"\ \n\ WARNING: If you have created or modified any\n\ DOS 6.x partitions, please see the cfdisk manual\n\ -page for additional information.\n", 276}, - {"FATAL ERROR", 277}, - {"Press any key to exit cfdisk", 278}, - {"Cannot seek on disk drive", 279}, - {"Cannot read disk drive", 280}, - {"Cannot write disk drive", 281}, - {"Too many partitions", 282}, - {"Partition begins before sector 0", 283}, - {"Partition ends before sector 0", 284}, - {"Partition begins after end-of-disk", 285}, - {"Partition ends after end-of-disk", 286}, - {"logical partitions not in disk order", 287}, - {"logical partitions overlap", 288}, - {"enlarged logical partitions overlap", 289}, - {"\ -!!!! Internal error creating logical drive with no extended partition !!!!", 290}, - {"\ -Cannot create logical drive here -- would create two extended partitions", 291}, - {"Menu item too long. Menu may look odd.", 292}, - {"Menu without direction. Defaulting horizontal.", 293}, - {"Illegal key", 294}, - {"Press a key to continue", 295}, - {"Primary", 296}, - {"Create a new primary partition", 297}, - {"Logical", 298}, - {"Create a new logical partition", 299}, - {"Cancel", 300}, - {"Don't create a partition", 301}, - {"!!! Internal error !!!", 302}, - {"Size (in MB): ", 303}, - {"Beginning", 304}, - {"Add partition at beginning of free space", 305}, - {"End", 306}, - {"Add partition at end of free space", 307}, - {"No room to create the extended partition", 308}, - {"Bad signature on partition table", 309}, - {"You specified more cylinders than fit on disk", 310}, - {"Cannot open disk drive", 311}, - {"Opened disk read-only - you have no permission to write", 312}, - {"Cannot get disk size", 313}, - {"Bad primary partition", 314}, - {"Bad logical partition", 315}, - {"Warning!! This may destroy data on your disk!", 316}, - {"Are you sure you want write the partition table to disk? (yes or no): ", 317}, - {"no", 318}, - {"Did not write partition table to disk", 319}, - {"yes", 320}, - {"Please enter `yes' or `no'", 321}, - {"Writing partition table to disk...", 322}, - {"Wrote partition table to disk", 323}, - {"\ -Wrote partition table, but re-read table failed. Reboot to update table.", 324}, - {"\ -Not precisely one primary partition is bootable. DOS MBR cannot boot this.", 325}, - {"Enter filename or press RETURN to display on screen: ", 326}, - {"Cannot open file '%s'", 327}, - {"Disk Drive: %s\n", 328}, - {"Sector 0:\n", 329}, - {"Sector %d:\n", 330}, - {" None ", 331}, - {" Pri/Log", 332}, - {" Primary", 333}, - {" Logical", 334}, - {"Unknown", 335}, - {"Boot (%02X)", 336}, - {"Unknown (%02X)", 337}, - {"None (%02X)", 338}, - {"Partition Table for %s\n", 339}, - {" First Last\n", 340}, - {"\ - # Type Sector Sector Offset Length Filesystem Type (ID) Flags\n", 341}, +page for additional information.\n", 282}, + {"FATAL ERROR", 283}, + {"Press any key to exit cfdisk", 284}, + {"Cannot seek on disk drive", 285}, + {"Cannot read disk drive", 286}, + {"Cannot write disk drive", 287}, + {"Too many partitions", 288}, + {"Partition begins before sector 0", 289}, + {"Partition ends before sector 0", 290}, + {"Partition begins after end-of-disk", 291}, + {"Partition ends after end-of-disk", 292}, + {"logical partitions not in disk order", 293}, + {"logical partitions overlap", 294}, + {"enlarged logical partitions overlap", 295}, + {"\ +!!!! Internal error creating logical drive with no extended partition !!!!", 296}, + {"\ +Cannot create logical drive here -- would create two extended partitions", 297}, + {"Menu item too long. Menu may look odd.", 298}, + {"Menu without direction. Defaulting horizontal.", 299}, + {"Illegal key", 300}, + {"Press a key to continue", 301}, + {"Primary", 302}, + {"Create a new primary partition", 303}, + {"Logical", 304}, + {"Create a new logical partition", 305}, + {"Cancel", 306}, + {"Don't create a partition", 307}, + {"!!! Internal error !!!", 308}, + {"Size (in MB): ", 309}, + {"Beginning", 310}, + {"Add partition at beginning of free space", 311}, + {"End", 312}, + {"Add partition at end of free space", 313}, + {"No room to create the extended partition", 314}, + {"Bad signature on partition table", 315}, + {"You specified more cylinders than fit on disk", 316}, + {"Cannot open disk drive", 317}, + {"Opened disk read-only - you have no permission to write", 318}, + {"Cannot get disk size", 319}, + {"Bad primary partition", 320}, + {"Bad logical partition", 321}, + {"Warning!! This may destroy data on your disk!", 322}, + {"Are you sure you want write the partition table to disk? (yes or no): ", 323}, + {"no", 324}, + {"Did not write partition table to disk", 325}, + {"yes", 326}, + {"Please enter `yes' or `no'", 327}, + {"Writing partition table to disk...", 328}, + {"Wrote partition table to disk", 329}, + {"\ +Wrote partition table, but re-read table failed. Reboot to update table.", 330}, + {"\ +Not precisely one primary partition is bootable. DOS MBR cannot boot this.", 331}, + {"Enter filename or press RETURN to display on screen: ", 332}, + {"Cannot open file '%s'", 333}, + {"Disk Drive: %s\n", 334}, + {"Sector 0:\n", 335}, + {"Sector %d:\n", 336}, + {" None ", 337}, + {" Pri/Log", 338}, + {" Primary", 339}, + {" Logical", 340}, + {"Unknown", 341}, + {"Boot (%02X)", 342}, + {"Unknown (%02X)", 343}, + {"None (%02X)", 344}, + {"Partition Table for %s\n", 345}, + {" First Last\n", 346}, + {"\ + # Type Sector Sector Offset Length Filesystem Type (ID) Flags\n", 347}, {"\ -- ------- -------- --------- ------ --------- ---------------------- \ ----------\n", 342}, - {" ---Starting--- ----Ending---- Start Number of\n", 343}, - {" # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n", 344}, - {"-- ----- ---- ---- ---- ---- ---- ---- ---- -------- ---------\n", 345}, - {"Raw", 346}, - {"Print the table using raw data format", 347}, - {"Sectors", 348}, - {"Print the table ordered by sectors", 349}, - {"Table", 350}, - {"Just print the partition table", 351}, - {"Don't print the table", 352}, - {"Help Screen for cfdisk", 353}, - {"This is cfdisk, a curses based disk partitioning program, which", 354}, - {"allows you to create, delete and modify partitions on your hard", 355}, - {"disk drive.", 356}, - {"Copyright (C) 1994-1999 Kevin E. Martin & aeb", 357}, - {"Command Meaning", 358}, - {"------- -------", 359}, - {" b Toggle bootable flag of the current partition", 360}, - {" d Delete the current partition", 361}, - {" g Change cylinders, heads, sectors-per-track parameters", 362}, - {" WARNING: This option should only be used by people who", 363}, - {" know what they are doing.", 364}, - {" h Print this screen", 365}, - {" m Maximize disk usage of the current partition", 366}, - {" Note: This may make the partition incompatible with", 367}, - {" DOS, OS/2, ...", 368}, - {" n Create new partition from free space", 369}, - {" p Print partition table to the screen or to a file", 370}, - {" There are several different formats for the partition", 371}, - {" that you can choose from:", 372}, - {" r - Raw data (exactly what would be written to disk)", 373}, - {" s - Table ordered by sectors", 374}, - {" t - Table in raw format", 375}, - {" q Quit program without writing partition table", 376}, - {" t Change the filesystem type", 377}, - {" u Change units of the partition size display", 378}, - {" Rotates through MB, sectors and cylinders", 379}, - {" W Write partition table to disk (must enter upper case W)", 380}, - {" Since this might destroy data on the disk, you must", 381}, - {" either confirm or deny the write by entering `yes' or", 382}, - {" `no'", 383}, - {"Up Arrow Move cursor to the previous partition", 384}, - {"Down Arrow Move cursor to the next partition", 385}, - {"CTRL-L Redraws the screen", 386}, - {" ? Print this screen", 387}, - {"Note: All of the commands can be entered with either upper or lower", 388}, - {"case letters (except for Writes).", 389}, - {"Cylinders", 390}, - {"Change cylinder geometry", 391}, - {"Heads", 392}, - {"Change head geometry", 393}, - {"Change sector geometry", 394}, - {"Done", 395}, - {"Done with changing geometry", 396}, - {"Enter the number of cylinders: ", 397}, - {"Illegal cylinders value", 398}, - {"Enter the number of heads: ", 399}, - {"Illegal heads value", 400}, - {"Enter the number of sectors per track: ", 401}, - {"Illegal sectors value", 402}, - {"Enter filesystem type: ", 403}, - {"Cannot change FS Type to empty", 404}, - {"Cannot change FS Type to extended", 405}, - {"Boot", 406}, - {"Unk(%02X)", 407}, - {", NC", 408}, - {"NC", 409}, - {"Pri/Log", 410}, - {"Disk Drive: %s", 411}, - {"Size: %lld bytes", 412}, - {"Heads: %d Sectors per Track: %d Cylinders: %d", 413}, - {"Name", 414}, - {"Flags", 415}, - {"Part Type", 416}, - {"FS Type", 417}, - {"[Label]", 418}, - {" Sectors", 419}, - {"Size (MB)", 420}, - {"Size (GB)", 421}, - {"Bootable", 422}, - {"Toggle bootable flag of the current partition", 423}, - {"Delete", 424}, - {"Delete the current partition", 425}, - {"Geometry", 426}, - {"Change disk geometry (experts only)", 427}, - {"Help", 428}, - {"Print help screen", 429}, - {"Maximize", 430}, - {"Maximize disk usage of the current partition (experts only)", 431}, - {"New", 432}, - {"Create new partition from free space", 433}, - {"Print", 434}, - {"Print partition table to the screen or to a file", 435}, - {"Quit", 436}, - {"Quit program without writing partition table", 437}, - {"Type", 438}, - {"Change the filesystem type (DOS, Linux, OS/2 and so on)", 439}, - {"Units", 440}, - {"Change units of the partition size display (MB, sect, cyl)", 441}, - {"Write", 442}, - {"Write partition table to disk (this might destroy data)", 443}, - {"Cannot make this partition bootable", 444}, - {"Cannot delete an empty partition", 445}, - {"Cannot maximize this partition", 446}, - {"This partition is unusable", 447}, - {"This partition is already in use", 448}, - {"Cannot change the type of an empty partition", 449}, - {"No more partitions", 450}, - {"Illegal command", 451}, - {"Copyright (C) 1994-2000 Kevin E. Martin & aeb\n", 452}, +---------\n", 348}, + {" ---Starting--- ----Ending---- Start Number of\n", 349}, + {" # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n", 350}, + {"-- ----- ---- ---- ---- ---- ---- ---- ---- -------- ---------\n", 351}, + {"Raw", 352}, + {"Print the table using raw data format", 353}, + {"Sectors", 354}, + {"Print the table ordered by sectors", 355}, + {"Table", 356}, + {"Just print the partition table", 357}, + {"Don't print the table", 358}, + {"Help Screen for cfdisk", 359}, + {"This is cfdisk, a curses based disk partitioning program, which", 360}, + {"allows you to create, delete and modify partitions on your hard", 361}, + {"disk drive.", 362}, + {"Copyright (C) 1994-1999 Kevin E. Martin & aeb", 363}, + {"Command Meaning", 364}, + {"------- -------", 365}, + {" b Toggle bootable flag of the current partition", 366}, + {" d Delete the current partition", 367}, + {" g Change cylinders, heads, sectors-per-track parameters", 368}, + {" WARNING: This option should only be used by people who", 369}, + {" know what they are doing.", 370}, + {" h Print this screen", 371}, + {" m Maximize disk usage of the current partition", 372}, + {" Note: This may make the partition incompatible with", 373}, + {" DOS, OS/2, ...", 374}, + {" n Create new partition from free space", 375}, + {" p Print partition table to the screen or to a file", 376}, + {" There are several different formats for the partition", 377}, + {" that you can choose from:", 378}, + {" r - Raw data (exactly what would be written to disk)", 379}, + {" s - Table ordered by sectors", 380}, + {" t - Table in raw format", 381}, + {" q Quit program without writing partition table", 382}, + {" t Change the filesystem type", 383}, + {" u Change units of the partition size display", 384}, + {" Rotates through MB, sectors and cylinders", 385}, + {" W Write partition table to disk (must enter upper case W)", 386}, + {" Since this might destroy data on the disk, you must", 387}, + {" either confirm or deny the write by entering `yes' or", 388}, + {" `no'", 389}, + {"Up Arrow Move cursor to the previous partition", 390}, + {"Down Arrow Move cursor to the next partition", 391}, + {"CTRL-L Redraws the screen", 392}, + {" ? Print this screen", 393}, + {"Note: All of the commands can be entered with either upper or lower", 394}, + {"case letters (except for Writes).", 395}, + {"Cylinders", 396}, + {"Change cylinder geometry", 397}, + {"Heads", 398}, + {"Change head geometry", 399}, + {"Change sector geometry", 400}, + {"Done", 401}, + {"Done with changing geometry", 402}, + {"Enter the number of cylinders: ", 403}, + {"Illegal cylinders value", 404}, + {"Enter the number of heads: ", 405}, + {"Illegal heads value", 406}, + {"Enter the number of sectors per track: ", 407}, + {"Illegal sectors value", 408}, + {"Enter filesystem type: ", 409}, + {"Cannot change FS Type to empty", 410}, + {"Cannot change FS Type to extended", 411}, + {"Boot", 412}, + {"Unk(%02X)", 413}, + {", NC", 414}, + {"NC", 415}, + {"Pri/Log", 416}, + {"Disk Drive: %s", 417}, + {"Size: %lld bytes", 418}, + {"Heads: %d Sectors per Track: %d Cylinders: %d", 419}, + {"Name", 420}, + {"Flags", 421}, + {"Part Type", 422}, + {"FS Type", 423}, + {"[Label]", 424}, + {" Sectors", 425}, + {"Size (MB)", 426}, + {"Size (GB)", 427}, + {"Bootable", 428}, + {"Toggle bootable flag of the current partition", 429}, + {"Delete", 430}, + {"Delete the current partition", 431}, + {"Geometry", 432}, + {"Change disk geometry (experts only)", 433}, + {"Help", 434}, + {"Print help screen", 435}, + {"Maximize", 436}, + {"Maximize disk usage of the current partition (experts only)", 437}, + {"New", 438}, + {"Create new partition from free space", 439}, + {"Print", 440}, + {"Print partition table to the screen or to a file", 441}, + {"Quit", 442}, + {"Quit program without writing partition table", 443}, + {"Type", 444}, + {"Change the filesystem type (DOS, Linux, OS/2 and so on)", 445}, + {"Units", 446}, + {"Change units of the partition size display (MB, sect, cyl)", 447}, + {"Write", 448}, + {"Write partition table to disk (this might destroy data)", 449}, + {"Cannot make this partition bootable", 450}, + {"Cannot delete an empty partition", 451}, + {"Cannot maximize this partition", 452}, + {"This partition is unusable", 453}, + {"This partition is already in use", 454}, + {"Cannot change the type of an empty partition", 455}, + {"No more partitions", 456}, + {"Illegal command", 457}, + {"Copyright (C) 1994-2000 Kevin E. Martin & aeb\n", 458}, {"\ \n\ Usage:\n\ @@ -587,7 +592,7 @@ Options:\n\ -z: Start with a zero partition table, instead of reading the pt from disk;\n\ -c C -h H -s S: Override the kernel's idea of the number of cylinders,\n\ the number of heads and the number of sectors/track.\n\ -\n", 453}, +\n", 459}, {"\ Usage: fdisk [-b SSZ] [-u] DISK Change partition table\n\ fdisk -l [-b SSZ] [-u] DISK List partition table(s)\n\ @@ -596,211 +601,219 @@ Usage: fdisk [-b SSZ] [-u] DISK Change partition table\n\ Here DISK is something like /dev/hdb or /dev/sda\n\ and PARTITION is something like /dev/hda7\n\ -u: give Start and End in sector (instead of cylinder) units\n\ --b 2048: (for certain MO drives) use 2048-byte sectors\n", 454}, +-b 2048: (for certain MO drives) use 2048-byte sectors\n", 460}, {"\ Usage: fdisk [-l] [-b SSZ] [-u] device\n\ E.g.: fdisk /dev/hda (for the first IDE disk)\n\ or: fdisk /dev/sdc (for the third SCSI disk)\n\ or: fdisk /dev/eda (for the first PS/2 ESDI drive)\n\ or: fdisk /dev/rd/c0d0 or: fdisk /dev/ida/c0d0 (for RAID devices)\n\ - ...\n", 455}, - {"Unable to open %s\n", 456}, - {"Unable to read %s\n", 457}, - {"Unable to seek on %s\n", 458}, - {"Unable to write %s\n", 459}, - {"BLKGETSIZE ioctl failed on %s\n", 460}, - {"Unable to allocate any more memory\n", 461}, - {"Fatal error\n", 462}, - {"Command action", 463}, - {" a toggle a read only flag", 464}, - {" b edit bsd disklabel", 465}, - {" c toggle the mountable flag", 466}, - {" d delete a partition", 467}, - {" l list known partition types", 468}, - {" m print this menu", 469}, - {" n add a new partition", 470}, - {" o create a new empty DOS partition table", 471}, - {" p print the partition table", 472}, - {" q quit without saving changes", 473}, - {" s create a new empty Sun disklabel", 474}, - {" t change a partition's system id", 475}, - {" u change display/entry units", 476}, - {" v verify the partition table", 477}, - {" w write table to disk and exit", 478}, - {" x extra functionality (experts only)", 479}, - {" a select bootable partition", 480}, - {" b edit bootfile entry", 481}, - {" c select sgi swap partition", 482}, - {" a toggle a bootable flag", 483}, - {" c toggle the dos compatibility flag", 484}, - {" a change number of alternate cylinders", 485}, - {" c change number of cylinders", 486}, - {" d print the raw data in the partition table", 487}, - {" e change number of extra sectors per cylinder", 488}, - {" h change number of heads", 489}, - {" i change interleave factor", 490}, - {" o change rotation speed (rpm)", 491}, - {" r return to main menu", 492}, - {" s change number of sectors/track", 493}, - {" y change number of physical cylinders", 494}, - {" b move beginning of data in a partition", 495}, - {" e list extended partitions", 496}, - {" g create an IRIX partition table", 497}, - {" f fix partition order", 498}, - {"You must set", 499}, - {"heads", 500}, - {"sectors", 501}, - {"cylinders", 502}, + ...\n", 461}, + {"Unable to open %s\n", 462}, + {"Unable to read %s\n", 463}, + {"Unable to seek on %s\n", 464}, + {"Unable to write %s\n", 465}, + {"BLKGETSIZE ioctl failed on %s\n", 466}, + {"Unable to allocate any more memory\n", 467}, + {"Fatal error\n", 468}, + {"Command action", 469}, + {" a toggle a read only flag", 470}, + {" b edit bsd disklabel", 471}, + {" c toggle the mountable flag", 472}, + {" d delete a partition", 473}, + {" l list known partition types", 474}, + {" m print this menu", 475}, + {" n add a new partition", 476}, + {" o create a new empty DOS partition table", 477}, + {" p print the partition table", 478}, + {" q quit without saving changes", 479}, + {" s create a new empty Sun disklabel", 480}, + {" t change a partition's system id", 481}, + {" u change display/entry units", 482}, + {" v verify the partition table", 483}, + {" w write table to disk and exit", 484}, + {" x extra functionality (experts only)", 485}, + {" a select bootable partition", 486}, + {" b edit bootfile entry", 487}, + {" c select sgi swap partition", 488}, + {" a toggle a bootable flag", 489}, + {" c toggle the dos compatibility flag", 490}, + {" a change number of alternate cylinders", 491}, + {" c change number of cylinders", 492}, + {" d print the raw data in the partition table", 493}, + {" e change number of extra sectors per cylinder", 494}, + {" h change number of heads", 495}, + {" i change interleave factor", 496}, + {" o change rotation speed (rpm)", 497}, + {" r return to main menu", 498}, + {" s change number of sectors/track", 499}, + {" y change number of physical cylinders", 500}, + {" b move beginning of data in a partition", 501}, + {" e list extended partitions", 502}, + {" g create an IRIX partition table", 503}, + {" f fix partition order", 504}, + {"You must set", 505}, + {"heads", 506}, + {"sectors", 507}, + {"cylinders", 508}, {"\ %s%s.\n\ -You can do this from the extra functions menu.\n", 503}, - {" and ", 504}, - {"Bad offset in primary extended partition\n", 505}, - {"Warning: deleting partitions after %d\n", 506}, - {"Warning: extra link pointer in partition table %d\n", 507}, - {"Warning: ignoring extra data in partition table %d\n", 508}, +You can do this from the extra functions menu.\n", 509}, + {" and ", 510}, + {"\ +\n\ +The number of cylinders for this disk is set to %d.\n\ +There is nothing wrong with that, but this is larger than 1024,\n\ +and could in certain setups cause problems with:\n\ +1) software that runs at boot time (e.g., old versions of LILO)\n\ +2) booting and partitioning software from other OSs\n\ + (e.g., DOS FDISK, OS/2 FDISK)\n", 511}, + {"Bad offset in primary extended partition\n", 512}, + {"Warning: deleting partitions after %d\n", 513}, + {"Warning: extra link pointer in partition table %d\n", 514}, + {"Warning: ignoring extra data in partition table %d\n", 515}, {"\ Building a new DOS disklabel. Changes will remain in memory only,\n\ until you decide to write them. After that, of course, the previous\n\ content won't be recoverable.\n\ -\n", 509}, - {"Note: sector size is %d (not %d)\n", 510}, - {"You will not be able to write the partition table.\n", 511}, +\n", 516}, + {"Note: sector size is %d (not %d)\n", 517}, + {"You will not be able to write the partition table.\n", 518}, {"\ Device contains neither a valid DOS partition table, nor Sun, SGI or OSF \ -disklabel\n", 512}, - {"Internal error\n", 513}, - {"Ignoring extra extended partition %d\n", 514}, +disklabel\n", 519}, + {"Internal error\n", 520}, + {"Ignoring extra extended partition %d\n", 521}, {"\ Warning: invalid flag 0x%04x of partition table %d will be corrected by \ -w(rite)\n", 515}, +w(rite)\n", 522}, {"\ \n\ -got EOF thrice - exiting..\n", 516}, - {"Hex code (type L to list codes): ", 517}, - {"%s (%d-%d, default %d): ", 518}, - {"Using default value %d\n", 519}, - {"Value out of range.\n", 520}, - {"Partition number", 521}, - {"Warning: partition %d has empty type\n", 522}, - {"cylinder", 523}, - {"sector", 524}, - {"Changing display/entry units to %s\n", 525}, - {"WARNING: Partition %d is an extended partition\n", 526}, - {"DOS Compatibility flag is set\n", 527}, - {"DOS Compatibility flag is not set\n", 528}, - {"Partition %d does not exist yet!\n", 529}, +got EOF thrice - exiting..\n", 523}, + {"Hex code (type L to list codes): ", 524}, + {"%s (%d-%d, default %d): ", 525}, + {"Using default value %d\n", 526}, + {"Value out of range.\n", 527}, + {"Partition number", 528}, + {"Warning: partition %d has empty type\n", 529}, + {"cylinder", 530}, + {"sector", 531}, + {"Changing display/entry units to %s\n", 532}, + {"WARNING: Partition %d is an extended partition\n", 533}, + {"DOS Compatibility flag is set\n", 534}, + {"DOS Compatibility flag is not set\n", 535}, + {"Partition %d does not exist yet!\n", 536}, {"\ Type 0 means free space to many systems\n\ (but not to Linux). Having partitions of\n\ type 0 is probably unwise. You can delete\n\ -a partition using the `d' command.\n", 530}, +a partition using the `d' command.\n", 537}, {"\ You cannot change a partition into an extended one or vice versa\n\ -Delete it first.\n", 531}, +Delete it first.\n", 538}, {"\ Consider leaving partition 3 as Whole disk (5),\n\ as SunOS/Solaris expects it and even Linux likes it.\n\ -\n", 532}, +\n", 539}, {"\ Consider leaving partition 9 as volume header (0),\n\ and partition 11 as entire volume (6)as IRIX expects it.\n\ -\n", 533}, - {"Changed system type of partition %d to %x (%s)\n", 534}, - {"Partition %d has different physical/logical beginnings (non-Linux?):\n", 535}, - {" phys=(%d, %d, %d) ", 536}, - {"logical=(%d, %d, %d)\n", 537}, - {"Partition %d has different physical/logical endings:\n", 538}, - {"Partition %i does not start on cylinder boundary:\n", 539}, - {"should be (%d, %d, 1)\n", 540}, - {"Partition %i does not end on cylinder boundary:\n", 541}, - {"should be (%d, %d, %d)\n", 542}, +\n", 540}, + {"Changed system type of partition %d to %x (%s)\n", 541}, + {"Partition %d has different physical/logical beginnings (non-Linux?):\n", 542}, + {" phys=(%d, %d, %d) ", 543}, + {"logical=(%d, %d, %d)\n", 544}, + {"Partition %d has different physical/logical endings:\n", 545}, + {"Partition %i does not start on cylinder boundary:\n", 546}, + {"should be (%d, %d, 1)\n", 547}, + {"Partition %i does not end on cylinder boundary:\n", 548}, + {"should be (%d, %d, %d)\n", 549}, {"\ \n\ Disk %s: %d heads, %d sectors, %d cylinders\n\ Units = %s of %d * %d bytes\n\ -\n", 543}, +\n", 550}, {"\ Nothing to do. Ordering is correct already.\n\ -\n", 544}, - {"%*s Boot Start End Blocks Id System\n", 545}, - {"Device", 546}, +\n", 551}, + {"%*s Boot Start End Blocks Id System\n", 552}, + {"Device", 553}, {"\ \n\ -Partition table entries are not in disk order\n", 547}, +Partition table entries are not in disk order\n", 554}, {"\ \n\ Disk %s: %d heads, %d sectors, %d cylinders\n\ -\n", 548}, - {"Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n", 549}, - {"Warning: partition %d contains sector 0\n", 550}, - {"Partition %d: head %d greater than maximum %d\n", 551}, - {"Partition %d: sector %d greater than maximum %d\n", 552}, - {"Partitions %d: cylinder %d greater than maximum %d\n", 553}, - {"Partition %d: previous sectors %d disagrees with total %d\n", 554}, - {"Warning: bad start-of-data in partition %d\n", 555}, - {"Warning: partition %d overlaps partition %d.\n", 556}, - {"Warning: partition %d is empty\n", 557}, - {"Logical partition %d not entirely in partition %d\n", 558}, - {"Total allocated sectors %d greater than the maximum %d\n", 559}, - {"%d unallocated sectors\n", 560}, - {"Partition %d is already defined. Delete it before re-adding it.\n", 561}, - {"First %s", 562}, - {"Sector %d is already allocated\n", 563}, - {"No free sectors available\n", 564}, - {"Last %s or +size or +sizeM or +sizeK", 565}, - {"Warning: partition %d has an odd number of sectors.\n", 566}, - {"The maximum number of partitions has been created\n", 567}, - {"You must delete some partition and add an extended partition first\n", 568}, +\n", 555}, + {"Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n", 556}, + {"Warning: partition %d contains sector 0\n", 557}, + {"Partition %d: head %d greater than maximum %d\n", 558}, + {"Partition %d: sector %d greater than maximum %d\n", 559}, + {"Partitions %d: cylinder %d greater than maximum %d\n", 560}, + {"Partition %d: previous sectors %d disagrees with total %d\n", 561}, + {"Warning: bad start-of-data in partition %d\n", 562}, + {"Warning: partition %d overlaps partition %d.\n", 563}, + {"Warning: partition %d is empty\n", 564}, + {"Logical partition %d not entirely in partition %d\n", 565}, + {"Total allocated sectors %d greater than the maximum %d\n", 566}, + {"%d unallocated sectors\n", 567}, + {"Partition %d is already defined. Delete it before re-adding it.\n", 568}, + {"First %s", 569}, + {"Sector %d is already allocated\n", 570}, + {"No free sectors available\n", 571}, + {"Last %s or +size or +sizeM or +sizeK", 572}, + {"Warning: partition %d has an odd number of sectors.\n", 573}, + {"The maximum number of partitions has been created\n", 574}, + {"You must delete some partition and add an extended partition first\n", 575}, {"\ Command action\n\ %s\n\ - p primary partition (1-4)\n", 569}, - {"l logical (5 or over)", 570}, - {"e extended", 571}, - {"Invalid partition number for type `%c'\n", 572}, + p primary partition (1-4)\n", 576}, + {"l logical (5 or over)", 577}, + {"e extended", 578}, + {"Invalid partition number for type `%c'\n", 579}, {"\ The partition table has been altered!\n\ -\n", 573}, - {"Calling ioctl() to re-read partition table.\n", 574}, +\n", 580}, + {"Calling ioctl() to re-read partition table.\n", 581}, {"\ Re-read table failed with error %d: %s.\n\ -Reboot your system to ensure the partition table is updated.\n", 575}, +Reboot your system to ensure the partition table is updated.\n", 582}, {"\ \n\ WARNING: If you have created or modified any DOS 6.x\n\ partitions, please see the fdisk manual page for additional\n\ -information.\n", 576}, - {"Syncing disks.\n", 577}, - {"Device: %s\n", 578}, - {"Partition %d has no data area\n", 579}, - {"New beginning of data", 580}, - {"Expert command (m for help): ", 581}, - {"Number of cylinders", 582}, - {"Number of heads", 583}, - {"Number of sectors", 584}, - {"Warning: setting sector offset for DOS compatiblity\n", 585}, - {"Disk %s doesn't contain a valid partition table\n", 586}, - {"Cannot open %s\n", 587}, - {"cannot open %s\n", 588}, - {"%c: unknown command\n", 589}, - {"This kernel finds the sector size itself - -b option ignored\n", 590}, +information.\n", 583}, + {"Syncing disks.\n", 584}, + {"Device: %s\n", 585}, + {"Partition %d has no data area\n", 586}, + {"New beginning of data", 587}, + {"Expert command (m for help): ", 588}, + {"Number of cylinders", 589}, + {"Number of heads", 590}, + {"Number of sectors", 591}, + {"Warning: setting sector offset for DOS compatiblity\n", 592}, + {"Disk %s doesn't contain a valid partition table\n", 593}, + {"Cannot open %s\n", 594}, + {"cannot open %s\n", 595}, + {"%c: unknown command\n", 596}, + {"This kernel finds the sector size itself - -b option ignored\n", 597}, {"\ Warning: the -b (set sector size) option should be used with one specified \ -device\n", 591}, +device\n", 598}, {"\ Detected an OSF/1 disklabel on %s, entering disklabel mode.\n\ -To return to DOS partition table mode, use the 'r' command.\n", 592}, - {"Command (m for help): ", 593}, +To return to DOS partition table mode, use the 'r' command.\n", 599}, + {"Command (m for help): ", 600}, {"\ \n\ -The current boot file is: %s\n", 594}, - {"Please enter the name of the new boot file: ", 595}, - {"Boot file unchanged\n", 596}, +The current boot file is: %s\n", 601}, + {"Please enter the name of the new boot file: ", 602}, + {"Boot file unchanged\n", 603}, {"\ \n\ \tSorry, no experts menu for SGI partition tables available.\n\ -\n", 597}, +\n", 604}, {"\ \n\ \tThere is a valid AIX label on this disk.\n\ @@ -813,92 +826,92 @@ The current boot file is: %s\n", 594}, \t erase the other disks as well, if unmirrored.)\n\ \t3. Before deleting this physical volume be sure\n\ \t to remove the disk logically from your AIX\n\ -\t machine. (Otherwise you become an AIXpert).", 598}, +\t machine. (Otherwise you become an AIXpert).", 605}, {"\ \n\ -BSD label for device: %s\n", 599}, - {" d delete a BSD partition", 600}, - {" e edit drive data", 601}, - {" i install bootstrap", 602}, - {" l list known filesystem types", 603}, - {" n add a new BSD partition", 604}, - {" p print BSD partition table", 605}, - {" s show complete disklabel", 606}, - {" t change a partition's filesystem id", 607}, - {" u change units (cylinders/sectors)", 608}, - {" w write disklabel to disk", 609}, - {" x link BSD partition to non-BSD partition", 610}, - {"Partition %s has invalid starting sector 0.\n", 611}, - {"Reading disklabel of %s at sector %d.\n", 612}, - {"There is no *BSD partition on %s.\n", 613}, - {"BSD disklabel command (m for help): ", 614}, - {"type: %s\n", 615}, - {"type: %d\n", 616}, - {"disk: %.*s\n", 617}, - {"label: %.*s\n", 618}, - {"flags:", 619}, - {" removable", 620}, - {" ecc", 621}, - {" badsect", 622}, - {"bytes/sector: %ld\n", 623}, - {"sectors/track: %ld\n", 624}, - {"tracks/cylinder: %ld\n", 625}, - {"sectors/cylinder: %ld\n", 626}, - {"cylinders: %ld\n", 627}, - {"rpm: %d\n", 628}, - {"interleave: %d\n", 629}, - {"trackskew: %d\n", 630}, - {"cylinderskew: %d\n", 631}, - {"headswitch: %ld\t\t# milliseconds\n", 632}, - {"track-to-track seek: %ld\t# milliseconds\n", 633}, - {"drivedata: ", 634}, +BSD label for device: %s\n", 606}, + {" d delete a BSD partition", 607}, + {" e edit drive data", 608}, + {" i install bootstrap", 609}, + {" l list known filesystem types", 610}, + {" n add a new BSD partition", 611}, + {" p print BSD partition table", 612}, + {" s show complete disklabel", 613}, + {" t change a partition's filesystem id", 614}, + {" u change units (cylinders/sectors)", 615}, + {" w write disklabel to disk", 616}, + {" x link BSD partition to non-BSD partition", 617}, + {"Partition %s has invalid starting sector 0.\n", 618}, + {"Reading disklabel of %s at sector %d.\n", 619}, + {"There is no *BSD partition on %s.\n", 620}, + {"BSD disklabel command (m for help): ", 621}, + {"type: %s\n", 622}, + {"type: %d\n", 623}, + {"disk: %.*s\n", 624}, + {"label: %.*s\n", 625}, + {"flags:", 626}, + {" removable", 627}, + {" ecc", 628}, + {" badsect", 629}, + {"bytes/sector: %ld\n", 630}, + {"sectors/track: %ld\n", 631}, + {"tracks/cylinder: %ld\n", 632}, + {"sectors/cylinder: %ld\n", 633}, + {"cylinders: %ld\n", 634}, + {"rpm: %d\n", 635}, + {"interleave: %d\n", 636}, + {"trackskew: %d\n", 637}, + {"cylinderskew: %d\n", 638}, + {"headswitch: %ld\t\t# milliseconds\n", 639}, + {"track-to-track seek: %ld\t# milliseconds\n", 640}, + {"drivedata: ", 641}, {"\ \n\ -%d partitions:\n", 635}, - {"# start end size fstype [fsize bsize cpg]\n", 636}, - {"Writing disklabel to %s.\n", 637}, - {"%s contains no disklabel.\n", 638}, - {"Do you want to create a disklabel? (y/n) ", 639}, - {"bytes/sector", 640}, - {"sectors/track", 641}, - {"tracks/cylinder", 642}, - {"sectors/cylinder", 643}, - {"Must be <= sectors/track * tracks/cylinder (default).\n", 644}, - {"rpm", 645}, - {"interleave", 646}, - {"trackskew", 647}, - {"cylinderskew", 648}, - {"headswitch", 649}, - {"track-to-track seek", 650}, - {"Bootstrap: %sboot -> boot%s (%s): ", 651}, - {"Bootstrap overlaps with disk label!\n", 652}, - {"Bootstrap installed on %s.\n", 653}, - {"Partition (a-%c): ", 654}, - {"This partition already exists.\n", 655}, - {"Warning: too many partitions (%d, maximum is %d).\n", 656}, +%d partitions:\n", 642}, + {"# start end size fstype [fsize bsize cpg]\n", 643}, + {"Writing disklabel to %s.\n", 644}, + {"%s contains no disklabel.\n", 645}, + {"Do you want to create a disklabel? (y/n) ", 646}, + {"bytes/sector", 647}, + {"sectors/track", 648}, + {"tracks/cylinder", 649}, + {"sectors/cylinder", 650}, + {"Must be <= sectors/track * tracks/cylinder (default).\n", 651}, + {"rpm", 652}, + {"interleave", 653}, + {"trackskew", 654}, + {"cylinderskew", 655}, + {"headswitch", 656}, + {"track-to-track seek", 657}, + {"Bootstrap: %sboot -> boot%s (%s): ", 658}, + {"Bootstrap overlaps with disk label!\n", 659}, + {"Bootstrap installed on %s.\n", 660}, + {"Partition (a-%c): ", 661}, + {"This partition already exists.\n", 662}, + {"Warning: too many partitions (%d, maximum is %d).\n", 663}, {"\ \n\ -Syncing disks.\n", 657}, - {"SGI volhdr", 658}, - {"SGI trkrepl", 659}, - {"SGI secrepl", 660}, - {"SGI raw", 661}, - {"SGI bsd", 662}, - {"SGI sysv", 663}, - {"SGI volume", 664}, - {"SGI efs", 665}, - {"SGI lvol", 666}, - {"SGI rlvol", 667}, - {"SGI xfs", 668}, - {"SGI xlvol", 669}, - {"SGI rxlvol", 670}, - {"Linux swap", 671}, - {"Linux native", 672}, - {"Linux LVM", 673}, +Syncing disks.\n", 664}, + {"SGI volhdr", 665}, + {"SGI trkrepl", 666}, + {"SGI secrepl", 667}, + {"SGI raw", 668}, + {"SGI bsd", 669}, + {"SGI sysv", 670}, + {"SGI volume", 671}, + {"SGI efs", 672}, + {"SGI lvol", 673}, + {"SGI rlvol", 674}, + {"SGI xfs", 675}, + {"SGI xlvol", 676}, + {"SGI rxlvol", 677}, + {"Linux swap", 678}, + {"Linux native", 679}, + {"Linux LVM", 680}, {"\ According to MIPS Computer Systems, Inc the Label must not contain more than \ -512 bytes\n", 674}, - {"Detected sgi disklabel with wrong checksum.\n", 675}, +512 bytes\n", 681}, + {"Detected sgi disklabel with wrong checksum.\n", 682}, {"\ \n\ Disk %s (SGI disk label): %d heads, %d sectors\n\ @@ -906,139 +919,139 @@ Disk %s (SGI disk label): %d heads, %d sectors\n\ %d extra sects/cyl, interleave %d:1\n\ %s\n\ Units = %s of %d * 512 bytes\n\ -\n", 676}, +\n", 683}, {"\ \n\ Disk %s (SGI disk label): %d heads, %d sectors, %d cylinders\n\ Units = %s of %d * 512 bytes\n\ -\n", 677}, +\n", 684}, {"\ ----- partitions -----\n\ -%*s Info Start End Sectors Id System\n", 678}, +%*s Info Start End Sectors Id System\n", 685}, {"\ ----- bootinfo -----\n\ Bootfile: %s\n\ ------ directory entries -----\n", 679}, - {"%2d: %-10s sector%5u size%8u\n", 680}, +----- directory entries -----\n", 686}, + {"%2d: %-10s sector%5u size%8u\n", 687}, {"\ \n\ Invalid Bootfile!\n\ \tThe bootfile must be an absolute non-zero pathname,\n\ -\te.g. \"/unix\" or \"/unix.save\".\n", 681}, +\te.g. \"/unix\" or \"/unix.save\".\n", 688}, {"\ \n\ -\tName of Bootfile too long: 16 bytes maximum.\n", 682}, +\tName of Bootfile too long: 16 bytes maximum.\n", 689}, {"\ \n\ -\tBootfile must have a fully qualified pathname.\n", 683}, +\tBootfile must have a fully qualified pathname.\n", 690}, {"\ \n\ \tBe aware, that the bootfile is not checked for existence.\n\ -\tSGI's default is \"/unix\" and for backup \"/unix.save\".\n", 684}, +\tSGI's default is \"/unix\" and for backup \"/unix.save\".\n", 691}, {"\ \n\ -\tBootfile is changed to \"%s\".\n", 685}, - {"More than one entire disk entry present.\n", 686}, - {"No partitions defined\n", 687}, - {"IRIX likes when Partition 11 covers the entire disk.\n", 688}, +\tBootfile is changed to \"%s\".\n", 692}, + {"More than one entire disk entry present.\n", 693}, + {"No partitions defined\n", 694}, + {"IRIX likes when Partition 11 covers the entire disk.\n", 695}, {"\ The entire disk partition should start at block 0,\n\ -not at diskblock %d.\n", 689}, +not at diskblock %d.\n", 696}, {"\ The entire disk partition is only %d diskblock large,\n\ -but the disk is %d diskblocks long.\n", 690}, - {"One Partition (#11) should cover the entire disk.\n", 691}, - {"Partition %d does not start on cylinder boundary.\n", 692}, - {"Partition %d does not end on cylinder boundary.\n", 693}, - {"The Partition %d and %d overlap by %d sectors.\n", 694}, - {"Unused gap of %8d sectors - sectors %8d-%d\n", 695}, +but the disk is %d diskblocks long.\n", 697}, + {"One Partition (#11) should cover the entire disk.\n", 698}, + {"Partition %d does not start on cylinder boundary.\n", 699}, + {"Partition %d does not end on cylinder boundary.\n", 700}, + {"The Partition %d and %d overlap by %d sectors.\n", 701}, + {"Unused gap of %8d sectors - sectors %8d-%d\n", 702}, {"\ \n\ -The boot partition does not exist.\n", 696}, +The boot partition does not exist.\n", 703}, {"\ \n\ -The swap partition does not exist.\n", 697}, +The swap partition does not exist.\n", 704}, {"\ \n\ -The swap partition has no swap type.\n", 698}, - {"\tYou have chosen an unusual boot file name.\n", 699}, - {"Sorry You may change the Tag of non-empty partitions.\n", 700}, +The swap partition has no swap type.\n", 705}, + {"\tYou have chosen an unusual boot file name.\n", 706}, + {"Sorry You may change the Tag of non-empty partitions.\n", 707}, {"\ It is highly recommended that the partition at offset 0\n\ is of type \"SGI volhdr\", the IRIX system will rely on it to\n\ retrieve from its directory standalone tools like sash and fx.\n\ Only the \"SGI volume\" entire disk section may violate this.\n\ -Type YES if you are sure about tagging this partition differently.\n", 701}, - {"Do You know, You got a partition overlap on the disk?\n", 702}, - {"Attempting to generate entire disk entry automatically.\n", 703}, - {"The entire disk is already covered with partitions.\n", 704}, - {"You got a partition overlap on the disk. Fix it first!\n", 705}, +Type YES if you are sure about tagging this partition differently.\n", 708}, + {"Do You know, You got a partition overlap on the disk?\n", 709}, + {"Attempting to generate entire disk entry automatically.\n", 710}, + {"The entire disk is already covered with partitions.\n", 711}, + {"You got a partition overlap on the disk. Fix it first!\n", 712}, {"\ It is highly recommended that eleventh partition\n\ -covers the entire disk and is of type `SGI volume'\n", 706}, - {"You will get a partition overlap on the disk. Fix it first!\n", 707}, - {" Last %s", 708}, +covers the entire disk and is of type `SGI volume'\n", 713}, + {"You will get a partition overlap on the disk. Fix it first!\n", 714}, + {" Last %s", 715}, {"\ Building a new SGI disklabel. Changes will remain in memory only,\n\ until you decide to write them. After that, of course, the previous\n\ content will be unrecoverably lost.\n\ -\n", 709}, - {"Trying to keep parameters of partition %d.\n", 710}, - {"ID=%02x\tSTART=%d\tLENGTH=%d\n", 711}, - {"Empty", 712}, - {"SunOS root", 713}, - {"SunOS swap", 714}, - {"SunOS usr", 715}, - {"Whole disk", 716}, - {"SunOS stand", 717}, - {"SunOS var", 718}, - {"SunOS home", 719}, +\n", 716}, + {"Trying to keep parameters of partition %d.\n", 717}, + {"ID=%02x\tSTART=%d\tLENGTH=%d\n", 718}, + {"Empty", 719}, + {"SunOS root", 720}, + {"SunOS swap", 721}, + {"SunOS usr", 722}, + {"Whole disk", 723}, + {"SunOS stand", 724}, + {"SunOS var", 725}, + {"SunOS home", 726}, {"\ Detected sun disklabel with wrong checksum.\n\ Probably you'll have to set all the values,\n\ e.g. heads, sectors, cylinders and partitions\n\ -or force a fresh label (s command in main menu)\n", 720}, - {"Autoconfigure found a %s%s%s\n", 721}, +or force a fresh label (s command in main menu)\n", 727}, + {"Autoconfigure found a %s%s%s\n", 728}, {"\ Building a new sun disklabel. Changes will remain in memory only,\n\ until you decide to write them. After that, of course, the previous\n\ content won't be recoverable.\n\ -\n", 722}, +\n", 729}, {"\ Drive type\n\ ? auto configure\n\ - 0 custom (with hardware detected defaults)", 723}, - {"Select type (? for auto, 0 for custom): ", 724}, - {"Autoconfigure failed.\n", 725}, - {"Sectors/track", 726}, - {"Alternate cylinders", 727}, - {"Physical cylinders", 728}, - {"Rotation speed (rpm)", 729}, - {"Interleave factor", 730}, - {"Extra sectors per cylinder", 731}, - {"You may change all the disk params from the x menu", 732}, - {"3,5\" floppy", 733}, - {"Linux custom", 734}, - {"Partition %d doesn't end on cylinder boundary\n", 735}, - {"Partition %d overlaps with others in sectors %d-%d\n", 736}, - {"Unused gap - sectors 0-%d\n", 737}, - {"Unused gap - sectors %d-%d\n", 738}, + 0 custom (with hardware detected defaults)", 730}, + {"Select type (? for auto, 0 for custom): ", 731}, + {"Autoconfigure failed.\n", 732}, + {"Sectors/track", 733}, + {"Alternate cylinders", 734}, + {"Physical cylinders", 735}, + {"Rotation speed (rpm)", 736}, + {"Interleave factor", 737}, + {"Extra sectors per cylinder", 738}, + {"You may change all the disk params from the x menu", 739}, + {"3,5\" floppy", 740}, + {"Linux custom", 741}, + {"Partition %d doesn't end on cylinder boundary\n", 742}, + {"Partition %d overlaps with others in sectors %d-%d\n", 743}, + {"Unused gap - sectors 0-%d\n", 744}, + {"Unused gap - sectors %d-%d\n", 745}, {"\ Other partitions already cover the whole disk.\n\ -Delete some/shrink them before retry.\n", 739}, +Delete some/shrink them before retry.\n", 746}, {"\ You haven't covered the whole disk with the 3rd partition, but your value\n\ %d %s covers some other partition. Your entry has been changed\n\ -to %d %s\n", 740}, +to %d %s\n", 747}, {"\ If you want to maintain SunOS/Solaris compatibility, consider leaving this\n\ -partition as Whole disk (5), starting at 0, with %u sectors\n", 741}, +partition as Whole disk (5), starting at 0, with %u sectors\n", 748}, {"\ It is highly recommended that the partition at offset 0\n\ is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n\ there may destroy your partition table and bootblock.\n\ Type YES if you're very sure you would like that partition\n\ -tagged with 82 (Linux swap): ", 742}, +tagged with 82 (Linux swap): ", 749}, {"\ \n\ Disk %s (Sun disk label): %d heads, %d sectors, %d rpm\n\ @@ -1046,1099 +1059,1126 @@ Disk %s (Sun disk label): %d heads, %d sectors, %d rpm\n\ %d extra sects/cyl, interleave %d:1\n\ %s\n\ Units = %s of %d * 512 bytes\n\ -\n", 743}, +\n", 750}, {"\ \n\ Disk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n\ Units = %s of %d * 512 bytes\n\ -\n", 744}, - {"%*s Flag Start End Blocks Id System\n", 745}, - {"Number of alternate cylinders", 746}, - {"Number of physical cylinders", 747}, - {"FAT12", 748}, - {"XENIX root", 749}, - {"XENIX usr", 750}, - {"FAT16 <32M", 751}, - {"Extended", 752}, - {"FAT16", 753}, - {"HPFS/NTFS", 754}, - {"AIX", 755}, - {"AIX bootable", 756}, - {"OS/2 Boot Manager", 757}, - {"Win95 FAT32", 758}, - {"Win95 FAT32 (LBA)", 759}, - {"Win95 FAT16 (LBA)", 760}, - {"Win95 Ext'd (LBA)", 761}, - {"OPUS", 762}, - {"Hidden FAT12", 763}, - {"Compaq diagnostics", 764}, - {"Hidden FAT16 <32M", 765}, - {"Hidden FAT16", 766}, - {"Hidden HPFS/NTFS", 767}, - {"AST Windows swapfile", 768}, - {"Hidden Win95 FAT32", 769}, - {"Hidden Win95 FAT32 (LBA)", 770}, - {"Hidden Win95 FAT16 (LBA)", 771}, - {"NEC DOS", 772}, - {"PartitionMagic recovery", 773}, - {"Venix 80286", 774}, - {"PPC PReP Boot", 775}, - {"SFS", 776}, - {"QNX4.x", 777}, - {"QNX4.x 2nd part", 778}, - {"QNX4.x 3rd part", 779}, - {"OnTrack DM", 780}, - {"OnTrack DM6 Aux1", 781}, - {"CP/M", 782}, - {"OnTrack DM6 Aux3", 783}, - {"OnTrackDM6", 784}, - {"EZ-Drive", 785}, - {"Golden Bow", 786}, - {"Priam Edisk", 787}, - {"SpeedStor", 788}, - {"GNU HURD or SysV", 789}, - {"Novell Netware 286", 790}, - {"Novell Netware 386", 791}, - {"DiskSecure Multi-Boot", 792}, - {"PC/IX", 793}, - {"Old Minix", 794}, - {"Minix / old Linux", 795}, - {"OS/2 hidden C: drive", 796}, - {"Linux extended", 797}, - {"NTFS volume set", 798}, - {"Amoeba", 799}, - {"Amoeba BBT", 800}, - {"BSD/OS", 801}, - {"IBM Thinkpad hibernation", 802}, - {"BSD/386", 803}, - {"OpenBSD", 804}, - {"NeXTSTEP", 805}, - {"BSDI fs", 806}, - {"BSDI swap", 807}, - {"DRDOS/sec (FAT-12)", 808}, - {"DRDOS/sec (FAT-16 < 32M)", 809}, - {"DRDOS/sec (FAT-16)", 810}, - {"Syrinx", 811}, - {"CP/M / CTOS / ...", 812}, - {"DOS access", 813}, - {"DOS R/O", 814}, - {"BeOS fs", 815}, - {"DOS secondary", 816}, - {"Linux raid autodetect", 817}, - {"LANstep", 818}, - {"BBT", 819}, - {"seek error on %s - cannot seek to %lu\n", 820}, - {"seek error: wanted 0x%08x%08x, got 0x%08x%08x\n", 821}, - {"out of memory - giving up\n", 822}, - {"read error on %s - cannot read sector %lu\n", 823}, - {"ERROR: sector %lu does not have an msdos signature\n", 824}, - {"write error on %s - cannot write sector %lu\n", 825}, - {"cannot open partition sector save file (%s)\n", 826}, - {"write error on %s\n", 827}, - {"cannot stat partition restore file (%s)\n", 828}, - {"partition restore file has wrong size - not restoring\n", 829}, - {"out of memory?\n", 830}, - {"cannot open partition restore file (%s)\n", 831}, - {"error reading %s\n", 832}, - {"cannot open device %s for writing\n", 833}, - {"error writing sector %lu on %s\n", 834}, - {"Disk %s: cannot get size\n", 835}, - {"Disk %s: cannot get geometry\n", 836}, - {"\ -Warning: start=%d - this looks like a partition rather than\n\ +\n", 751}, + {"%*s Flag Start End Blocks Id System\n", 752}, + {"Number of alternate cylinders", 753}, + {"Number of physical cylinders", 754}, + {"FAT12", 755}, + {"XENIX root", 756}, + {"XENIX usr", 757}, + {"FAT16 <32M", 758}, + {"Extended", 759}, + {"FAT16", 760}, + {"HPFS/NTFS", 761}, + {"AIX", 762}, + {"AIX bootable", 763}, + {"OS/2 Boot Manager", 764}, + {"Win95 FAT32", 765}, + {"Win95 FAT32 (LBA)", 766}, + {"Win95 FAT16 (LBA)", 767}, + {"Win95 Ext'd (LBA)", 768}, + {"OPUS", 769}, + {"Hidden FAT12", 770}, + {"Compaq diagnostics", 771}, + {"Hidden FAT16 <32M", 772}, + {"Hidden FAT16", 773}, + {"Hidden HPFS/NTFS", 774}, + {"AST Windows swapfile", 775}, + {"Hidden Win95 FAT32", 776}, + {"Hidden Win95 FAT32 (LBA)", 777}, + {"Hidden Win95 FAT16 (LBA)", 778}, + {"NEC DOS", 779}, + {"Plan 9", 780}, + {"PartitionMagic recovery", 781}, + {"Venix 80286", 782}, + {"PPC PReP Boot", 783}, + {"SFS", 784}, + {"QNX4.x", 785}, + {"QNX4.x 2nd part", 786}, + {"QNX4.x 3rd part", 787}, + {"OnTrack DM", 788}, + {"OnTrack DM6 Aux1", 789}, + {"CP/M", 790}, + {"OnTrack DM6 Aux3", 791}, + {"OnTrackDM6", 792}, + {"EZ-Drive", 793}, + {"Golden Bow", 794}, + {"Priam Edisk", 795}, + {"SpeedStor", 796}, + {"GNU HURD or SysV", 797}, + {"Novell Netware 286", 798}, + {"Novell Netware 386", 799}, + {"DiskSecure Multi-Boot", 800}, + {"PC/IX", 801}, + {"Old Minix", 802}, + {"Minix / old Linux", 803}, + {"OS/2 hidden C: drive", 804}, + {"Linux extended", 805}, + {"NTFS volume set", 806}, + {"Amoeba", 807}, + {"Amoeba BBT", 808}, + {"BSD/OS", 809}, + {"IBM Thinkpad hibernation", 810}, + {"BSD/386", 811}, + {"OpenBSD", 812}, + {"NeXTSTEP", 813}, + {"BSDI fs", 814}, + {"BSDI swap", 815}, + {"DRDOS/sec (FAT-12)", 816}, + {"DRDOS/sec (FAT-16 < 32M)", 817}, + {"DRDOS/sec (FAT-16)", 818}, + {"Syrinx", 819}, + {"Non-FS data", 820}, + {"CP/M / CTOS / ...", 821}, + {"DOS access", 822}, + {"DOS R/O", 823}, + {"BeOS fs", 824}, + {"DOS secondary", 825}, + {"Linux raid autodetect", 826}, + {"LANstep", 827}, + {"BBT", 828}, + {"seek error on %s - cannot seek to %lu\n", 829}, + {"seek error: wanted 0x%08x%08x, got 0x%08x%08x\n", 830}, + {"out of memory - giving up\n", 831}, + {"read error on %s - cannot read sector %lu\n", 832}, + {"ERROR: sector %lu does not have an msdos signature\n", 833}, + {"write error on %s - cannot write sector %lu\n", 834}, + {"cannot open partition sector save file (%s)\n", 835}, + {"write error on %s\n", 836}, + {"cannot stat partition restore file (%s)\n", 837}, + {"partition restore file has wrong size - not restoring\n", 838}, + {"out of memory?\n", 839}, + {"cannot open partition restore file (%s)\n", 840}, + {"error reading %s\n", 841}, + {"cannot open device %s for writing\n", 842}, + {"error writing sector %lu on %s\n", 843}, + {"Disk %s: cannot get size\n", 844}, + {"Disk %s: cannot get geometry\n", 845}, + {"\ +Warning: start=%lu - this looks like a partition rather than\n\ the entire disk. Using fdisk on it is probably meaningless.\n\ -[Use the --force option if you really want this]\n", 837}, - {"Warning: HDIO_GETGEO says that there are %d heads\n", 838}, - {"Warning: HDIO_GETGEO says that there are %d sectors\n", 839}, - {"Warning: BLKGETSIZE/HDIO_GETGEO says that there are %d cylinders\n", 840}, +[Use the --force option if you really want this]\n", 846}, + {"Warning: HDIO_GETGEO says that there are %lu heads\n", 847}, + {"Warning: HDIO_GETGEO says that there are %lu sectors\n", 848}, + {"Warning: BLKGETSIZE/HDIO_GETGEO says that there are %lu cylinders\n", 849}, {"\ -Warning: unlikely number of sectors (%d) - usually at most 63\n\ -This will give problems with all software that uses C/H/S addressing.\n", 841}, +Warning: unlikely number of sectors (%lu) - usually at most 63\n\ +This will give problems with all software that uses C/H/S addressing.\n", 850}, {"\ \n\ -Disk %s: %lu cylinders, %lu heads, %lu sectors/track\n", 842}, +Disk %s: %lu cylinders, %lu heads, %lu sectors/track\n", 851}, {"\ -%s of partition %s has impossible value for head: %d (should be in 0-%d)\n", 843}, +%s of partition %s has impossible value for head: %lu (should be in 0-%lu)\n", 852}, {"\ -%s of partition %s has impossible value for sector: %d (should be in 1-%d)\n", 844}, +%s of partition %s has impossible value for sector: %lu (should be in \ +1-%lu)\n", 853}, {"\ -%s of partition %s has impossible value for cylinders: %d (should be in \ -0-%d)\n", 845}, +%s of partition %s has impossible value for cylinders: %lu (should be in \ +0-%lu)\n", 854}, {"\ Id Name\n\ -\n", 846}, - {"Re-reading the partition table ...\n", 847}, +\n", 855}, + {"Re-reading the partition table ...\n", 856}, {"\ The command to re-read the partition table failed\n\ -Reboot your system now, before using mkfs\n", 848}, - {"Error closing %s\n", 849}, - {"%s: no such partition\n", 850}, - {"unrecognized format - using sectors\n", 851}, - {"# partition table of %s\n", 852}, - {"unimplemented format - using %s\n", 853}, +Reboot your system now, before using mkfs\n", 857}, + {"Error closing %s\n", 858}, + {"%s: no such partition\n", 859}, + {"unrecognized format - using sectors\n", 860}, + {"# partition table of %s\n", 861}, + {"unimplemented format - using %s\n", 862}, {"\ Units = cylinders of %lu bytes, blocks of 1024 bytes, counting from %d\n\ -\n", 854}, - {" Device Boot Start End #cyls #blocks Id System\n", 855}, +\n", 863}, + {" Device Boot Start End #cyls #blocks Id System\n", 864}, {"\ Units = sectors of 512 bytes, counting from %d\n\ -\n", 856}, - {" Device Boot Start End #sectors Id System\n", 857}, +\n", 865}, + {" Device Boot Start End #sectors Id System\n", 866}, {"\ Units = blocks of 1024 bytes, counting from %d\n\ -\n", 858}, - {" Device Boot Start End #blocks Id System\n", 859}, +\n", 867}, + {" Device Boot Start End #blocks Id System\n", 868}, {"\ Units = megabytes of 1048576 bytes, blocks of 1024 bytes, counting from %d\n\ -\n", 860}, - {" Device Boot Start End MB #blocks Id System\n", 861}, - {"\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 862}, - {"\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 863}, - {"partition ends on cylinder %ld, beyond the end of the disk\n", 864}, - {"No partitions found\n", 865}, +\n", 869}, + {" Device Boot Start End MB #blocks Id System\n", 870}, + {"\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 871}, + {"\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 872}, + {"partition ends on cylinder %ld, beyond the end of the disk\n", 873}, + {"No partitions found\n", 874}, {"\ Warning: The first partition looks like it was made\n\ for C/H/S=*/%ld/%ld (instead of %ld/%ld/%ld).\n\ -For this listing I'll assume that geometry.\n", 866}, - {"no partition table present.\n", 867}, - {"strange, only %d partitions defined.\n", 868}, - {"Warning: partition %s has size 0 but is not marked Empty\n", 869}, - {"Warning: partition %s has size 0 and is bootable\n", 870}, - {"Warning: partition %s has size 0 and nonzero start\n", 871}, - {"Warning: partition %s ", 872}, - {"is not contained in partition %s\n", 873}, - {"Warning: partitions %s ", 874}, - {"and %s overlap\n", 875}, - {"Warning: partition %s contains part of ", 876}, - {"the partition table (sector %lu),\n", 877}, - {"and will destroy it when filled\n", 878}, - {"Warning: partition %s starts at sector 0\n", 879}, - {"Warning: partition %s extends past end of disk\n", 880}, - {"Among the primary partitions, at most one can be extended\n", 881}, - {" (although this is not a problem under Linux)\n", 882}, - {"Warning: partition %s does not start at a cylinder boundary\n", 883}, - {"Warning: partition %s does not end at a cylinder boundary\n", 884}, +For this listing I'll assume that geometry.\n", 875}, + {"no partition table present.\n", 876}, + {"strange, only %d partitions defined.\n", 877}, + {"Warning: partition %s has size 0 but is not marked Empty\n", 878}, + {"Warning: partition %s has size 0 and is bootable\n", 879}, + {"Warning: partition %s has size 0 and nonzero start\n", 880}, + {"Warning: partition %s ", 881}, + {"is not contained in partition %s\n", 882}, + {"Warning: partitions %s ", 883}, + {"and %s overlap\n", 884}, + {"Warning: partition %s contains part of ", 885}, + {"the partition table (sector %lu),\n", 886}, + {"and will destroy it when filled\n", 887}, + {"Warning: partition %s starts at sector 0\n", 888}, + {"Warning: partition %s extends past end of disk\n", 889}, + {"Among the primary partitions, at most one can be extended\n", 890}, + {" (although this is not a problem under Linux)\n", 891}, + {"Warning: partition %s does not start at a cylinder boundary\n", 892}, + {"Warning: partition %s does not end at a cylinder boundary\n", 893}, {"\ Warning: more than one primary partition is marked bootable (active)\n\ -This does not matter for LILO, but the DOS MBR will not boot this disk.\n", 885}, +This does not matter for LILO, but the DOS MBR will not boot this disk.\n", 894}, {"\ Warning: usually one can boot from primary partitions only\n\ -LILO disregards the `bootable' flag.\n", 886}, +LILO disregards the `bootable' flag.\n", 895}, {"\ Warning: no primary partition is marked bootable (active)\n\ -This does not matter for LILO, but the DOS MBR will not boot this disk.\n", 887}, - {"\ -partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 888}, - {"partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 889}, - {"partition %s ends on cylinder %ld, beyond the end of the disk\n", 890}, - {"Warning: shifted start of the extd partition from %ld to %ld\n", 891}, - {"(For listing purposes only. Do not change its contents.)\n", 892}, - {"Warning: extended partition does not start at a cylinder boundary.\n", 893}, - {"DOS and Linux will interpret the contents differently.\n", 894}, - {"too many partitions - ignoring those past nr (%d)\n", 895}, - {"tree of partitions?\n", 896}, - {"detected Disk Manager - unable to handle that\n", 897}, - {"DM6 signature found - giving up\n", 898}, - {"strange..., an extended partition of size 0?\n", 899}, - {"strange..., a BSD partition of size 0?\n", 900}, - {" %s: unrecognized partition\n", 901}, - {"-n flag was given: Nothing changed\n", 902}, - {"Failed saving the old sectors - aborting\n", 903}, - {"Failed writing the partition on %s\n", 904}, - {"long or incomplete input line - quitting\n", 905}, - {"input error: `=' expected after %s field\n", 906}, - {"input error: unexpected character %c after %s field\n", 907}, - {"unrecognized input: %s\n", 908}, - {"number too big\n", 909}, - {"trailing junk after number\n", 910}, - {"no room for partition descriptor\n", 911}, - {"cannot build surrounding extended partition\n", 912}, - {"too many input fields\n", 913}, - {"No room for more\n", 914}, - {"Illegal type\n", 915}, - {"Warning: given size (%lu) exceeds max allowable size (%lu)\n", 916}, - {"Warning: empty partition\n", 917}, - {"Warning: bad partition start (earliest %lu)\n", 918}, - {"unrecognized bootable flag - choose - or *\n", 919}, - {"partial c,h,s specification?\n", 920}, - {"Extended partition not where expected\n", 921}, - {"bad input\n", 922}, - {"too many partitions\n", 923}, +This does not matter for LILO, but the DOS MBR will not boot this disk.\n", 896}, + {"\ +partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 897}, + {"partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 898}, + {"partition %s ends on cylinder %ld, beyond the end of the disk\n", 899}, + {"Warning: shifted start of the extd partition from %ld to %ld\n", 900}, + {"(For listing purposes only. Do not change its contents.)\n", 901}, + {"Warning: extended partition does not start at a cylinder boundary.\n", 902}, + {"DOS and Linux will interpret the contents differently.\n", 903}, + {"too many partitions - ignoring those past nr (%d)\n", 904}, + {"tree of partitions?\n", 905}, + {"detected Disk Manager - unable to handle that\n", 906}, + {"DM6 signature found - giving up\n", 907}, + {"strange..., an extended partition of size 0?\n", 908}, + {"strange..., a BSD partition of size 0?\n", 909}, + {" %s: unrecognized partition\n", 910}, + {"-n flag was given: Nothing changed\n", 911}, + {"Failed saving the old sectors - aborting\n", 912}, + {"Failed writing the partition on %s\n", 913}, + {"long or incomplete input line - quitting\n", 914}, + {"input error: `=' expected after %s field\n", 915}, + {"input error: unexpected character %c after %s field\n", 916}, + {"unrecognized input: %s\n", 917}, + {"number too big\n", 918}, + {"trailing junk after number\n", 919}, + {"no room for partition descriptor\n", 920}, + {"cannot build surrounding extended partition\n", 921}, + {"too many input fields\n", 922}, + {"No room for more\n", 923}, + {"Illegal type\n", 924}, + {"Warning: given size (%lu) exceeds max allowable size (%lu)\n", 925}, + {"Warning: empty partition\n", 926}, + {"Warning: bad partition start (earliest %lu)\n", 927}, + {"unrecognized bootable flag - choose - or *\n", 928}, + {"partial c,h,s specification?\n", 929}, + {"Extended partition not where expected\n", 930}, + {"bad input\n", 931}, + {"too many partitions\n", 932}, {"\ Input in the following format; absent fields get a default value.\n\ \n\ -Usually you only need to specify and (and perhaps ).\n", 924}, - {"version", 925}, - {"Usage: %s [options] device ...\n", 926}, - {"device: something like /dev/hda or /dev/sda", 927}, - {"useful options:", 928}, - {" -s [or --show-size]: list size of a partition", 929}, - {" -c [or --id]: print or change partition Id", 930}, - {" -l [or --list]: list partitions of each device", 931}, - {" -d [or --dump]: idem, but in a format suitable for later input", 932}, - {" -i [or --increment]: number cylinders etc. from 1 instead of from 0", 933}, +Usually you only need to specify and (and perhaps ).\n", 933}, + {"version", 934}, + {"Usage: %s [options] device ...\n", 935}, + {"device: something like /dev/hda or /dev/sda", 936}, + {"useful options:", 937}, + {" -s [or --show-size]: list size of a partition", 938}, + {" -c [or --id]: print or change partition Id", 939}, + {" -l [or --list]: list partitions of each device", 940}, + {" -d [or --dump]: idem, but in a format suitable for later input", 941}, + {" -i [or --increment]: number cylinders etc. from 1 instead of from 0", 942}, {"\ -uS, -uB, -uC, -uM: accept/report in units of \ -sectors/blocks/cylinders/MB", 934}, - {" -T [or --list-types]:list the known partition types", 935}, - {" -D [or --DOS]: for DOS-compatibility: waste a little space", 936}, - {" -R [or --re-read]: make kernel reread partition table", 937}, - {" -N# : change only the partition with number #", 938}, - {" -n : do not actually write to disk", 939}, - {"\ - -O file : save the sectors that will be overwritten to file", 940}, - {" -I file : restore these sectors again", 941}, - {" -v [or --version]: print version", 942}, - {" -? [or --help]: print this message", 943}, - {"dangerous options:", 944}, - {" -g [or --show-geometry]: print the kernel's idea of the geometry", 945}, +sectors/blocks/cylinders/MB", 943}, + {" -T [or --list-types]:list the known partition types", 944}, + {" -D [or --DOS]: for DOS-compatibility: waste a little space", 945}, + {" -R [or --re-read]: make kernel reread partition table", 946}, + {" -N# : change only the partition with number #", 947}, + {" -n : do not actually write to disk", 948}, + {"\ + -O file : save the sectors that will be overwritten to file", 949}, + {" -I file : restore these sectors again", 950}, + {" -v [or --version]: print version", 951}, + {" -? [or --help]: print this message", 952}, + {"dangerous options:", 953}, + {" -g [or --show-geometry]: print the kernel's idea of the geometry", 954}, {"\ -x [or --show-extended]: also list extended partitions on output\n\ - or expect descriptors for them on input", 946}, - {"\ - -L [or --Linux]: do not complain about things irrelevant for Linux", 947}, - {" -q [or --quiet]: suppress warning messages", 948}, - {" You can override the detected geometry using:", 949}, - {" -C# [or --cylinders #]:set the number of cylinders to use", 950}, - {" -H# [or --heads #]: set the number of heads to use", 951}, - {" -S# [or --sectors #]: set the number of sectors to use", 952}, - {"You can disable all consistency checking with:", 953}, - {" -f [or --force]: do what I say, even if it is stupid", 954}, - {"Usage:", 955}, - {"%s device\t\t list active partitions on device\n", 956}, - {"%s device n1 n2 ... activate partitions n1 ..., inactivate the rest\n", 957}, - {"%s -An device\t activate partition n, inactivate the other ones\n", 958}, - {"no command?\n", 959}, - {"total: %d blocks\n", 960}, - {"usage: sfdisk --print-id device partition-number\n", 961}, - {"usage: sfdisk --change-id device partition-number Id\n", 962}, - {"usage: sfdisk --id device partition-number [Id]\n", 963}, - {"can specify only one device (except with -l or -s)\n", 964}, - {"cannot open %s %s\n", 965}, - {"read-write", 966}, - {"for reading", 967}, - {"%s: OK\n", 968}, - {"%s: %ld cylinders, %ld heads, %ld sectors/track\n", 969}, - {"BLKGETSIZE ioctl failed for %s\n", 970}, - {"bad active byte: 0x%x instead of 0x80\n", 971}, + or expect descriptors for them on input", 955}, + {"\ + -L [or --Linux]: do not complain about things irrelevant for Linux", 956}, + {" -q [or --quiet]: suppress warning messages", 957}, + {" You can override the detected geometry using:", 958}, + {" -C# [or --cylinders #]:set the number of cylinders to use", 959}, + {" -H# [or --heads #]: set the number of heads to use", 960}, + {" -S# [or --sectors #]: set the number of sectors to use", 961}, + {"You can disable all consistency checking with:", 962}, + {" -f [or --force]: do what I say, even if it is stupid", 963}, + {"Usage:", 964}, + {"%s device\t\t list active partitions on device\n", 965}, + {"%s device n1 n2 ... activate partitions n1 ..., inactivate the rest\n", 966}, + {"%s -An device\t activate partition n, inactivate the other ones\n", 967}, + {"no command?\n", 968}, + {"total: %d blocks\n", 969}, + {"usage: sfdisk --print-id device partition-number\n", 970}, + {"usage: sfdisk --change-id device partition-number Id\n", 971}, + {"usage: sfdisk --id device partition-number [Id]\n", 972}, + {"can specify only one device (except with -l or -s)\n", 973}, + {"cannot open %s %s\n", 974}, + {"read-write", 975}, + {"for reading", 976}, + {"%s: OK\n", 977}, + {"%s: %ld cylinders, %ld heads, %ld sectors/track\n", 978}, + {"BLKGETSIZE ioctl failed for %s\n", 979}, + {"bad active byte: 0x%x instead of 0x80\n", 980}, {"\ Done\n\ -\n", 972}, +\n", 981}, {"\ You have %d active primary partitions. This does not matter for LILO,\n\ -but the DOS MBR will only boot a disk with 1 active partition.\n", 973}, - {"partition %s has id %x and is not hidden\n", 974}, - {"Bad Id %x\n", 975}, - {"This disk is currently in use.\n", 976}, - {"Fatal error: cannot find %s\n", 977}, - {"Warning: %s is not a block device\n", 978}, - {"Checking that no-one is using this disk right now ...\n", 979}, +but the DOS MBR will only boot a disk with 1 active partition.\n", 982}, + {"partition %s has id %x and is not hidden\n", 983}, + {"Bad Id %lx\n", 984}, + {"This disk is currently in use.\n", 985}, + {"Fatal error: cannot find %s\n", 986}, + {"Warning: %s is not a block device\n", 987}, + {"Checking that no-one is using this disk right now ...\n", 988}, {"\ \n\ This disk is currently in use - repartitioning is probably a bad idea.\n\ Umount all file systems, and swapoff all swap partitions on this disk.\n\ -Use the --no-reread flag to suppress this check.\n", 980}, - {"Use the --force flag to overrule all checks.\n", 981}, - {"OK\n", 982}, - {"Old situation:\n", 983}, - {"Partition %d does not exist, cannot change it\n", 984}, - {"New situation:\n", 985}, +Use the --no-reread flag to suppress this check.\n", 989}, + {"Use the --force flag to overrule all checks.\n", 990}, + {"OK\n", 991}, + {"Old situation:\n", 992}, + {"Partition %d does not exist, cannot change it\n", 993}, + {"New situation:\n", 994}, {"\ I don't like these partitions - nothing changed.\n\ -(If you really want this, use the --force option.)\n", 986}, - {"I don't like this - probably you should answer No\n", 987}, - {"Are you satisfied with this? [ynq] ", 988}, - {"Do you want to write this to disk? [ynq] ", 989}, +(If you really want this, use the --force option.)\n", 995}, + {"I don't like this - probably you should answer No\n", 996}, + {"Are you satisfied with this? [ynq] ", 997}, + {"Do you want to write this to disk? [ynq] ", 998}, {"\ \n\ -sfdisk: premature end of input\n", 990}, - {"Quitting - nothing changed\n", 991}, - {"Please answer one of y,n,q\n", 992}, +sfdisk: premature end of input\n", 999}, + {"Quitting - nothing changed\n", 1000}, + {"Please answer one of y,n,q\n", 1001}, {"\ Successfully wrote the new partition table\n\ -\n", 993}, +\n", 1002}, {"\ If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)\n\ to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1\n\ -(See fdisk(8).)\n", 994}, - {"usage: banner [-w width]\n", 995}, - {"Message: ", 996}, - {"The character '%c' is not in my character set", 997}, - {"Message '%s' is OK\n", 998}, - {"Try `getopt --help' for more information.\n", 999}, - {"empty long option after -l or --long argument", 1000}, - {"unknown shell after -s or --shell argument", 1001}, - {"Usage: getopt optstring parameters\n", 1002}, - {" getopt [options] [--] optstring parameters\n", 1003}, - {" getopt [options] -o|--options optstring [options] [--]\n", 1004}, - {" parameters\n", 1005}, - {"\ - -a, --alternative Allow long options starting with single -\n", 1006}, - {" -h, --help This small usage guide\n", 1007}, - {" -l, --longoptions=longopts Long options to be recognized\n", 1008}, - {"\ - -n, --name=progname The name under which errors are reported\n", 1009}, - {" -o, --options=optstring Short options to be recognized\n", 1010}, - {" -q, --quiet Disable error reporting by getopt(3)\n", 1011}, - {" -Q, --quiet-output No normal output\n", 1012}, - {" -s, --shell=shell Set shell quoting conventions\n", 1013}, - {" -T, --test Test for getopt(1) version\n", 1014}, - {" -V, --version Output version information\n", 1015}, - {"missing optstring argument", 1016}, - {"getopt (enhanced) 1.0.3\n", 1017}, - {"internal error, contact the author.", 1018}, - {"calling open_tty\n", 1019}, - {"calling termio_init\n", 1020}, - {"writing init string\n", 1021}, - {"before autobaud\n", 1022}, - {"waiting for cr-lf\n", 1023}, - {"read %c\n", 1024}, - {"reading login name\n", 1025}, - {"%s: can't exec %s: %m", 1026}, - {"can't malloc initstring", 1027}, - {"bad timeout value: %s", 1028}, - {"after getopt loop\n", 1029}, - {"exiting parseargs\n", 1030}, - {"entered parse_speeds\n", 1031}, - {"bad speed: %s", 1032}, - {"too many alternate speeds", 1033}, - {"exiting parsespeeds\n", 1034}, - {"%s: open for update: %m", 1035}, - {"%s: no utmp entry", 1036}, - {"/dev: chdir() failed: %m", 1037}, - {"/dev/%s: not a character device", 1038}, - {"open(2)\n", 1039}, - {"/dev/%s: cannot open as standard input: %m", 1040}, - {"%s: not open for read/write", 1041}, - {"duping\n", 1042}, - {"%s: dup problem: %m", 1043}, - {"term_io 2\n", 1044}, - {"user", 1045}, - {"users", 1046}, - {"%s: read: %m", 1047}, - {"%s: input overrun", 1048}, +(See fdisk(8).)\n", 1003}, + {"usage: banner [-w width]\n", 1004}, + {"Message: ", 1005}, + {"The character '%c' is not in my character set", 1006}, + {"Message '%s' is OK\n", 1007}, + {"Try `getopt --help' for more information.\n", 1008}, + {"empty long option after -l or --long argument", 1009}, + {"unknown shell after -s or --shell argument", 1010}, + {"Usage: getopt optstring parameters\n", 1011}, + {" getopt [options] [--] optstring parameters\n", 1012}, + {" getopt [options] -o|--options optstring [options] [--]\n", 1013}, + {" parameters\n", 1014}, + {"\ + -a, --alternative Allow long options starting with single -\n", 1015}, + {" -h, --help This small usage guide\n", 1016}, + {" -l, --longoptions=longopts Long options to be recognized\n", 1017}, + {"\ + -n, --name=progname The name under which errors are reported\n", 1018}, + {" -o, --options=optstring Short options to be recognized\n", 1019}, + {" -q, --quiet Disable error reporting by getopt(3)\n", 1020}, + {" -Q, --quiet-output No normal output\n", 1021}, + {" -s, --shell=shell Set shell quoting conventions\n", 1022}, + {" -T, --test Test for getopt(1) version\n", 1023}, + {" -u, --unqote Do not quote the output\n", 1024}, + {" -V, --version Output version information\n", 1025}, + {"missing optstring argument", 1026}, + {"getopt (enhanced) 1.1.0\n", 1027}, + {"internal error, contact the author.", 1028}, + {"calling open_tty\n", 1029}, + {"calling termio_init\n", 1030}, + {"writing init string\n", 1031}, + {"before autobaud\n", 1032}, + {"waiting for cr-lf\n", 1033}, + {"read %c\n", 1034}, + {"reading login name\n", 1035}, + {"%s: can't exec %s: %m", 1036}, + {"can't malloc initstring", 1037}, + {"bad timeout value: %s", 1038}, + {"after getopt loop\n", 1039}, + {"exiting parseargs\n", 1040}, + {"entered parse_speeds\n", 1041}, + {"bad speed: %s", 1042}, + {"too many alternate speeds", 1043}, + {"exiting parsespeeds\n", 1044}, + {"%s: open for update: %m", 1045}, + {"%s: no utmp entry", 1046}, + {"/dev: chdir() failed: %m", 1047}, + {"/dev/%s: not a character device", 1048}, + {"open(2)\n", 1049}, + {"/dev/%s: cannot open as standard input: %m", 1050}, + {"%s: not open for read/write", 1051}, + {"duping\n", 1052}, + {"%s: dup problem: %m", 1053}, + {"term_io 2\n", 1054}, + {"user", 1055}, + {"users", 1056}, + {"%s: read: %m", 1057}, + {"%s: input overrun", 1058}, {"\ Usage: %s [-hiLmw] [-l login_program] [-t timeout] [-I initstring] [-H \ login_host] baud_rate,... line [termtype]\n\ or\t[-hiLmw] [-l login_program] [-t timeout] [-I initstring] [-H login_host] \ -line baud_rate,... [termtype]\n", 1049}, - {"badlogin: %s\n", 1050}, - {"sleepexit %d\n", 1051}, - {"login: memory low, login may fail\n", 1052}, - {"can't malloc for ttyclass", 1053}, - {"can't malloc for grplist", 1054}, - {"Login on %s from %s denied by default.\n", 1055}, - {"Login on %s from %s denied.\n", 1056}, - {"%s: you (user %d) don't exist.\n", 1057}, - {"%s: user \"%s\" does not exist.\n", 1058}, - {"%s: can only change local entries; use yp%s instead.\n", 1059}, - {"Changing finger information for %s.\n", 1060}, - {"Password error.", 1061}, - {"Password: ", 1062}, - {"Incorrect password.", 1063}, - {"Finger information not changed.\n", 1064}, - {"Usage: %s [ -f full-name ] [ -o office ] ", 1065}, +line baud_rate,... [termtype]\n", 1059}, + {"login: memory low, login may fail\n", 1060}, + {"can't malloc for ttyclass", 1061}, + {"can't malloc for grplist", 1062}, + {"Login on %s from %s denied by default.\n", 1063}, + {"Login on %s from %s denied.\n", 1064}, + {"%s: you (user %d) don't exist.\n", 1065}, + {"%s: user \"%s\" does not exist.\n", 1066}, + {"%s: can only change local entries; use yp%s instead.\n", 1067}, + {"Changing finger information for %s.\n", 1068}, + {"Password error.", 1069}, + {"Password: ", 1070}, + {"Incorrect password.", 1071}, + {"Finger information not changed.\n", 1072}, + {"Usage: %s [ -f full-name ] [ -o office ] ", 1073}, {"\ [ -p office-phone ]\n\ -\t[ -h home-phone ] ", 1066}, - {"[ --help ] [ --version ]\n", 1067}, +\t[ -h home-phone ] ", 1074}, + {"[ --help ] [ --version ]\n", 1075}, {"\ \n\ -Aborted.\n", 1068}, - {"field is too long.\n", 1069}, - {"'%c' is not allowed.\n", 1070}, - {"Control characters are not allowed.\n", 1071}, - {"Finger information *NOT* changed. Try again later.\n", 1072}, - {"Finger information changed.\n", 1073}, - {"malloc failed", 1074}, - {"%s: Your shell is not in /etc/shells, shell change denied\n", 1075}, - {"Changing shell for %s.\n", 1076}, - {"New shell", 1077}, - {"Shell not changed.\n", 1078}, - {"Shell *NOT* changed. Try again later.\n", 1079}, - {"Shell changed.\n", 1080}, - {"Usage: %s [ -s shell ] ", 1081}, - {"[ --list-shells ] [ --help ] [ --version ]\n", 1082}, - {" [ username ]\n", 1083}, - {"%s: shell must be a full path name.\n", 1084}, - {"%s: \"%s\" does not exist.\n", 1085}, - {"%s: \"%s\" is not executable.\n", 1086}, - {"%s: '%c' is not allowed.\n", 1087}, - {"%s: Control characters are not allowed.\n", 1088}, - {"Warning: \"%s\" is not listed in /etc/shells\n", 1089}, - {"%s: \"%s\" is not listed in /etc/shells.\n", 1090}, - {"%s: use -l option to see list\n", 1091}, - {"Warning: \"%s\" is not listed in /etc/shells.\n", 1092}, - {"Use %s -l to see list.\n", 1093}, - {"No known shells.\n", 1094}, - {"couldn't open /dev/urandom", 1095}, - {"couldn't read random data from /dev/urandom", 1096}, - {"can't open %s for reading", 1097}, - {"can't stat(%s)", 1098}, - {"%s doesn't have the correct filemodes", 1099}, - {"can't read data from %s", 1100}, - {"Can't read %s, exiting.", 1101}, - {"usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n", 1102}, - {" still logged in", 1103}, +Aborted.\n", 1076}, + {"field is too long.\n", 1077}, + {"'%c' is not allowed.\n", 1078}, + {"Control characters are not allowed.\n", 1079}, + {"Finger information *NOT* changed. Try again later.\n", 1080}, + {"Finger information changed.\n", 1081}, + {"malloc failed", 1082}, + {"%s: Your shell is not in /etc/shells, shell change denied\n", 1083}, + {"Changing shell for %s.\n", 1084}, + {"New shell", 1085}, + {"Shell not changed.\n", 1086}, + {"Shell *NOT* changed. Try again later.\n", 1087}, + {"Shell changed.\n", 1088}, + {"Usage: %s [ -s shell ] ", 1089}, + {"[ --list-shells ] [ --help ] [ --version ]\n", 1090}, + {" [ username ]\n", 1091}, + {"%s: shell must be a full path name.\n", 1092}, + {"%s: \"%s\" does not exist.\n", 1093}, + {"%s: \"%s\" is not executable.\n", 1094}, + {"%s: '%c' is not allowed.\n", 1095}, + {"%s: Control characters are not allowed.\n", 1096}, + {"Warning: \"%s\" is not listed in /etc/shells\n", 1097}, + {"%s: \"%s\" is not listed in /etc/shells.\n", 1098}, + {"%s: use -l option to see list\n", 1099}, + {"Warning: \"%s\" is not listed in /etc/shells.\n", 1100}, + {"Use %s -l to see list.\n", 1101}, + {"No known shells.\n", 1102}, + {"couldn't open /dev/urandom", 1103}, + {"couldn't read random data from /dev/urandom", 1104}, + {"can't open %s for reading", 1105}, + {"can't stat(%s)", 1106}, + {"%s doesn't have the correct filemodes", 1107}, + {"can't read data from %s", 1108}, + {"Can't read %s, exiting.", 1109}, + {"usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n", 1110}, + {" still logged in", 1111}, {"\ \n\ -wtmp begins %s", 1104}, - {"last: malloc failure.\n", 1105}, - {"last: gethostname", 1106}, +wtmp begins %s", 1112}, + {"last: malloc failure.\n", 1113}, + {"last: gethostname", 1114}, {"\ \n\ -interrupted %10.10s %5.5s \n", 1107}, - {"login: -h for super-user only.\n", 1108}, - {"usage: login [-fp] [username]\n", 1109}, - {"login: PAM Failure, aborting: %s\n", 1110}, - {"Couldn't initialize PAM: %s", 1111}, - {"login: ", 1112}, - {"FAILED LOGIN %d FROM %s FOR %s, %s", 1113}, +interrupted %10.10s %5.5s \n", 1115}, + {"login: -h for super-user only.\n", 1116}, + {"usage: login [-fp] [username]\n", 1117}, + {"login: PAM Failure, aborting: %s\n", 1118}, + {"Couldn't initialize PAM: %s", 1119}, + {"login: ", 1120}, + {"FAILED LOGIN %d FROM %s FOR %s, %s", 1121}, {"\ Login incorrect\n\ -\n", 1114}, - {"TOO MANY LOGIN TRIES (%d) FROM %s FOR %s, %s", 1115}, - {"FAILED LOGIN SESSION FROM %s FOR %s, %s", 1116}, +\n", 1122}, + {"TOO MANY LOGIN TRIES (%d) FROM %s FOR %s, %s", 1123}, + {"FAILED LOGIN SESSION FROM %s FOR %s, %s", 1124}, {"\ \n\ -Login incorrect\n", 1117}, - {"Illegal username", 1118}, - {"%s login refused on this terminal.\n", 1119}, - {"LOGIN %s REFUSED FROM %s ON TTY %s", 1120}, - {"LOGIN %s REFUSED ON TTY %s", 1121}, - {"Login incorrect\n", 1122}, +Login incorrect\n", 1125}, + {"Illegal username", 1126}, + {"%s login refused on this terminal.\n", 1127}, + {"LOGIN %s REFUSED FROM %s ON TTY %s", 1128}, + {"LOGIN %s REFUSED ON TTY %s", 1129}, + {"Login incorrect\n", 1130}, {"\ Too many users logged on already.\n\ -Try again later.\n", 1123}, - {"You have too many processes running.\n", 1124}, - {"Warning: no Kerberos tickets issued\n", 1125}, - {"Sorry -- your password has expired.\n", 1126}, - {"Warning: your password expires on %s %d, %d\n", 1127}, - {"Sorry -- your account has expired.\n", 1128}, - {"Warning: your account expires on %s %d, %d\n", 1129}, - {"DIALUP AT %s BY %s", 1130}, - {"ROOT LOGIN ON %s FROM %s", 1131}, - {"ROOT LOGIN ON %s", 1132}, - {"LOGIN ON %s BY %s FROM %s", 1133}, - {"LOGIN ON %s BY %s", 1134}, - {"You have %smail.\n", 1135}, - {"new ", 1136}, - {"login: failure forking: %s", 1137}, - {"setuid() failed", 1138}, - {"No directory %s!\n", 1139}, - {"Logging in with home = \"/\".\n", 1140}, - {"login: no memory for shell script.\n", 1141}, - {"login: couldn't exec shell script: %s.\n", 1142}, - {"login: no shell: %s.\n", 1143}, +Try again later.\n", 1131}, + {"You have too many processes running.\n", 1132}, + {"Warning: no Kerberos tickets issued\n", 1133}, + {"Sorry -- your password has expired.\n", 1134}, + {"Warning: your password expires on %d %s %d.\n", 1135}, + {"Sorry -- your account has expired.\n", 1136}, + {"Warning: your account expires on %d %s %d.\n", 1137}, + {"DIALUP AT %s BY %s", 1138}, + {"ROOT LOGIN ON %s FROM %s", 1139}, + {"ROOT LOGIN ON %s", 1140}, + {"LOGIN ON %s BY %s FROM %s", 1141}, + {"LOGIN ON %s BY %s", 1142}, + {"You have %smail.\n", 1143}, + {"new ", 1144}, + {"login: failure forking: %s", 1145}, + {"setuid() failed", 1146}, + {"No directory %s!\n", 1147}, + {"Logging in with home = \"/\".\n", 1148}, + {"login: no memory for shell script.\n", 1149}, + {"login: couldn't exec shell script: %s.\n", 1150}, + {"login: no shell: %s.\n", 1151}, {"\ \n\ -%s login: ", 1144}, - {"login name much too long.\n", 1145}, - {"NAME too long", 1146}, - {"login names may not start with '-'.\n", 1147}, - {"too many bare linefeeds.\n", 1148}, - {"EXCESSIVE linefeeds", 1149}, - {"Login timed out after %d seconds\n", 1150}, - {"Last login: %.*s ", 1151}, - {"from %.*s\n", 1152}, - {"on %.*s\n", 1153}, - {"LOGIN FAILURE FROM %s, %s", 1154}, - {"LOGIN FAILURE ON %s, %s", 1155}, - {"%d LOGIN FAILURES FROM %s, %s", 1156}, - {"%d LOGIN FAILURES ON %s, %s", 1157}, - {"is y\n", 1158}, - {"is n\n", 1159}, - {"usage: mesg [y | n]\n", 1160}, - {"newgrp: Who are you?", 1161}, - {"newgrp: setgid", 1162}, - {"newgrp: No such group.", 1163}, - {"newgrp: Permission denied", 1164}, - {"newgrp: setuid", 1165}, - {"No shell", 1166}, - {"The password must have at least 6 characters, try again.\n", 1167}, - {"The password must contain characters out of two of the following\n", 1168}, - {"classes: upper and lower case letters, digits and non alphanumeric\n", 1169}, - {"characters. See passwd(1) for more information.\n", 1170}, - {"You cannot reuse the old password.\n", 1171}, - {"Please don't use something like your username as password!\n", 1172}, - {"Please don't use something like your realname as password!\n", 1173}, - {"Usage: passwd [username [password]]\n", 1174}, - {"Only root may use the one and two argument forms.\n", 1175}, - {"Usage: passwd [-foqsvV] [user [password]]\n", 1176}, - {"Can't exec %s: %s\n", 1177}, - {"Cannot find login name", 1178}, - {"Only root can change the password for others.\n", 1179}, - {"Too many arguments.\n", 1180}, - {"Can't find username anywhere. Is `%s' really a user?", 1181}, - {"Sorry, I can only change local passwords. Use yppasswd instead.", 1182}, - {"UID and username does not match, imposter!", 1183}, - {"Changing password for %s\n", 1184}, - {"Enter old password: ", 1185}, - {"Illegal password, imposter.", 1186}, - {"Enter new password: ", 1187}, - {"Password not changed.", 1188}, - {"Re-type new password: ", 1189}, - {"You misspelled it. Password not changed.", 1190}, - {"password changed, user %s", 1191}, - {"ROOT PASSWORD CHANGED", 1192}, - {"password changed by root, user %s", 1193}, - {"calling setpwnam to set password.\n", 1194}, - {"Password *NOT* changed. Try again later.\n", 1195}, - {"Password changed.\n", 1196}, - {"Usage: shutdown [-h|-r] [-fqs] [now|hh:ss|+mins]\n", 1197}, - {"Shutdown process aborted", 1198}, - {"%s: Only root can shut a system down.\n", 1199}, - {"That must be tomorrow, can't you wait till then?\n", 1200}, - {"for maintenance; bounce, bounce", 1201}, - {"timeout = %d, quiet = %d, reboot = %d\n", 1202}, - {"The system is being shut down within 5 minutes", 1203}, - {"Login is therefore prohibited.", 1204}, - {"%s by %s: %s", 1205}, - {"rebooted", 1206}, - {"halted", 1207}, +%s login: ", 1152}, + {"login name much too long.\n", 1153}, + {"NAME too long", 1154}, + {"login names may not start with '-'.\n", 1155}, + {"too many bare linefeeds.\n", 1156}, + {"EXCESSIVE linefeeds", 1157}, + {"Login timed out after %d seconds\n", 1158}, + {"Last login: %.*s ", 1159}, + {"from %.*s\n", 1160}, + {"on %.*s\n", 1161}, + {"LOGIN FAILURE FROM %s, %s", 1162}, + {"LOGIN FAILURE ON %s, %s", 1163}, + {"%d LOGIN FAILURES FROM %s, %s", 1164}, + {"%d LOGIN FAILURES ON %s, %s", 1165}, + {"is y\n", 1166}, + {"is n\n", 1167}, + {"usage: mesg [y | n]\n", 1168}, + {"newgrp: Who are you?", 1169}, + {"newgrp: setgid", 1170}, + {"newgrp: No such group.", 1171}, + {"newgrp: Permission denied", 1172}, + {"newgrp: setuid", 1173}, + {"No shell", 1174}, + {"The password must have at least 6 characters, try again.\n", 1175}, + {"The password must contain characters out of two of the following\n", 1176}, + {"classes: upper and lower case letters, digits and non alphanumeric\n", 1177}, + {"characters. See passwd(1) for more information.\n", 1178}, + {"You cannot reuse the old password.\n", 1179}, + {"Please don't use something like your username as password!\n", 1180}, + {"Please don't use something like your realname as password!\n", 1181}, + {"Usage: passwd [username [password]]\n", 1182}, + {"Only root may use the one and two argument forms.\n", 1183}, + {"Usage: passwd [-foqsvV] [user [password]]\n", 1184}, + {"Can't exec %s: %s\n", 1185}, + {"Cannot find login name", 1186}, + {"Only root can change the password for others.\n", 1187}, + {"Too many arguments.\n", 1188}, + {"Can't find username anywhere. Is `%s' really a user?", 1189}, + {"Sorry, I can only change local passwords. Use yppasswd instead.", 1190}, + {"UID and username does not match, imposter!", 1191}, + {"Changing password for %s\n", 1192}, + {"Enter old password: ", 1193}, + {"Illegal password, imposter.", 1194}, + {"Enter new password: ", 1195}, + {"Password not changed.", 1196}, + {"Re-type new password: ", 1197}, + {"You misspelled it. Password not changed.", 1198}, + {"password changed, user %s", 1199}, + {"ROOT PASSWORD CHANGED", 1200}, + {"password changed by root, user %s", 1201}, + {"calling setpwnam to set password.\n", 1202}, + {"Password *NOT* changed. Try again later.\n", 1203}, + {"Password changed.\n", 1204}, + {"Usage: shutdown [-h|-r] [-fqs] [now|hh:ss|+mins]\n", 1205}, + {"Shutdown process aborted", 1206}, + {"%s: Only root can shut a system down.\n", 1207}, + {"That must be tomorrow, can't you wait till then?\n", 1208}, + {"for maintenance; bounce, bounce", 1209}, + {"timeout = %d, quiet = %d, reboot = %d\n", 1210}, + {"The system is being shut down within 5 minutes", 1211}, + {"Login is therefore prohibited.", 1212}, + {"%s by %s: %s", 1213}, + {"rebooted", 1214}, + {"halted", 1215}, {"\ \n\ -Why am I still alive after reboot?", 1208}, +Why am I still alive after reboot?", 1216}, {"\ \n\ -Now you can turn off the power...", 1209}, - {"Calling kernel power-off facility...\n", 1210}, - {"Error powering off\t%s\n", 1211}, - {"Executing the program \"%s\" ...\n", 1212}, - {"Error executing\t%s\n", 1213}, - {"URGENT: broadcast message from %s:", 1214}, - {"System going down IMMEDIATELY!\n", 1215}, - {"System going down in %d hour%s %d minutes", 1216}, - {"s", 1217}, - {"System going down in %d minute%s\n", 1218}, - {"\t... %s ...\n", 1219}, - {"Cannot fork for swapoff. Shrug!", 1220}, - {"Cannot exec swapoff, hoping umount will do the trick.", 1221}, - {"Cannot fork for umount, trying manually.", 1222}, - {"Cannot exec %s, trying umount.\n", 1223}, - {"Cannot exec umount, giving up on umount.", 1224}, - {"Unmounting any remaining filesystems...", 1225}, - {"shutdown: Couldn't umount %s\n", 1226}, - {"Booting to single user mode.\n", 1227}, - {"exec of single user shell failed\n", 1228}, - {"fork of single user shell failed\n", 1229}, - {"error opening fifo\n", 1230}, +Now you can turn off the power...", 1217}, + {"Calling kernel power-off facility...\n", 1218}, + {"Error powering off\t%s\n", 1219}, + {"Executing the program \"%s\" ...\n", 1220}, + {"Error executing\t%s\n", 1221}, + {"URGENT: broadcast message from %s:", 1222}, + {"System going down in %d hours %d minutes", 1223}, + {"System going down in 1 hour %d minutes", 1224}, + {"System going down in %d minutes\n", 1225}, + {"System going down in 1 minute\n", 1226}, + {"System going down IMMEDIATELY!\n", 1227}, + {"\t... %s ...\n", 1228}, + {"Cannot fork for swapoff. Shrug!", 1229}, + {"Cannot exec swapoff, hoping umount will do the trick.", 1230}, + {"Cannot fork for umount, trying manually.", 1231}, + {"Cannot exec %s, trying umount.\n", 1232}, + {"Cannot exec umount, giving up on umount.", 1233}, + {"Unmounting any remaining filesystems...", 1234}, + {"shutdown: Couldn't umount %s: %s\n", 1235}, + {"Booting to single user mode.\n", 1236}, + {"exec of single user shell failed\n", 1237}, + {"fork of single user shell failed\n", 1238}, + {"error opening fifo\n", 1239}, + {"error running finalprog\n", 1240}, + {"error forking finalprog\n", 1241}, {"\ \n\ -Wrong password.\n", 1231}, - {"stat of path failed\n", 1232}, - {"open of directory failed\n", 1233}, - {"fork failed\n", 1234}, - {"exec failed\n", 1235}, - {"cannot open inittab\n", 1236}, - {"no TERM or cannot stat tty\n", 1237}, - {"error running programme\n", 1238}, - {"too many iov's (change code in wall/ttymsg.c)", 1239}, - {"excessively long line arg", 1240}, - {"cannot fork", 1241}, - {"fork: %s", 1242}, - {"%s: BAD ERROR", 1243}, - {"%s: the %s file is busy.\n", 1244}, - {"%s: the %s file is busy (%s present)\n", 1245}, - {"%s: can't link %s: %s\n", 1246}, - {"%s: can't unlock %s: %s (your changes are still in %s)\n", 1247}, - {"%s: Cannot fork\n", 1248}, - {"%s: %s unchanged\n", 1249}, - {"%s: no changes made\n", 1250}, - {"usage: %s [file]\n", 1251}, - {"%s: can't open temporary file.\n", 1252}, - {"Broadcast Message from %s@%s", 1253}, - {"%s: can't read %s.\n", 1254}, - {"%s: can't stat temporary file.\n", 1255}, - {"%s: can't read temporary file.\n", 1256}, - {"illegal month value: use 1-12", 1257}, - {"illegal year value: use 1-9999", 1258}, - {"usage: cal [-mjyV] [[month] year]\n", 1259}, - {"usage: %s [+format] [day month year]\n", 1260}, - {"St. Tib's Day", 1261}, - {"%s: unknown signal %s\n", 1262}, - {"%s: can't find process \"%s\"\n", 1263}, - {"%s: unknown signal %s; valid signals:\n", 1264}, - {"usage: %s [ -s signal | -p ] [ -a ] pid ...\n", 1265}, - {" %s -l [ signal ]\n", 1266}, - {"logger: %s: %s.\n", 1267}, - {"logger: unknown facility name: %s.\n", 1268}, - {"logger: unknown priority name: %s.\n", 1269}, - {"\ -usage: logger [-is] [-f file] [-p pri] [-t tag] [-u socket] [ message ... ]\n", 1270}, - {"usage: look [-dfa] [-t char] string [file]\n", 1271}, - {"Could not open %s\n", 1272}, - {"Got %d bytes from %s\n", 1273}, - {"namei: unable to get current directory - %s\n", 1274}, - {"namei: unable to chdir to %s - %s (%d)\n", 1275}, - {"usage: namei [-mx] pathname [pathname ...]\n", 1276}, - {"namei: could not chdir to root!\n", 1277}, - {"namei: could not stat root!\n", 1278}, - {" ? could not chdir into %s - %s (%d)\n", 1279}, - {" ? problems reading symlink %s - %s (%d)\n", 1280}, - {" *** EXCEEDED UNIX LIMIT OF SYMLINKS ***\n", 1281}, - {"namei: unknown file type 0%06o on file %s\n", 1282}, - {"usage: script [-a] [file]\n", 1283}, - {"Script started, file is %s\n", 1284}, - {"Script started on %s", 1285}, +Wrong password.\n", 1242}, + {"stat of path failed\n", 1243}, + {"open of directory failed\n", 1244}, + {"fork failed\n", 1245}, + {"exec failed\n", 1246}, + {"cannot open inittab\n", 1247}, + {"no TERM or cannot stat tty\n", 1248}, + {"error running programme\n", 1249}, + {"too many iov's (change code in wall/ttymsg.c)", 1250}, + {"excessively long line arg", 1251}, + {"cannot fork", 1252}, + {"fork: %s", 1253}, + {"%s: BAD ERROR", 1254}, + {"%s: the %s file is busy.\n", 1255}, + {"%s: the %s file is busy (%s present)\n", 1256}, + {"%s: can't link %s: %s\n", 1257}, + {"%s: can't unlock %s: %s (your changes are still in %s)\n", 1258}, + {"%s: Cannot fork\n", 1259}, + {"%s: %s unchanged\n", 1260}, + {"%s: no changes made\n", 1261}, + {"usage: %s [file]\n", 1262}, + {"%s: can't open temporary file.\n", 1263}, + {"Broadcast Message from %s@%s", 1264}, + {"%s: will not read %s - use stdin.\n", 1265}, + {"%s: can't read %s.\n", 1266}, + {"%s: can't stat temporary file.\n", 1267}, + {"%s: can't read temporary file.\n", 1268}, + {"illegal month value: use 1-12", 1269}, + {"illegal year value: use 1-9999", 1270}, + {"usage: cal [-mjyV] [[month] year]\n", 1271}, + {"usage: %s [+format] [day month year]\n", 1272}, + {"St. Tib's Day", 1273}, + {"%s: unknown signal %s\n", 1274}, + {"%s: can't find process \"%s\"\n", 1275}, + {"%s: unknown signal %s; valid signals:\n", 1276}, + {"usage: %s [ -s signal | -p ] [ -a ] pid ...\n", 1277}, + {" %s -l [ signal ]\n", 1278}, + {"logger: %s: %s.\n", 1279}, + {"logger: unknown facility name: %s.\n", 1280}, + {"logger: unknown priority name: %s.\n", 1281}, + {"\ +usage: logger [-is] [-f file] [-p pri] [-t tag] [-u socket] [ message ... ]\n", 1282}, + {"usage: look [-dfa] [-t char] string [file]\n", 1283}, + {"Could not open %s\n", 1284}, + {"Got %d bytes from %s\n", 1285}, + {"namei: unable to get current directory - %s\n", 1286}, + {"namei: unable to chdir to %s - %s (%d)\n", 1287}, + {"usage: namei [-mx] pathname [pathname ...]\n", 1288}, + {"namei: could not chdir to root!\n", 1289}, + {"namei: could not stat root!\n", 1290}, + {" ? could not chdir into %s - %s (%d)\n", 1291}, + {" ? problems reading symlink %s - %s (%d)\n", 1292}, + {" *** EXCEEDED UNIX LIMIT OF SYMLINKS ***\n", 1293}, + {"namei: unknown file type 0%06o on file %s\n", 1294}, + {"\ +Warning: `%s' is a symlink.\n\ +Use `%s [options] %s' if you really want to use it.\n\ +Script not started.\n", 1295}, + {"usage: script [-a] [-f] [-q] [file]\n", 1296}, + {"Script started, file is %s\n", 1297}, + {"Script started on %s", 1298}, {"\ \n\ -Script done on %s", 1286}, - {"Script done, file is %s\n", 1287}, - {"openpty failed\n", 1288}, - {"Out of pty's\n", 1289}, - {"%s: Argument error, usage\n", 1290}, - {" [ -term terminal_name ]\n", 1291}, - {" [ -reset ]\n", 1292}, - {" [ -initialize ]\n", 1293}, - {" [ -cursor [on|off] ]\n", 1294}, - {" [ -snow [on|off] ]\n", 1295}, - {" [ -softscroll [on|off] ]\n", 1296}, - {" [ -repeat [on|off] ]\n", 1297}, - {" [ -appcursorkeys [on|off] ]\n", 1298}, - {" [ -linewrap [on|off] ]\n", 1299}, - {" [ -default ]\n", 1300}, - {" [ -foreground black|blue|green|cyan", 1301}, - {"|red|magenta|yellow|white|default ]\n", 1302}, - {" [ -background black|blue|green|cyan", 1303}, - {" [ -ulcolor black|grey|blue|green|cyan", 1304}, - {"|red|magenta|yellow|white ]\n", 1305}, - {" [ -ulcolor bright blue|green|cyan", 1306}, - {" [ -hbcolor black|grey|blue|green|cyan", 1307}, - {" [ -hbcolor bright blue|green|cyan", 1308}, - {" [ -standout [ attr ] ]\n", 1309}, - {" [ -inversescreen [on|off] ]\n", 1310}, - {" [ -bold [on|off] ]\n", 1311}, - {" [ -half-bright [on|off] ]\n", 1312}, - {" [ -blink [on|off] ]\n", 1313}, - {" [ -reverse [on|off] ]\n", 1314}, - {" [ -underline [on|off] ]\n", 1315}, - {" [ -store ]\n", 1316}, - {" [ -clear [all|rest] ]\n", 1317}, - {" [ -tabs [ tab1 tab2 tab3 ... ] ] (tabn = 1-160)\n", 1318}, - {" [ -clrtabs [ tab1 tab2 tab3 ... ] ] (tabn = 1-160)\n", 1319}, - {" [ -regtabs [1-160] ]\n", 1320}, - {" [ -blank [0-60] ]\n", 1321}, - {" [ -dump [1-NR_CONSOLES] ]\n", 1322}, - {" [ -append [1-NR_CONSOLES] ]\n", 1323}, - {" [ -file dumpfilename ]\n", 1324}, - {" [ -msg [on|off] ]\n", 1325}, - {" [ -msglevel [0-8] ]\n", 1326}, - {" [ -powersave [on|vsync|hsync|powerdown|off] ]\n", 1327}, - {" [ -powerdown [0-60] ]\n", 1328}, - {" [ -blength [0-2000] ]\n", 1329}, - {" [ -bfreq freqnumber ]\n", 1330}, - {"snow.on", 1331}, - {"snow.off", 1332}, - {"softscroll.on", 1333}, - {"softscroll.off", 1334}, - {"cannot (un)set powersave mode\n", 1335}, - {"klogctl error: %s\n", 1336}, - {"Error reading %s\n", 1337}, - {"Error writing screendump\n", 1338}, - {"couldn't read %s, and cannot ioctl dump\n", 1339}, - {"%s: $TERM is not defined.\n", 1340}, - {"usage: tsort [ inputfile ]\n", 1341}, - {"tsort: odd data count.\n", 1342}, - {"tsort: cycle in data.\n", 1343}, - {"tsort: internal error -- could not find cycle.\n", 1344}, - {"whereis [ -sbmu ] [ -SBM dir ... -f ] name...\n", 1345}, - {"write: can't find your tty's name\n", 1346}, - {"write: you have write permission turned off.\n", 1347}, - {"write: %s is not logged in on %s.\n", 1348}, - {"write: %s has messages disabled on %s\n", 1349}, - {"usage: write user [tty]\n", 1350}, - {"write: %s is not logged in\n", 1351}, - {"write: %s has messages disabled\n", 1352}, - {"write: %s is logged in more than once; writing to %s\n", 1353}, - {"Message from %s@%s on %s at %s ...", 1354}, - {"warning: error reading %s: %s", 1355}, - {"warning: can't open %s: %s", 1356}, - {"mount: could not open %s - using %s instead\n", 1357}, - {"can't create lock file %s: %s (use -n flag to override)", 1358}, - {"can't link lock file %s: %s (use -n flag to override)", 1359}, - {"can't open lock file %s: %s (use -n flag to override)", 1360}, - {"Can't lock lock file %s: %s\n", 1361}, - {"can't lock lock file %s: %s", 1362}, - {"timed out", 1363}, +Script done on %s", 1299}, + {"Script done, file is %s\n", 1300}, + {"openpty failed\n", 1301}, + {"Out of pty's\n", 1302}, + {"%s: Argument error, usage\n", 1303}, + {" [ -term terminal_name ]\n", 1304}, + {" [ -reset ]\n", 1305}, + {" [ -initialize ]\n", 1306}, + {" [ -cursor [on|off] ]\n", 1307}, + {" [ -snow [on|off] ]\n", 1308}, + {" [ -softscroll [on|off] ]\n", 1309}, + {" [ -repeat [on|off] ]\n", 1310}, + {" [ -appcursorkeys [on|off] ]\n", 1311}, + {" [ -linewrap [on|off] ]\n", 1312}, + {" [ -default ]\n", 1313}, + {" [ -foreground black|blue|green|cyan", 1314}, + {"|red|magenta|yellow|white|default ]\n", 1315}, + {" [ -background black|blue|green|cyan", 1316}, + {" [ -ulcolor black|grey|blue|green|cyan", 1317}, + {"|red|magenta|yellow|white ]\n", 1318}, + {" [ -ulcolor bright blue|green|cyan", 1319}, + {" [ -hbcolor black|grey|blue|green|cyan", 1320}, + {" [ -hbcolor bright blue|green|cyan", 1321}, + {" [ -standout [ attr ] ]\n", 1322}, + {" [ -inversescreen [on|off] ]\n", 1323}, + {" [ -bold [on|off] ]\n", 1324}, + {" [ -half-bright [on|off] ]\n", 1325}, + {" [ -blink [on|off] ]\n", 1326}, + {" [ -reverse [on|off] ]\n", 1327}, + {" [ -underline [on|off] ]\n", 1328}, + {" [ -store ]\n", 1329}, + {" [ -clear [all|rest] ]\n", 1330}, + {" [ -tabs [ tab1 tab2 tab3 ... ] ] (tabn = 1-160)\n", 1331}, + {" [ -clrtabs [ tab1 tab2 tab3 ... ] ] (tabn = 1-160)\n", 1332}, + {" [ -regtabs [1-160] ]\n", 1333}, + {" [ -blank [0-60] ]\n", 1334}, + {" [ -dump [1-NR_CONSOLES] ]\n", 1335}, + {" [ -append [1-NR_CONSOLES] ]\n", 1336}, + {" [ -file dumpfilename ]\n", 1337}, + {" [ -msg [on|off] ]\n", 1338}, + {" [ -msglevel [0-8] ]\n", 1339}, + {" [ -powersave [on|vsync|hsync|powerdown|off] ]\n", 1340}, + {" [ -powerdown [0-60] ]\n", 1341}, + {" [ -blength [0-2000] ]\n", 1342}, + {" [ -bfreq freqnumber ]\n", 1343}, + {"snow.on", 1344}, + {"snow.off", 1345}, + {"softscroll.on", 1346}, + {"softscroll.off", 1347}, + {"cannot (un)set powersave mode\n", 1348}, + {"klogctl error: %s\n", 1349}, + {"Error reading %s\n", 1350}, + {"Error writing screendump\n", 1351}, + {"couldn't read %s, and cannot ioctl dump\n", 1352}, + {"%s: $TERM is not defined.\n", 1353}, + {"usage: tsort [ inputfile ]\n", 1354}, + {"tsort: odd data count.\n", 1355}, + {"tsort: cycle in data.\n", 1356}, + {"tsort: internal error -- could not find cycle.\n", 1357}, + {"whereis [ -sbmu ] [ -SBM dir ... -f ] name...\n", 1358}, + {"write: can't find your tty's name\n", 1359}, + {"write: you have write permission turned off.\n", 1360}, + {"write: %s is not logged in on %s.\n", 1361}, + {"write: %s has messages disabled on %s\n", 1362}, + {"usage: write user [tty]\n", 1363}, + {"write: %s is not logged in\n", 1364}, + {"write: %s has messages disabled\n", 1365}, + {"write: %s is logged in more than once; writing to %s\n", 1366}, + {"Message from %s@%s (as %s) on %s at %s ...", 1367}, + {"Message from %s@%s on %s at %s ...", 1368}, + {"warning: error reading %s: %s", 1369}, + {"warning: can't open %s: %s", 1370}, + {"mount: could not open %s - using %s instead\n", 1371}, + {"can't create lock file %s: %s (use -n flag to override)", 1372}, + {"can't link lock file %s: %s (use -n flag to override)", 1373}, + {"can't open lock file %s: %s (use -n flag to override)", 1374}, + {"Can't lock lock file %s: %s\n", 1375}, + {"can't lock lock file %s: %s", 1376}, + {"timed out", 1377}, {"\ Cannot create link %s\n\ -Perhaps there is a stale lock file?\n", 1364}, - {"cannot open %s (%s) - mtab not updated", 1365}, - {"mount: warning: cannot change mounted device with a remount\n", 1366}, - {"mount: warning: cannot change filesystem type with a remount\n", 1367}, - {"error writing %s: %s", 1368}, - {"error changing mode of %s: %s\n", 1369}, - {"can't rename %s to %s: %s\n", 1370}, - {"loop: can't open device %s: %s\n", 1371}, - {"loop: can't get info on device %s: %s\n", 1372}, - {"%s: [%04x]:%ld (%s) offset %d, %s encryption\n", 1373}, - {"mount: could not find any device /dev/loop#", 1374}, +Perhaps there is a stale lock file?\n", 1378}, + {"cannot open %s (%s) - mtab not updated", 1379}, + {"error writing %s: %s", 1380}, + {"error changing mode of %s: %s\n", 1381}, + {"can't rename %s to %s: %s\n", 1382}, + {"loop: can't open device %s: %s\n", 1383}, + {"loop: can't get info on device %s: %s\n", 1384}, + {"%s: [%04x]:%ld (%s) offset %d, %s encryption\n", 1385}, + {"mount: could not find any device /dev/loop#", 1386}, {"\ mount: Could not find any loop device.\n\ - Maybe /dev/loop# has a wrong major number?", 1375}, + Maybe /dev/loop# has a wrong major number?", 1387}, {"\ mount: Could not find any loop device, and, according to %s,\n\ this kernel does not know about the loop device.\n\ - (If so, then recompile or `insmod loop.o'.)", 1376}, + (If so, then recompile or `insmod loop.o'.)", 1388}, {"\ mount: Could not find any loop device. Maybe this kernel does not know\n\ about the loop device (then recompile or `insmod loop.o'), or\n\ - maybe /dev/loop# has the wrong major number?", 1377}, - {"mount: could not find any free loop device", 1378}, - {"Unsupported encryption type %s\n", 1379}, - {"Couldn't lock into memory, exiting.\n", 1380}, - {"Init (up to 16 hex digits): ", 1381}, - {"Non-hex digit '%c'.\n", 1382}, - {"Don't know how to get key for encryption system %d\n", 1383}, - {"set_loop(%s,%s,%d): success\n", 1384}, - {"loop: can't delete device %s: %s\n", 1385}, - {"del_loop(%s): success\n", 1386}, - {"This mount was compiled without loop support. Please recompile.\n", 1387}, + maybe /dev/loop# has the wrong major number?", 1389}, + {"mount: could not find any free loop device", 1390}, + {"Unsupported encryption type %s\n", 1391}, + {"Couldn't lock into memory, exiting.\n", 1392}, + {"Init (up to 16 hex digits): ", 1393}, + {"Non-hex digit '%c'.\n", 1394}, + {"Don't know how to get key for encryption system %d\n", 1395}, + {"set_loop(%s,%s,%d): success\n", 1396}, + {"loop: can't delete device %s: %s\n", 1397}, + {"del_loop(%s): success\n", 1398}, + {"This mount was compiled without loop support. Please recompile.\n", 1399}, {"\ usage:\n\ %s loop_device # give info\n\ %s -d loop_device # delete\n\ - %s [ -e encryption ] [ -o offset ] loop_device file # setup\n", 1388}, - {"not enough memory", 1389}, - {"No loop support was available at compile time. Please recompile.\n", 1390}, - {"[mntent]: warning: no final newline at the end of %s\n", 1391}, - {"[mntent]: line %d in %s is bad%s\n", 1392}, - {"; rest of file ignored", 1393}, - {"mount: according to mtab, %s is already mounted on %s", 1394}, - {"mount: according to mtab, %s is mounted on %s", 1395}, - {"mount: can't open %s for writing: %s", 1396}, - {"mount: error writing %s: %s", 1397}, - {"mount: error changing mode of %s: %s", 1398}, - {"%s looks like swapspace - not mounted", 1399}, - {"mount failed", 1400}, - {"mount: only root can mount %s on %s", 1401}, - {"mount: loop device specified twice", 1402}, - {"mount: type specified twice", 1403}, - {"mount: skipping the setup of a loop device\n", 1404}, - {"mount: going to use the loop device %s\n", 1405}, - {"mount: failed setting up loop device\n", 1406}, - {"mount: setup loop device successfully\n", 1407}, - {"mount: can't open %s: %s", 1408}, - {"mount: cannot not open %s for setting speed", 1409}, - {"mount: cannot set speed: %s", 1410}, - {"mount: cannot fork: %s", 1411}, - {"mount: this version was compiled without support for the type `nfs'", 1412}, - {"mount: failed with nfs mount version 4, trying 3..\n", 1413}, - {"\ -mount: I could not determine the filesystem type, and none was specified", 1414}, - {"mount: you must specify the filesystem type", 1415}, - {"mount: mount failed", 1416}, - {"mount: mount point %s is not a directory", 1417}, - {"mount: permission denied", 1418}, - {"mount: must be superuser to use mount", 1419}, - {"mount: %s is busy", 1420}, - {"mount: proc already mounted", 1421}, - {"mount: %s already mounted or %s busy", 1422}, - {"mount: mount point %s does not exist", 1423}, - {"mount: mount point %s is a symbolic link to nowhere", 1424}, - {"mount: special device %s does not exist", 1425}, + %s [ -e encryption ] [ -o offset ] loop_device file # setup\n", 1400}, + {"not enough memory", 1401}, + {"No loop support was available at compile time. Please recompile.\n", 1402}, + {"[mntent]: warning: no final newline at the end of %s\n", 1403}, + {"[mntent]: line %d in %s is bad%s\n", 1404}, + {"; rest of file ignored", 1405}, + {"mount: according to mtab, %s is already mounted on %s", 1406}, + {"mount: according to mtab, %s is mounted on %s", 1407}, + {"mount: can't open %s for writing: %s", 1408}, + {"mount: error writing %s: %s", 1409}, + {"mount: error changing mode of %s: %s", 1410}, + {"%s looks like swapspace - not mounted", 1411}, + {"mount failed", 1412}, + {"mount: only root can mount %s on %s", 1413}, + {"mount: loop device specified twice", 1414}, + {"mount: type specified twice", 1415}, + {"mount: skipping the setup of a loop device\n", 1416}, + {"mount: going to use the loop device %s\n", 1417}, + {"mount: failed setting up loop device\n", 1418}, + {"mount: setup loop device successfully\n", 1419}, + {"mount: can't open %s: %s", 1420}, + {"mount: cannot not open %s for setting speed", 1421}, + {"mount: cannot set speed: %s", 1422}, + {"mount: cannot fork: %s", 1423}, + {"mount: this version was compiled without support for the type `nfs'", 1424}, + {"mount: failed with nfs mount version 4, trying 3..\n", 1425}, + {"\ +mount: I could not determine the filesystem type, and none was specified", 1426}, + {"mount: you must specify the filesystem type", 1427}, + {"mount: mount failed", 1428}, + {"mount: mount point %s is not a directory", 1429}, + {"mount: permission denied", 1430}, + {"mount: must be superuser to use mount", 1431}, + {"mount: %s is busy", 1432}, + {"mount: proc already mounted", 1433}, + {"mount: %s already mounted or %s busy", 1434}, + {"mount: mount point %s does not exist", 1435}, + {"mount: mount point %s is a symbolic link to nowhere", 1436}, + {"mount: special device %s does not exist", 1437}, {"\ mount: special device %s does not exist\n\ - (a path prefix is not a directory)\n", 1426}, - {"mount: %s not mounted already, or bad option", 1427}, + (a path prefix is not a directory)\n", 1438}, + {"mount: %s not mounted already, or bad option", 1439}, {"\ mount: wrong fs type, bad option, bad superblock on %s,\n\ - or too many mounted file systems", 1428}, - {"mount table full", 1429}, - {"mount: %s: can't read superblock", 1430}, - {"mount: %s has wrong major or minor number", 1431}, - {"mount: fs type %s not supported by kernel", 1432}, - {"mount: probably you meant %s", 1433}, - {"mount: maybe you meant iso9660 ?", 1434}, - {"mount: %s has wrong device number or fs type %s not supported", 1435}, - {"mount: %s is not a block device, and stat fails?", 1436}, + or too many mounted file systems", 1440}, + {"mount table full", 1441}, + {"mount: %s: can't read superblock", 1442}, + {"mount: %s: unknown device", 1443}, + {"mount: fs type %s not supported by kernel", 1444}, + {"mount: probably you meant %s", 1445}, + {"mount: maybe you meant iso9660 ?", 1446}, + {"mount: %s has wrong device number or fs type %s not supported", 1447}, + {"mount: %s is not a block device, and stat fails?", 1448}, {"\ mount: the kernel does not recognize %s as a block device\n\ - (maybe `insmod driver'?)", 1437}, - {"mount: %s is not a block device (maybe try `-o loop'?)", 1438}, - {"mount: %s is not a block device", 1439}, - {"mount: %s is not a valid block device", 1440}, - {"block device ", 1441}, - {"mount: %s%s is not permitted on its filesystem", 1442}, - {"mount: %s%s is write-protected but explicit `-w' flag given", 1443}, - {"mount: %s%s is write-protected, mounting read-only", 1444}, - {"mount: consider mounting %s by %s\n", 1445}, - {"UUID", 1446}, - {"label", 1447}, - {"mount: no such partition found", 1448}, - {"mount: no type was given - I'll assume nfs because of the colon\n", 1449}, - {"mount: backgrounding \"%s\"\n", 1450}, - {"mount: giving up \"%s\"\n", 1451}, - {"mount: %s already mounted on %s\n", 1452}, - {"\ -Usage: mount [-lhV]\n\ - mount -a [-nfFrsvw] [-t vfstypes]\n\ - mount [-nfrsvw] [-o options] special | node\n\ - mount [-nfrsvw] [-t vfstype] [-o options] special node\n\ - A special device can be indicated by -L label or -U uuid .\n", 1453}, - {"mount: only root can do that", 1454}, - {"mount: no %s found - creating it..\n", 1455}, - {"mount: mounting %s\n", 1456}, - {"not mounted anything", 1457}, - {"mount: cannot find %s in %s", 1458}, - {"mount: can't find %s in %s or %s", 1459}, - {"mount: bad UUID", 1460}, - {"mount: you didn't specify a filesystem type for %s\n", 1461}, - {" I will try all types mentioned in %s or %s\n", 1462}, - {" and it looks like this is swapspace\n", 1463}, - {" I will try type %s\n", 1464}, - {"Trying %s\n", 1465}, - {"mount: excessively long host:dir argument\n", 1466}, - {"mount: warning: multiple hostnames not supported\n", 1467}, - {"mount: directory to mount not in host:dir format\n", 1468}, - {"mount: can't get address for %s\n", 1469}, - {"mount: got bad hp->h_length\n", 1470}, - {"mount: excessively long option argument\n", 1471}, - {"Warning: Unrecognized proto= option.\n", 1472}, - {"Warning: Option namlen is not supported.\n", 1473}, - {"unknown nfs mount parameter: %s=%d\n", 1474}, - {"Warning: option nolock is not supported.\n", 1475}, - {"unknown nfs mount option: %s%s\n", 1476}, - {"mount: got bad hp->h_length?\n", 1477}, - {"NFS over TCP is not supported.\n", 1478}, - {"nfs socket", 1479}, - {"nfs bindresvport", 1480}, - {"used portmapper to find NFS port\n", 1481}, - {"using port %d for nfs deamon\n", 1482}, - {"nfs connect", 1483}, - {"unknown nfs status return value: %d", 1484}, - {"bug in xstrndup call", 1485}, + (maybe `insmod driver'?)", 1449}, + {"mount: %s is not a block device (maybe try `-o loop'?)", 1450}, + {"mount: %s is not a block device", 1451}, + {"mount: %s is not a valid block device", 1452}, + {"block device ", 1453}, + {"mount: cannot mount %s%s read-only", 1454}, + {"mount: %s%s is write-protected but explicit `-w' flag given", 1455}, + {"mount: %s%s is write-protected, mounting read-only", 1456}, + {"mount: going to mount %s by %s\n", 1457}, + {"UUID", 1458}, + {"label", 1459}, + {"mount: no such partition found", 1460}, + {"mount: no type was given - I'll assume nfs because of the colon\n", 1461}, + {"mount: backgrounding \"%s\"\n", 1462}, + {"mount: giving up \"%s\"\n", 1463}, + {"mount: %s already mounted on %s\n", 1464}, + {"\ +Usage: mount -V : print version\n\ + mount -h : print this help\n\ + mount : list mounted filesystems\n\ + mount -l : idem, including volume labels\n\ +So far the informational part. Next the mounting.\n\ +The command is `mount [-t fstype] something somewhere'.\n\ +Details found in /etc/fstab may be omitted.\n\ + mount -a : mount all stuff from /etc/fstab\n\ + mount device : mount device at the known place\n\ + mount directory : mount known device here\n\ + mount -t type dev dir : ordinary mount command\n\ +Note that one does not really mount a device, one mounts\n\ +a filesystem (of the given type) found on the device.\n\ +One can also mount an already visible directory tree elsewhere:\n\ + mount --bind olddir newdir\n\ +A device can be given by name, say /dev/hda1 or /dev/cdrom,\n\ +or by label, using -L label or by uuid, using -U uuid .\n\ +Union or stack mounts are specified using one of\n\ + --replace, --after, --before, --over\n\ +Other options: [-nfFrsvw] [-o options].\n\ +For many more details, say man 8 mount .\n", 1465}, + {"mount: only root can do that", 1466}, + {"mount: no %s found - creating it..\n", 1467}, + {"mount: mounting %s\n", 1468}, + {"not mounted anything", 1469}, + {"mount: cannot find %s in %s", 1470}, + {"mount: can't find %s in %s or %s", 1471}, + {"\ +mount: could not open %s, so UUID and LABEL conversion cannot be done.\n", 1472}, + {"mount: bad UUID", 1473}, + {"mount: you didn't specify a filesystem type for %s\n", 1474}, + {" I will try all types mentioned in %s or %s\n", 1475}, + {" and it looks like this is swapspace\n", 1476}, + {" I will try type %s\n", 1477}, + {"Trying %s\n", 1478}, + {"mount: excessively long host:dir argument\n", 1479}, + {"mount: warning: multiple hostnames not supported\n", 1480}, + {"mount: directory to mount not in host:dir format\n", 1481}, + {"mount: can't get address for %s\n", 1482}, + {"mount: got bad hp->h_length\n", 1483}, + {"mount: excessively long option argument\n", 1484}, + {"Warning: Unrecognized proto= option.\n", 1485}, + {"Warning: Option namlen is not supported.\n", 1486}, + {"unknown nfs mount parameter: %s=%d\n", 1487}, + {"Warning: option nolock is not supported.\n", 1488}, + {"unknown nfs mount option: %s%s\n", 1489}, + {"mount: got bad hp->h_length?\n", 1490}, + {"NFS over TCP is not supported.\n", 1491}, + {"nfs socket", 1492}, + {"nfs bindresvport", 1493}, + {"used portmapper to find NFS port\n", 1494}, + {"using port %d for nfs deamon\n", 1495}, + {"nfs connect", 1496}, + {"unknown nfs status return value: %d", 1497}, + {"bug in xstrndup call", 1498}, {"\ usage: %s [-hV]\n\ %s -a [-v]\n\ %s [-v] [-p priority] special ...\n\ - %s [-s]\n", 1486}, - {"%s on %s\n", 1487}, - {"swapon: cannot stat %s: %s\n", 1488}, - {"swapon: warning: %s has insecure permissions %04o, 0600 suggested\n", 1489}, - {"swapon: Skipping file %s - it appears to have holes.\n", 1490}, - {"%s: cannot open %s: %s\n", 1491}, - {"umount: compiled without support for -f\n", 1492}, - {"host: %s, directory: %s\n", 1493}, - {"umount: can't get address for %s\n", 1494}, - {"umount: got bad hostp->h_length\n", 1495}, - {"umount: %s: invalid block device", 1496}, - {"umount: %s: not mounted", 1497}, - {"umount: %s: can't write superblock", 1498}, - {"umount: %s: device is busy", 1499}, - {"umount: %s: not found", 1500}, - {"umount: %s: must be superuser to umount", 1501}, - {"umount: %s: block devices not permitted on fs", 1502}, - {"umount: %s: %s", 1503}, - {"no umount2, trying umount...\n", 1504}, - {"could not umount %s - trying %s instead\n", 1505}, - {"umount: %s busy - remounted read-only\n", 1506}, - {"umount: could not remount %s read-only\n", 1507}, - {"%s umounted\n", 1508}, - {"umount: cannot find list of filesystems to unmount", 1509}, + %s [-s]\n", 1499}, + {"%s on %s\n", 1500}, + {"swapon: cannot stat %s: %s\n", 1501}, + {"swapon: warning: %s has insecure permissions %04o, 0600 suggested\n", 1502}, + {"swapon: Skipping file %s - it appears to have holes.\n", 1503}, + {"%s: cannot open %s: %s\n", 1504}, + {"umount: compiled without support for -f\n", 1505}, + {"host: %s, directory: %s\n", 1506}, + {"umount: can't get address for %s\n", 1507}, + {"umount: got bad hostp->h_length\n", 1508}, + {"umount: %s: invalid block device", 1509}, + {"umount: %s: not mounted", 1510}, + {"umount: %s: can't write superblock", 1511}, + {"umount: %s: device is busy", 1512}, + {"umount: %s: not found", 1513}, + {"umount: %s: must be superuser to umount", 1514}, + {"umount: %s: block devices not permitted on fs", 1515}, + {"umount: %s: %s", 1516}, + {"no umount2, trying umount...\n", 1517}, + {"could not umount %s - trying %s instead\n", 1518}, + {"umount: %s busy - remounted read-only\n", 1519}, + {"umount: could not remount %s read-only\n", 1520}, + {"%s umounted\n", 1521}, + {"umount: cannot find list of filesystems to unmount", 1522}, {"\ Usage: umount [-hV]\n\ umount -a [-f] [-r] [-n] [-v] [-t vfstypes]\n\ - umount [-f] [-r] [-n] [-v] special | node...\n", 1510}, - {"umount: only root can do that", 1511}, - {"Trying to umount %s\n", 1512}, - {"Could not find %s in mtab\n", 1513}, - {"umount: %s is not mounted (according to mtab)", 1514}, - {"umount: it seems %s is mounted multiple times", 1515}, - {"umount: %s is not in the fstab (and you are not root)", 1516}, - {"umount: %s mount disagrees with the fstab", 1517}, - {"umount: only root can unmount %s from %s", 1518}, - {"umount: only %s can unmount %s from %s", 1519}, - {"You must be root to set the Ctrl-Alt-Del behaviour.\n", 1520}, - {"Usage: ctrlaltdel hard|soft\n", 1521}, + umount [-f] [-r] [-n] [-v] special | node...\n", 1523}, + {"umount: only root can do that", 1524}, + {"Trying to umount %s\n", 1525}, + {"Could not find %s in mtab\n", 1526}, + {"umount: %s is not mounted (according to mtab)", 1527}, + {"umount: it seems %s is mounted multiple times", 1528}, + {"umount: %s is not in the fstab (and you are not root)", 1529}, + {"umount: %s mount disagrees with the fstab", 1530}, + {"umount: only root can unmount %s from %s", 1531}, + {"umount: only %s can unmount %s from %s", 1532}, + {"You must be root to set the Ctrl-Alt-Del behaviour.\n", 1533}, + {"Usage: ctrlaltdel hard|soft\n", 1534}, {"\ File %s, For threshold value %lu, Maximum characters in fifo were %d,\n\ -and the maximum transfer rate in characters/second was %f\n", 1522}, +and the maximum transfer rate in characters/second was %f\n", 1535}, {"\ File %s, For threshold value %lu and timrout value %lu, Maximum characters \ in fifo were %d,\n\ -and the maximum transfer rate in characters/second was %f\n", 1523}, - {"Invalid interval value: %s\n", 1524}, - {"Invalid set value: %s\n", 1525}, - {"Invalid default value: %s\n", 1526}, - {"Invalid set time value: %s\n", 1527}, - {"Invalid default time value: %s\n", 1528}, +and the maximum transfer rate in characters/second was %f\n", 1536}, + {"Invalid interval value: %s\n", 1537}, + {"Invalid set value: %s\n", 1538}, + {"Invalid default value: %s\n", 1539}, + {"Invalid set time value: %s\n", 1540}, + {"Invalid default time value: %s\n", 1541}, {"\ Usage: %s [-q [-i interval]] ([-s value]|[-S value]) ([-t value]|[-T value]) \ -[-g|-G] file [file...]\n", 1529}, - {"Can't open %s: %s\n", 1530}, - {"Can't set %s to threshold %d: %s\n", 1531}, - {"Can't set %s to time threshold %d: %s\n", 1532}, - {"Can't get threshold for %s: %s\n", 1533}, - {"Can't get timeout for %s: %s\n", 1534}, - {"%s: %ld %s threshold and %ld %s timeout\n", 1535}, - {"current", 1536}, - {"default", 1537}, - {"Can't set signal handler", 1538}, - {"gettimeofday failed", 1539}, - {"Can't issue CYGETMON on %s: %s\n", 1540}, - {"%s: %lu ints, %lu/%lu chars; ", 1541}, - {"fifo: %lu thresh, %lu tmout, ", 1542}, - {"%lu max, %lu now\n", 1543}, - {" %f int/sec; %f rec, %f send (char/sec)\n", 1544}, - {"\ -%s: %lu ints, %lu chars; fifo: %lu thresh, %lu tmout, %lu max, %lu now\n", 1545}, - {" %f int/sec; %f rec (char/sec)\n", 1546}, - {"Usage: %s [-c] [-n level] [-s bufsize]\n", 1547}, - {"invalid id: %s\n", 1548}, - {"cannot remove id %s (%s)\n", 1549}, - {"usage: %s {shm | msg | sem} id ...\n", 1550}, - {"unknown resource type: %s\n", 1551}, - {"resource(s) deleted\n", 1552}, - {"usage : %s -asmq -tclup \n", 1553}, - {"\t%s [-s -m -q] -i id\n", 1554}, - {"\t%s -h for help.\n", 1555}, - {"%s provides information on ipc facilities for", 1556}, - {" which you have read access.\n", 1557}, +[-g|-G] file [file...]\n", 1542}, + {"Can't open %s: %s\n", 1543}, + {"Can't set %s to threshold %d: %s\n", 1544}, + {"Can't set %s to time threshold %d: %s\n", 1545}, + {"Can't get threshold for %s: %s\n", 1546}, + {"Can't get timeout for %s: %s\n", 1547}, + {"%s: %ld %s threshold and %ld %s timeout\n", 1548}, + {"current", 1549}, + {"default", 1550}, + {"Can't set signal handler", 1551}, + {"gettimeofday failed", 1552}, + {"Can't issue CYGETMON on %s: %s\n", 1553}, + {"%s: %lu ints, %lu/%lu chars; ", 1554}, + {"fifo: %lu thresh, %lu tmout, ", 1555}, + {"%lu max, %lu now\n", 1556}, + {" %f int/sec; %f rec, %f send (char/sec)\n", 1557}, + {"\ +%s: %lu ints, %lu chars; fifo: %lu thresh, %lu tmout, %lu max, %lu now\n", 1558}, + {" %f int/sec; %f rec (char/sec)\n", 1559}, + {"Usage: %s [-c] [-n level] [-s bufsize]\n", 1560}, + {"invalid id: %s\n", 1561}, + {"cannot remove id %s (%s)\n", 1562}, + {"usage: %s {shm | msg | sem} id ...\n", 1563}, + {"unknown resource type: %s\n", 1564}, + {"resource(s) deleted\n", 1565}, + {"usage : %s -asmq -tclup \n", 1566}, + {"\t%s [-s -m -q] -i id\n", 1567}, + {"\t%s -h for help.\n", 1568}, + {"%s provides information on ipc facilities for", 1569}, + {" which you have read access.\n", 1570}, {"\ Resource Specification:\n\ \t-m : shared_mem\n\ -\t-q : messages\n", 1558}, +\t-q : messages\n", 1571}, {"\ \t-s : semaphores\n\ -\t-a : all (default)\n", 1559}, +\t-a : all (default)\n", 1572}, {"\ Output Format:\n\ \t-t : time\n\ \t-p : pid\n\ -\t-c : creator\n", 1560}, +\t-c : creator\n", 1573}, {"\ \t-l : limits\n\ -\t-u : summary\n", 1561}, - {"-i id [-s -q -m] : details on resource identified by id\n", 1562}, - {"kernel not configured for shared memory\n", 1563}, - {"------ Shared Memory Limits --------\n", 1564}, - {"max number of segments = %d\n", 1565}, - {"max seg size (kbytes) = %d\n", 1566}, - {"max total shared memory (kbytes) = %d\n", 1567}, - {"min seg size (bytes) = %d\n", 1568}, - {"------ Shared Memory Status --------\n", 1569}, - {"segments allocated %d\n", 1570}, - {"pages allocated %ld\n", 1571}, - {"pages resident %ld\n", 1572}, - {"pages swapped %ld\n", 1573}, - {"Swap performance: %ld attempts\t %ld successes\n", 1574}, - {"------ Shared Memory Segment Creators/Owners --------\n", 1575}, - {"%-10s%-10s%-10s%-10s%-10s%-10s\n", 1576}, - {"shmid", 1577}, - {"perms", 1578}, - {"cuid", 1579}, - {"cgid", 1580}, - {"uid", 1581}, - {"gid", 1582}, - {"------ Shared Memory Attach/Detach/Change Times --------\n", 1583}, - {"%-10s%-10s %-20s%-20s%-20s\n", 1584}, - {"owner", 1585}, - {"attached", 1586}, - {"detached", 1587}, - {"changed", 1588}, - {"------ Shared Memory Creator/Last-op --------\n", 1589}, - {"%-10s%-10s%-10s%-10s\n", 1590}, - {"cpid", 1591}, - {"lpid", 1592}, - {"------ Shared Memory Segments --------\n", 1593}, - {"%-10s%-10s%-10s%-10s%-10s%-10s%-12s\n", 1594}, - {"key", 1595}, - {"bytes", 1596}, - {"nattch", 1597}, - {"status", 1598}, - {"Not set", 1599}, - {"dest", 1600}, - {"locked", 1601}, - {"kernel not configured for semaphores\n", 1602}, - {"------ Semaphore Limits --------\n", 1603}, - {"max number of arrays = %d\n", 1604}, - {"max semaphores per array = %d\n", 1605}, - {"max semaphores system wide = %d\n", 1606}, - {"max ops per semop call = %d\n", 1607}, - {"semaphore max value = %d\n", 1608}, - {"------ Semaphore Status --------\n", 1609}, - {"used arrays = %d\n", 1610}, - {"allocated semaphores = %d\n", 1611}, - {"------ Semaphore Arrays Creators/Owners --------\n", 1612}, - {"semid", 1613}, - {"------ Shared Memory Operation/Change Times --------\n", 1614}, - {"%-8s%-10s %-26.24s %-26.24s\n", 1615}, - {"last-op", 1616}, - {"last-changed", 1617}, - {"------ Semaphore Arrays --------\n", 1618}, - {"%-10s%-10s%-10s%-10s%-10s%-12s\n", 1619}, - {"nsems", 1620}, - {"------ Messages: Limits --------\n", 1621}, - {"max queues system wide = %d\n", 1622}, - {"max size of message (bytes) = %d\n", 1623}, - {"default max size of queue (bytes) = %d\n", 1624}, - {"------ Messages: Status --------\n", 1625}, - {"allocated queues = %d\n", 1626}, - {"used headers = %d\n", 1627}, - {"used space = %d bytes\n", 1628}, - {"------ Message Queues: Creators/Owners --------\n", 1629}, - {"msqid", 1630}, - {"------ Message Queues Send/Recv/Change Times --------\n", 1631}, - {"%-8s%-10s %-20s%-20s%-20s\n", 1632}, - {"send", 1633}, - {"recv", 1634}, - {"change", 1635}, - {"------ Message Queues PIDs --------\n", 1636}, - {"lspid", 1637}, - {"lrpid", 1638}, - {"------ Message Queues --------\n", 1639}, - {"%-10s%-10s%-10s%-10s%-12s%-12s\n", 1640}, - {"used-bytes", 1641}, - {"messages", 1642}, +\t-u : summary\n", 1574}, + {"-i id [-s -q -m] : details on resource identified by id\n", 1575}, + {"kernel not configured for shared memory\n", 1576}, + {"------ Shared Memory Limits --------\n", 1577}, + {"max number of segments = %ld\n", 1578}, + {"max seg size (kbytes) = %ld\n", 1579}, + {"max total shared memory (kbytes) = %ld\n", 1580}, + {"min seg size (bytes) = %ld\n", 1581}, + {"------ Shared Memory Status --------\n", 1582}, + {"segments allocated %d\n", 1583}, + {"pages allocated %ld\n", 1584}, + {"pages resident %ld\n", 1585}, + {"pages swapped %ld\n", 1586}, + {"Swap performance: %ld attempts\t %ld successes\n", 1587}, + {"------ Shared Memory Segment Creators/Owners --------\n", 1588}, + {"%-10s%-10s%-10s%-10s%-10s%-10s\n", 1589}, + {"shmid", 1590}, + {"perms", 1591}, + {"cuid", 1592}, + {"cgid", 1593}, + {"uid", 1594}, + {"gid", 1595}, + {"------ Shared Memory Attach/Detach/Change Times --------\n", 1596}, + {"%-10s%-10s %-20s%-20s%-20s\n", 1597}, + {"owner", 1598}, + {"attached", 1599}, + {"detached", 1600}, + {"changed", 1601}, + {"------ Shared Memory Creator/Last-op --------\n", 1602}, + {"%-10s%-10s%-10s%-10s\n", 1603}, + {"cpid", 1604}, + {"lpid", 1605}, + {"------ Shared Memory Segments --------\n", 1606}, + {"%-10s%-10s%-10s%-10s%-10s%-10s%-12s\n", 1607}, + {"key", 1608}, + {"bytes", 1609}, + {"nattch", 1610}, + {"status", 1611}, + {"Not set", 1612}, + {"dest", 1613}, + {"locked", 1614}, + {"kernel not configured for semaphores\n", 1615}, + {"------ Semaphore Limits --------\n", 1616}, + {"max number of arrays = %d\n", 1617}, + {"max semaphores per array = %d\n", 1618}, + {"max semaphores system wide = %d\n", 1619}, + {"max ops per semop call = %d\n", 1620}, + {"semaphore max value = %d\n", 1621}, + {"------ Semaphore Status --------\n", 1622}, + {"used arrays = %d\n", 1623}, + {"allocated semaphores = %d\n", 1624}, + {"------ Semaphore Arrays Creators/Owners --------\n", 1625}, + {"semid", 1626}, + {"------ Shared Memory Operation/Change Times --------\n", 1627}, + {"%-8s%-10s %-26.24s %-26.24s\n", 1628}, + {"last-op", 1629}, + {"last-changed", 1630}, + {"------ Semaphore Arrays --------\n", 1631}, + {"%-10s%-10s%-10s%-10s%-10s%-12s\n", 1632}, + {"nsems", 1633}, + {"------ Messages: Limits --------\n", 1634}, + {"max queues system wide = %d\n", 1635}, + {"max size of message (bytes) = %d\n", 1636}, + {"default max size of queue (bytes) = %d\n", 1637}, + {"------ Messages: Status --------\n", 1638}, + {"allocated queues = %d\n", 1639}, + {"used headers = %d\n", 1640}, + {"used space = %d bytes\n", 1641}, + {"------ Message Queues: Creators/Owners --------\n", 1642}, + {"msqid", 1643}, + {"------ Message Queues Send/Recv/Change Times --------\n", 1644}, + {"%-8s%-10s %-20s%-20s%-20s\n", 1645}, + {"send", 1646}, + {"recv", 1647}, + {"change", 1648}, + {"------ Message Queues PIDs --------\n", 1649}, + {"lspid", 1650}, + {"lrpid", 1651}, + {"------ Message Queues --------\n", 1652}, + {"%-10s%-10s%-10s%-10s%-12s%-12s\n", 1653}, + {"used-bytes", 1654}, + {"messages", 1655}, {"\ \n\ -Shared memory Segment shmid=%d\n", 1643}, - {"uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n", 1644}, - {"mode=%#o\taccess_perms=%#o\n", 1645}, - {"bytes=%d\tlpid=%d\tcpid=%d\tnattch=%d\n", 1646}, - {"att_time=%s", 1647}, - {"Not set\n", 1648}, - {"det_time=%s", 1649}, - {"change_time=%s", 1650}, +Shared memory Segment shmid=%d\n", 1656}, + {"uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n", 1657}, + {"mode=%#o\taccess_perms=%#o\n", 1658}, + {"bytes=%d\tlpid=%d\tcpid=%d\tnattch=%ld\n", 1659}, + {"att_time=%s", 1660}, + {"Not set\n", 1661}, + {"det_time=%s", 1662}, + {"change_time=%s", 1663}, {"\ \n\ -Message Queue msqid=%d\n", 1651}, - {"uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n", 1652}, - {"cbytes=%d\tqbytes=%d\tqnum=%d\tlspid=%d\tlrpid=%d\n", 1653}, - {"send_time=%srcv_time=%schange_time=%s", 1654}, - {"Not Set\n", 1655}, +Message Queue msqid=%d\n", 1664}, + {"uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n", 1665}, + {"cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n", 1666}, + {"send_time=%srcv_time=%schange_time=%s", 1667}, + {"Not Set\n", 1668}, {"\ \n\ -Semaphore Array semid=%d\n", 1656}, - {"uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n", 1657}, - {"mode=%#o, access_perms=%#o\n", 1658}, - {"nsems = %d\n", 1659}, - {"otime = %s", 1660}, - {"ctime = %s", 1661}, - {"%-10s%-10s%-10s%-10s%-10s\n", 1662}, - {"semnum", 1663}, - {"value", 1664}, - {"ncount", 1665}, - {"zcount", 1666}, - {"pid", 1667}, - {"usage: rdev [ -rsv ] [ -o OFFSET ] [ IMAGE [ VALUE [ OFFSET ] ] ]", 1668}, - {"\ - rdev /dev/fd0 (or rdev /linux, etc.) displays the current ROOT device", 1669}, - {" rdev /dev/fd0 /dev/hda2 sets ROOT to /dev/hda2", 1670}, - {" rdev -R /dev/fd0 1 set the ROOTFLAGS (readonly status)", 1671}, - {" rdev -s /dev/fd0 /dev/hda2 set the SWAP device", 1672}, - {" rdev -r /dev/fd0 627 set the RAMDISK size", 1673}, - {" rdev -v /dev/fd0 1 set the bootup VIDEOMODE", 1674}, - {" rdev -o N ... use the byte offset N", 1675}, - {" rootflags ... same as rdev -R", 1676}, - {" swapdev ... same as rdev -s", 1677}, - {" ramsize ... same as rdev -r", 1678}, - {" vidmode ... same as rdev -v", 1679}, - {"\ -Note: video modes are: -3=Ask, -2=Extended, -1=NormalVga, 1=key1, 2=key2,...", 1680}, - {" use -R 1 to mount root readonly, -R 0 for read/write.", 1681}, +Semaphore Array semid=%d\n", 1669}, + {"uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n", 1670}, + {"mode=%#o, access_perms=%#o\n", 1671}, + {"nsems = %ld\n", 1672}, + {"otime = %s", 1673}, + {"ctime = %s", 1674}, + {"%-10s%-10s%-10s%-10s%-10s\n", 1675}, + {"semnum", 1676}, + {"value", 1677}, + {"ncount", 1678}, + {"zcount", 1679}, + {"pid", 1680}, + {"usage: rdev [ -rsv ] [ -o OFFSET ] [ IMAGE [ VALUE [ OFFSET ] ] ]", 1681}, + {"\ + rdev /dev/fd0 (or rdev /linux, etc.) displays the current ROOT device", 1682}, + {" rdev /dev/fd0 /dev/hda2 sets ROOT to /dev/hda2", 1683}, + {" rdev -R /dev/fd0 1 set the ROOTFLAGS (readonly status)", 1684}, + {" rdev -s /dev/fd0 /dev/hda2 set the SWAP device", 1685}, + {" rdev -r /dev/fd0 627 set the RAMDISK size", 1686}, + {" rdev -v /dev/fd0 1 set the bootup VIDEOMODE", 1687}, + {" rdev -o N ... use the byte offset N", 1688}, + {" rootflags ... same as rdev -R", 1689}, + {" swapdev ... same as rdev -s", 1690}, + {" ramsize ... same as rdev -r", 1691}, + {" vidmode ... same as rdev -v", 1692}, + {"\ +Note: video modes are: -3=Ask, -2=Extended, -1=NormalVga, 1=key1, 2=key2,...", 1693}, + {" use -R 1 to mount root readonly, -R 0 for read/write.", 1694}, {"\ %s: Usage: \"%s [options]\n\ \t -m (default = \"%s\")\n\ @@ -2147,110 +2187,110 @@ Note: video modes are: -3=Ask, -2=Extended, -1=NormalVga, 1=key1, 2=key2,...", 1 \t -v print verbose data\n\ \t -a print all symbols, even if count is 0\n\ \t -r reset all the counters (root only)\n\ -\t -V print version and exit\n", 1682}, - {"%s Version %s\n", 1683}, - {"anything\n", 1684}, - {"Sampling_step: %i\n", 1685}, - {"%s: %s(%i): wrong map line\n", 1686}, - {"%s: can't find \"_stext\" in %s\n", 1687}, - {"total", 1688}, - {"\ -usage: renice priority [ [ -p ] pids ] [ [ -g ] pgrps ] [ [ -u ] users ]\n", 1689}, - {"renice: %s: unknown user\n", 1690}, - {"renice: %s: bad value\n", 1691}, - {"getpriority", 1692}, - {"setpriority", 1693}, - {"%d: old priority %d, new priority %d\n", 1694}, - {"usage: %s program [arg ...]\n", 1695}, +\t -V print version and exit\n", 1695}, + {"%s Version %s\n", 1696}, + {"anything\n", 1697}, + {"Sampling_step: %i\n", 1698}, + {"%s: %s(%i): wrong map line\n", 1699}, + {"%s: can't find \"_stext\" in %s\n", 1700}, + {"total", 1701}, + {"\ +usage: renice priority [ [ -p ] pids ] [ [ -g ] pgrps ] [ [ -u ] users ]\n", 1702}, + {"renice: %s: unknown user\n", 1703}, + {"renice: %s: bad value\n", 1704}, + {"getpriority", 1705}, + {"setpriority", 1706}, + {"%d: old priority %d, new priority %d\n", 1707}, + {"usage: %s program [arg ...]\n", 1708}, {"\ Usage: %s [ -i | -t