diff options
author | Karel Zak | 2006-12-07 00:25:34 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:34 +0100 |
commit | fd6b7a7ffc50400704beb41d5a23af5f9edb1eed (patch) | |
tree | 997c0ca2abc018369babd7da59bcd0afe492068e /sys-utils | |
parent | Imported from util-linux-2.5 tarball. (diff) | |
download | kernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.tar.gz kernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.tar.xz kernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.zip |
Imported from util-linux-2.7.1 tarball.
Diffstat (limited to 'sys-utils')
31 files changed, 3024 insertions, 1853 deletions
diff --git a/sys-utils/Makefile b/sys-utils/Makefile index fc5afd4eb..9513717ee 100644 --- a/sys-utils/Makefile +++ b/sys-utils/Makefile @@ -1,7 +1,8 @@ # Makefile -- Makefile for util-linux Linux utilities # Created: Sat Dec 26 20:09:40 1992 -# Revised: Sat Oct 7 19:24:39 1995 by r.faith@ieee.org +# Revised: Mon Aug 19 20:12:33 1996 by faith@cs.unc.edu # Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu) +# Copyright 1996 Nicolai Langfeldt (janl@math.uio.no)?? # include ../MCONFIG @@ -10,21 +11,37 @@ include ../MCONFIG MAN1= arch.1 readprofile.1 -MAN8= chroot.8 clock.8 ctrlaltdel.8 cytune.8 dmesg.8 \ - ipcrm.8 ipcs.8 kbdrate.8 ramsize.8 rdev.8 renice.8 \ - rootflags.8 setserial.8 setsid.8 swapdev.8 sync.8 tunelp.8 \ - vidmode.8 +MAN8= chroot.8 ctrlaltdel.8 cytune.8 dmesg.8 \ + ipcrm.8 ipcs.8 kbdrate.8 ramsize.8 renice.8 \ + rootflags.8 setsid.8 swapdev.8 tunelp.8 \ + vidmode.8 + +ifneq "$(CPU)" "sparc" +MAN8:= $(MAN8) hwclock.8 +endif + +ifeq "$(CPU)" "intel" +MAN8:= $(MAN8) rdev.8 +endif # Where to put binaries? # See the "install" rule for the links. . . -SBIN= clock ctrlaltdel kbdrate sln +SBIN= sln ctrlaltdel kbdrate + +ifneq "$(CPU)" "sparc" +SBIN:=$(SBIN) hwclock +endif -BIN= arch dmesg setserial sync +BIN= arch dmesg USRSBIN= chroot -USRBIN= cytune ipcrm ipcs rdev renice readprofile setsid tunelp +USRBIN= cytune ipcrm ipcs renice readprofile setsid tunelp + +ifeq "$(CPU)" "intel" +USRBIN:=$(USRBIN) rdev +endif # Where to put datebase files? @@ -35,14 +52,12 @@ all: $(SBIN) $(BIN) $(USRSBIN) $(USRBIN) sln: sln.c $(CC) -static $(CFLAGS) $(LDFLAGS) $< -o $@ -sync: sync.S - $(CC) -nostdlib $(LDFLAGS) $< -o $@ - # Rules for everything else arch: arch.o chroot: chroot.o -clock: clock.o +hwclock.o: hwclock.c shhopt.h +hwclock: hwclock.o shhopt.o ctrlaltdel: ctrlaltdel.o ipcrm: ipcrm.o ipcs: ipcs.o @@ -50,7 +65,6 @@ kbdrate: kbdrate.o rdev: rdev.o renice: renice.o readprofile: readprofile.o -setserial: setserial.o setsid: setsid.o install: all diff --git a/sys-utils/README.MAKEDEV b/sys-utils/README.MAKEDEV deleted file mode 100644 index 02652b2b6..000000000 --- a/sys-utils/README.MAKEDEV +++ /dev/null @@ -1,24 +0,0 @@ -$Id: README.MAKEDEV,v 2.2 1995/06/04 16:32:02 faith Exp $ - -Here is the original comment taken from the MAKEDEV script. One day, -I'll do this properly. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - -This is my attempt at a MAKEDEV script. IMHO it cleans up many areas. -It can be used to determine the necessary info for a device without -actually creating it using the '-n' flag. - -It makes less individual devices and tends to make classes of devices -(eg "MAKEDEV hda" will create "hda" and the 8 partitions; "MAKEDEV ptyp" -will create the ptyp[0-f] master and ttyp[0-f] slave devices). - -If you are aware of any glaring omissions or errors, please let me know. -Also, if you are a developer who wants your devices supported by MAKEDEV, -let me know. - -Thanks go to many people. Ian Jackson for the original help and -encouragement, to Matthias Urlichs for plugging "MAKEDEV update", and -to the many others that have bought errors and omissions to my attention. - - Nick Holloway <Nick.Holloway@alfie.demon.co.uk> diff --git a/sys-utils/README.hwclock b/sys-utils/README.hwclock new file mode 100644 index 000000000..7d2f460dd --- /dev/null +++ b/sys-utils/README.hwclock @@ -0,0 +1,46 @@ +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. + +Hwclock is shipped with an ELF executable built for ISA (Intel) +machines. So there is nothing to build for those machines. Just +install the executable file "hwclock" and the man page file +"hwclock.8" in suitable directories (like /sbin/hwclock and +/usr/man/man8/hwclock.8) and you're ready to go. + +hwclock accesses platform-dependent hardware, so if you have something +other than an ISA machine, the shipped executable probably doesn't work, +and you have to compile hwclock yourself. + +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 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. An ELF +executable of this library is included in the package, but you can use +a copy that is already on your system by altering the make file. You +can find a more authoritative copy of this library, and its source +code, on sunsite (ftp://sunsite.unc.edu/pub/Linux/libs/shhopt-X.Y). + +As shipped, the routines are linked in statically, so you only need the +libsshopt.a file to build hwclock, not to run it. + + + + diff --git a/sys-utils/README.linux68k b/sys-utils/README.linux68k new file mode 100644 index 000000000..ae6367130 --- /dev/null +++ b/sys-utils/README.linux68k @@ -0,0 +1,11 @@ + +Here are the ports of the clock and kbdrate utilities that needed +/dev/port in their original implementation. /dev/port does not exist +under Linux/68k, so the needed functionalities are implemented as new +ioctls in the kernel. The modified sources (in src/) first test if the +kernel knows that ioctls. If it does, they are used. Else, /dev/port +is tried the old way. The kernel patch necessary for clock and kbdrate +is in kernel-patch/. (It is #14a of my patch list to 0.9pl4). + +Roman (Roman.Hodek@informatik.uni-erlangen.de) + diff --git a/sys-utils/README.setserial b/sys-utils/README.setserial deleted file mode 100644 index bf3a5847d..000000000 --- a/sys-utils/README.setserial +++ /dev/null @@ -1,73 +0,0 @@ -setserial Version 2.10 - -Setserial is a program which allows you to look at and change various -attributes of a serial device, including its port, its IRQ, and other -serial port options. - -Starting with Linux 0.99 pl10, only the COM1-4 ports are configured, -using the default IRQ of 4 and 3. So, if you have any other serial -ports provided by other boards (such as an AST Fourport), or if COM3-4 -have been a non-standard IRQ so that you can use time simultaneously -with COM1-2, you *must* use this program in order to configure those -serial ports. - -The simplest way to configure the serial ports is to copy the provided -rc.serial file to /etc/rc.serial, and then add to /etc/rc the lines: - -if [ -f /etc/rc.serial ]; then -sh /etc/rc.serial -fi - -Take a look at /etc/rc.serial; it was written to be relatively easy to -modify, and you may need to modify it so that it works best in your -environment. - - -------------------------------------------------------- - -Here is setserial's command line syntax: - -usage: ./setserial [-abgqvVW] serial-device [cmd1 [arg]] [cmd2] ... - -Available options: - -a Display all possible information about the port - -b Display boot-time level of information - -q Quiet flag - -v Verbose flag - - -g Get and display the serial information of all - serial ports on the machine - -V Display the current Version and then exit - - -W Do wild interrupt initialization and then exit - -Available commands: (* = Takes an argument) - (^ = can be preceded by a '^' to turn off the option) - * port set the I/O port - * irq set the interrupt - * uart set UART type (none, 8250, 16450, 16550, 16550A - * baud_base set base baud rate (CLOCK_FREQ / 16) - * divisor set the custom divisor (see spd_custom) - ^ fourport configure the port as an AST Fourport - autoconfigure automatically configure the serial port - ^ auto_irq try to determine irq during autoconfiguration - ^ skip_test skip UART test during autoconfiguration - - ^ sak set the break key as the Secure Attention Key - ^ session_lockout Lock out callout port across different sessions - ^ pgrp_lockout Lock out callout port across different process groups - ^ split_termios Use separate termios for callout and dailin lines - ^ hup_notify Notify a process blocked on opening a dialin line - when a process has finished using a callout - line by returning EAGAIN to the open. - ^ callout_nohup Don't hangup the tty if carrier detect drops on a - callout line. - - spd_hi use 56kb instead of 38.4kb - spd_vhi use 115kb instead of 38.4kb - spd_cust use the custom divisor to set the speed at 38.4kb - (baud rate = baud_base / custom_divisor) - spd_normal use 38.4kb when a buad rate of 38.4kb is selected - -Use a leading '0x' for hex numbers. -CAUTION: Using an invalid port can lock up your machine! diff --git a/sys-utils/README.shhopt-1.1 b/sys-utils/README.shhopt-1.1 new file mode 100644 index 000000000..766d6cbdc --- /dev/null +++ b/sys-utils/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/sys-utils/arch.1 b/sys-utils/arch.1 index c465c55fe..a2830ed3c 100644 --- a/sys-utils/arch.1 +++ b/sys-utils/arch.1 @@ -1,7 +1,7 @@ .\" arch.1 -- .\" Copyright 1993 Rickard E. Faith (faith@cs.unc.edu) .\" Public domain: may be freely distributed. -.TH ARCH 1 "20 December 1993" "Linux 0.99" "Linux Programmer's Manual" +.TH ARCH 1 "4 July 1997" "Linux 2.0" "Linux Programmer's Manual" .SH NAME arch \- print machine architecture .SH SYNOPSIS @@ -13,6 +13,6 @@ is equivalent to On current Linux systems, .B arch -prints "i386" or "i486". +prints things such as "i386" or "i486". .SH SEE ALSO .BR uname (1) ", " uname (2) diff --git a/sys-utils/clock.8 b/sys-utils/clock.8 deleted file mode 100644 index 1f6139ae4..000000000 --- a/sys-utils/clock.8 +++ /dev/null @@ -1,108 +0,0 @@ -.\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu) -.\" May be distributed under the GNU General Public License -.TH CLOCK 8 "24 December 1992" "Linux 0.99" "Linux Programmer's Manual" -.SH NAME -clock \- manipulate the CMOS clock -.SH SYNOPSIS -.B "/sbin/clock [ -u ] -r" -.br -.B "/sbin/clock [ -u ] -w" -.br -.B "/sbin/clock [ -u ] -s" -.br -.B "/sbin/clock [ -u ] -a" -.SH DESCRIPTION -.B clock -manipulates the CMOS clock in variaous ways, allowing it to be read or -written, and allowing synchronization between the CMOS clock and the -kernel's version of the system time. -.SH OPTIONS -.TP -.B \-u -Indicates that the CMOS clock is set to Universal Time. -.TP -.B \-r -Read CMOS clock and print the result to stdout. -.TP -.B \-w -Write the system time into the CMOS clock. -.TP -.B \-s -Set the system time from the CMOS clock. -.TP -.B \-a -Set the system time from the CMOS clock, adjusting the time to correct for -systematic error, and writting it back into the CMOS clock. -.sp -This option uses the file -.I /etc/adjtime -to determine how the clock changes. It contains three numbers: -.RS -The first number is the correction in seconds per day (for example, if your -clock runs 5 seconds fast each day, the first number should read -5.0). -.LP -The second number tells when -.B clock -was last used, in seconds since 1/1/1970. -.LP -The third number is the remaining part of a second that was left over after -the last adjustment. -.LP -The following instructions are from the source code: -.TP -a) -create a file -.I /etc/adjtime -containing as the first and only line: '0.0 0 0.0' -.TP -b) -run -.I "clock -au" -or -.IR "clock -a" , -depending on whether your CMOS is in Universal or Local Time. This updates -the second number. -.TP -c) -set your system time using the -.I date -command. -.TP -d) -update your CMOS time using -.I "clock -wu" -or -.I clock -w -.TP -e) -replace the first number in -.I /etc/adjtime -by your correction. -.TP -f) -put the command -.I "clock -au" -or -.I "clock -a" -in your -.IR /etc/rc.local , -or let -.BR cron (8) -start it regularly. -.RE -.SH FILES -.I /etc/adjtime -.br -.I /etc/rc.local -.SH AUTHORS -.TP -.B V1.0 -Charles Hedrick, hedrick@cs.rutgers.edu, Apr 1992 -.TP -.B V1.1 -Modified for clock adjustments, Rob Hooft, hooft@chem.ruu.nl, Nov 1992 -.TP -.B V1.2 -Patches by Harald Koenig, koenig@nova.tat.physik.uni-tuebingen.de, -applied by Rob Hooft, hooft@EMBL-Heidelberg.DE, Oct 1993 -.sp diff --git a/sys-utils/clock.c b/sys-utils/clock.c deleted file mode 100644 index 15020c260..000000000 --- a/sys-utils/clock.c +++ /dev/null @@ -1,490 +0,0 @@ -#include <stdio.h> -#include <errno.h> -#include <stdlib.h> -#include <unistd.h> -#include <getopt.h> -#include <time.h> -#include <sys/time.h> -#include <string.h> - -#define USE_INLINE_ASM_IO - -#ifdef USE_INLINE_ASM_IO -#include <asm/io.h> -#endif - -/* 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 the CMOS port. - * - * I don't know what the CMOS clock will do in 2000, so this program - * probably won't work past the century boundary. - * - ********************* - * 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. - * - */ - -#define VERSION "1.4" - -/* Here the information for time adjustments is kept. */ -#define ADJPATH "/etc/adjtime" - - -/* 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; - -volatile void -usage () -{ - 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 (1); -} - -#ifndef USE_INLINE_ASM_IO -int cmos_fd; -#endif - -static inline unsigned char cmos_read(unsigned char reg) -{ - register unsigned char ret; - __asm__ volatile ("cli"); - outb (reg | 0x80, 0x70); - ret = inb (0x71); - __asm__ volatile ("sti"); - return ret; -} - -static inline void cmos_write(unsigned char reg, unsigned char val) -{ - outb (reg | 0x80, 0x70); - outb (val, 0x71); -} - -#ifndef outb -static inline void -outb (char val, unsigned short port) -{ -#ifdef USE_INLINE_ASM_IO - __asm__ volatile ("out%B0 %0,%1"::"a" (val), "d" (port)); -#else - lseek (cmos_fd, port, 0); - write (cmos_fd, &val, 1); -#endif -} -#endif - -#ifndef inb -static inline unsigned char -inb (unsigned short port) -{ - unsigned char ret; -#ifdef USE_INLINE_ASM_IO - __asm__ volatile ("in%B0 %1,%0":"=a" (ret):"d" (port)); -#else - lseek (cmos_fd, port, 0); - read (cmos_fd, &ret, 1); -#endif - return ret; -} -#endif - -void -cmos_init () -{ -#ifdef USE_INLINE_ASM_IO - if (iopl (3)) - { - fprintf(stderr,"clock: unable to get I/O port access\n"); - exit (1); - } -#else - cmos_fd = open ("/dev/port", 2); - if (cmos_fd < 0) - { - perror ("unable to open /dev/port read/write : "); - exit (1); - } - if (lseek (cmos_fd, 0x70, 0) < 0 || lseek (cmos_fd, 0x71, 0) < 0) - { - perror ("unable to seek port 0x70 in /dev/port : "); - exit (1); - } -#endif -} - -static inline int -cmos_read_bcd (int addr) -{ - int b; - b = cmos_read (addr); - return (b & 15) + (b >> 4) * 10; -} - -static inline void -cmos_write_bcd (int addr, int value) -{ - cmos_write (addr, ((value / 10) << 4) + value % 10); -} - -int -main (int argc, char **argv, char **envp) -{ - struct tm tm; - time_t systime; - time_t last_time; - char arg; - double factor; - double not_adjusted; - int adjustment = 0; - unsigned char save_control, save_freq_select; - - 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': - fprintf( stderr, "clock " VERSION "\n" ); - exit(0); - default: - usage (); - } - } - - if (readit + writeit + setit + adjustit > 1) - usage (); /* only allow one of these */ - - if (!(readit | writeit | setit | adjustit)) /* default to read */ - readit = 1; - - cmos_init (); - - if (adjustit) - { /* Read adjustment parameters first */ - FILE *adj; - if ((adj = fopen (ADJPATH, "r")) == NULL) - { - perror (ADJPATH); - exit (2); - } - if (fscanf (adj, "%lf %d %lf", &factor, &last_time, ¬_adjusted) < 0) - { - perror (ADJPATH); - exit (2); - } - fclose (adj); - if (debug) printf ("Last adjustment done at %d seconds after 1/1/1970\n", last_time); - } - - if (readit || setit || adjustit) - { - int i; - -/* read RTC exactly on falling edge of update flag */ -/* Wait for rise.... (may take upto 1 second) */ - - for (i = 0; i < 10000000; i++) - if (cmos_read (10) & 0x80) - break; - -/* Wait for fall.... (must try at least 2.228 ms) */ - - for (i = 0; i < 1000000; i++) - if (!(cmos_read (10) & 0x80)) - break; - -/* The purpose of the "do" loop is called "low-risk programming" */ -/* In theory it should never run more than once */ - do - { - tm.tm_sec = cmos_read_bcd (0); - tm.tm_min = cmos_read_bcd (2); - tm.tm_hour = cmos_read_bcd (4); - tm.tm_wday = cmos_read_bcd (6); - tm.tm_mday = cmos_read_bcd (7); - tm.tm_mon = cmos_read_bcd (8); - tm.tm_year = cmos_read_bcd (9); - } - while (tm.tm_sec != cmos_read_bcd (0)); - if (tm.tm_year < 70) - tm.tm_year += 100; /* 70..99 => 1970..1999, 0..69 => 2000..2069 */ - tm.tm_mon--; /* DOS uses 1 base */ - tm.tm_wday -= 3; /* DOS uses 3 - 9 for week days */ - tm.tm_isdst = -1; /* don't know whether it's daylight */ - if (debug) printf ("Cmos time : %d:%d:%d\n", tm.tm_hour, tm.tm_min, tm.tm_sec); - } - - if (readit || setit || adjustit) - { -/* - * mktime() assumes we're giving it local time. If the CMOS clock - * is in GMT, we have to set up TZ so mktime knows it. tzset() gets - * called implicitly by the time code, but only the first time. When - * changing the environment variable, better call tzset() explicitly. - */ - if (universal) - { - char *zone; - zone = (char *) getenv ("TZ"); /* save original time zone */ - (void) putenv ("TZ="); - tzset (); - systime = mktime (&tm); - /* now put back the original zone */ - if (zone) - { - - char *zonebuf; - zonebuf = malloc (strlen (zone) + 4); - strcpy (zonebuf, "TZ="); - strcpy (zonebuf+3, zone); - putenv (zonebuf); - free (zonebuf); - } - else - { /* wasn't one, so clear it */ - putenv ("TZ"); - } - tzset (); - } - else - { - systime = mktime (&tm); - } - if (debug) printf ("Number of seconds since 1/1/1970 is %d\n", systime); - } - - if (readit) - { - printf ("%s", ctime (&systime )); - } - - if (setit || adjustit) - { - struct timeval tv; - struct timezone tz; - -/* program is designed to run setuid, be secure! */ - - if (getuid () != 0) - { - fprintf (stderr, "Sorry, must be root to set or adjust time\n"); - exit (2); - } - - 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) { - printf ("Time since last adjustment is %d seconds\n", - (int) (systime - last_time)); - printf ("Adjusting time by %d seconds\n", - adjustment); - 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) - { - fprintf (stderr, - "Unable to set time -- probably you are not root\n"); - exit (1); - } - - if (debug) { - printf( "Called settimeofday:\n" ); - printf( "\ttv.tv_sec = %ld, tv.tv_usec = %ld\n", - tv.tv_sec, tv.tv_usec ); - printf( "\ttz.tz_minuteswest = %d, tz.tz_dsttime = %d\n", - tz.tz_minuteswest, tz.tz_dsttime ); - } -#endif - } - - if (writeit || (adjustit && adjustment != 0)) - { - struct tm *tmp; - systime = time (NULL); - if (universal) - tmp = gmtime (&systime); - else - tmp = localtime (&systime); - -#ifndef KEEP_OFF - __asm__ volatile ("cli"); - 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)); - - cmos_write_bcd (0, tmp->tm_sec); - cmos_write_bcd (2, tmp->tm_min); - cmos_write_bcd (4, tmp->tm_hour); - cmos_write_bcd (6, tmp->tm_wday + 3); - cmos_write_bcd (7, tmp->tm_mday); - cmos_write_bcd (8, tmp->tm_mon + 1); - cmos_write_bcd (9, tmp->tm_year); - - cmos_write (10, save_freq_select); - cmos_write (11, save_control); - __asm__ volatile ("sti"); -#endif - if (debug) printf ("Set to : %d:%d:%d\n", tmp->tm_hour, tmp->tm_min, tmp->tm_sec); - } - else - if (debug) printf ("CMOS clock unchanged.\n"); - /* Save data for next 'adjustit' call */ - if (adjustit) - { - FILE *adj; - if ((adj = fopen (ADJPATH, "w")) == NULL) - { - perror (ADJPATH); - exit (2); - } - fprintf (adj, "%f %d %f\n", factor, systime, not_adjusted); - fclose (adj); - } - exit (0); -} diff --git a/sys-utils/cytune.c b/sys-utils/cytune.c index 32a27006b..f7fe1ee38 100644 --- a/sys-utils/cytune.c +++ b/sys-utils/cytune.c @@ -35,11 +35,11 @@ #include <stdio.h> #include <stdlib.h> -#include <sys/serial.h> #include <sys/types.h> #include <sys/time.h> #include <sys/ioctl.h> #include <unistd.h> +#include <string.h> #include <fcntl.h> #include <errno.h> #include <linux/tty.h> @@ -151,7 +151,7 @@ static int set_def_time_val = -1; int main(int argc, char *argv[]) { struct timeval lasttime, thistime; - struct timezone tz = {0,DST_NONE}; + struct timezone tz = {0,0}; double diff; int errflg = 0; int file; diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c index 880528531..56beb3fea 100644 --- a/sys-utils/dmesg.c +++ b/sys-utils/dmesg.c @@ -9,13 +9,24 @@ #include <linux/unistd.h> #include <stdio.h> #include <getopt.h> +#include <stdlib.h> -#define __NR_klog __NR_syslog +#if __GNU_LIBRARY__ < 5 -static inline _syscall3(int,klog,int,type,char *,b,int,len) +#ifndef __alpha__ +# define __NR_klogctl __NR_syslog + static inline _syscall3(int, klogctl, int, type, char *, b, int, len); +#else /* __alpha__ */ +#define klogctl syslog +#endif + +#else +# include <sys/klog.h> +#endif static char *progname; +void usage() { fprintf( stderr, "Usage: %s [-c] [-n level]\n", progname ); @@ -27,7 +38,7 @@ int main( int argc, char *argv[] ) int i; int n; int c; - int level; + int level = 0; int lastc; int cmd = 3; @@ -56,17 +67,17 @@ int main( int argc, char *argv[] ) } if (cmd == 8) { - n = klog( cmd, NULL, level ); + n = klogctl( cmd, NULL, level ); if (n < 0) { - perror( "klog" ); + perror( "klogctl" ); exit( 1 ); } exit( 0 ); } - n = klog( cmd, buf, sizeof( buf ) ); + n = klogctl( cmd, buf, sizeof( buf ) ); if (n < 0) { - perror( "klog" ); + perror( "klogctl" ); exit( 1 ); } diff --git a/sys-utils/hwclock.8 b/sys-utils/hwclock.8 new file mode 100644 index 000000000..a7308a600 --- /dev/null +++ b/sys-utils/hwclock.8 @@ -0,0 +1,246 @@ +.TH CLOCK 8 "23 September 1996" +.SH NAME +clock \- query and set the ISA hardware clock (RTC) +.SH SYNOPSIS +.B "hwclock --show [ --utc ] [ --test ] [ --debug ]" +.br +.B "hwclock --set --date=newdate [ --utc ] [ --test ] [ --debug ]" +.br +.B "hwclock --systohc [ --utc ] [ --test ] [ --debug ]" +.br +.B "hwclock --hctosys [ --utc ] [ --test ] [ --debug ]" +.br +.B "hwclock --adjust [ --utc ] [ --test ] [ --debug ]" +.br +.B "hwclock --version [ --debug ] +.PP +Minimum unique abbreviations of all options are acceptable. +.PP +Also, equivalent options -r, -w, -s, -a, -v, -u, and -D are accepted for +compatibility with the program "clock". + +.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. +.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. 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 \-\-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" +.PP +The following options apply to most functions. +.TP +.B \-\-utc +Indicates that the Hardware Clock is kept in Universal Coordinated +Time. 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 +.I hwclock. +.PP +If you don't specify +.B --utc +when you should, or vice versa, both setting and querying of the +Hardware Clock will be messed up. +.TP +.B \-\-test +Do everything except actually updating the Hardware Clock. 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. It 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 +the ISA timer interrupt. 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 +.I 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 +.I adjtimex(8) +to smoothly adjust the System Time while the system runs. + + +.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. +.I 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, +.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 --set +at system startup time, and maybe periodically while the system is +running via cron. +.PP +The format of the adjtime file is: +.PP +Line 1: 3 numbers: 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 +.I clock +). +.PP +Line 2: 1 number: Resulting number of seconds since 1969 UTC of most +recent calibration. +.PP +You can use an adjtime file that was previously used with the +.I clock +program with +.I hwclock. + +.SH FILES +.I /etc/adjtime + +.SH SEE ALSO +adjtimex(8), date(1), gettimeofday(2), settimeofday(2), crontab(1) + +.SH AUTHORS +Written By Bryan Henderson, September 1996, 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/sys-utils/hwclock.c b/sys-utils/hwclock.c new file mode 100644 index 000000000..9f4d77149 --- /dev/null +++ b/sys-utils/hwclock.c @@ -0,0 +1,1623 @@ +/************************************************************************** + hwclock +*************************************************************************** + + This is a program for reading and setting the Hardware Clock on an ISA + family computer. This is the clock that is also known as the RTC, + real time clock, or, unfortunately, the CMOS clock. + + See man page for details. + + By Bryan Henderson, 96.09.19 + + Based on work by others; see history at end of source code. + +**************************************************************************/ +/************************************************************************** + 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 it + 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. + + 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). + +****************************************************************************/ + +#define _GNU_SOURCE /* for snprintf */ + +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <asm/io.h> +#include <shhopt.h> +#include "../version.h" + +#define MYNAME "hwclock" +#define VERSION "2.1" + +#define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1)); + +/* Here the information for time adjustments is kept. */ +#define ADJPATH "/etc/adjtime" + +/* Note that we must define the boolean type as int because we use the + shhopt option processing library which, unfortunately, returns flag + options as integers. It is customary to define bool as char, but + then we would have to do a lot of conversion in order to interface + with shhopt. +*/ +typedef int bool; +#define TRUE 1 +#define FALSE 0 + +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 <dirty>, 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; + float drift_factor; + time_t last_adj_time; + float not_adjusted; + time_t last_calib_time; +}; + + +enum clock_access_method {ISA, RTC_IOCTL, KD}; + /* A method for accessing (reading, writing) the hardware clock: + + ISA: + via direct CPU I/O instructions that work on an ISA family + machine (IBM PC compatible). + + RTC_IOCTL: + via the rtc device driver, using device special file /dev/rtc. + + KD: + via the console driver, using device special file /dev/console. + This is the m64k ioctl interface. + + NO_CLOCK: + Unable to determine a accessmethod for the system clock. + */ + + +/* The following are just constants. Oddly, this program will not + compile if the inb() and outb() functions use something even + slightly different from these variables. This is probably at least + partially related to the fact that __builtin_constant_p() doesn't + work (is never true) in an inline function. See comment to this + effect in asm/io.h. +*/ +static unsigned short clock_ctl_addr = 0x70; +static unsigned short clock_data_addr = 0x71; + +bool debug; + /* We are running in debug mode, wherein we put a lot of information about + what we're doing to standard error. Because of the pervasive and yet + background nature of this value, this is a global variable. */ + + +#include <linux/version.h> +/* Check if the /dev/rtc interface is available in this version of + the system headers. 131072 is linux 2.0.0. Might need to make + it conditional on i386 or something too -janl */ +#if LINUX_VERSION_CODE >= 131072 +#include <linux/mc146818rtc.h> +#include <linux/kd.h> +static const bool got_rtc = TRUE; +#else +/* Dummy to make it compile */ +#define RTC_SET_TIME 0 +static const bool got_rtc = FALSE; +#endif + + + +#if defined(KDGHWCLK) +static const bool got_kdghwclk = TRUE; +static const int kdghwclk_ioctl = KDGHWCLK; +static const int kdshwclk_ioctl = KDSHWCLK; +#else +static const bool got_kdghwclk = FALSE; +static const int kdghwclk_ioctl; /* Never used; just to make compile work */ +struct hwclk_time {char dummy;}; + /* Never used; just to make compile work */ +#endif + + + +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 ); +} + + +struct timeval +time_inc(struct timeval addend, float increment) { +/*---------------------------------------------------------------------------- + The time, in "timeval" format, which is <increment> seconds after + the time <addend>. Of course, <increment> 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 inline unsigned char +hclock_read(unsigned char reg) { +/*--------------------------------------------------------------------------- + Relative byte <reg> of the Hardware Clock value. +---------------------------------------------------------------------------*/ +#ifdef __i386__ + register unsigned char ret; + __asm__ volatile ("cli"); + /* & 0x7f ensures that we are not disabling NMI while we read. + Setting on Bit 7 here would disable NMI + */ + outb(reg & 0x7f, clock_ctl_addr); + ret = inb(clock_data_addr); + __asm__ volatile ("sti"); + return ret; +#endif +} + + + +static inline void +hclock_write(unsigned char reg, unsigned char val) { +/*---------------------------------------------------------------------------- + Set relative byte <reg> of the Hardware Clock value to <val>. +----------------------------------------------------------------------------*/ +#ifdef __i386__ + /* & 0x7f ensures that we are not disabling NMI while we read. + Setting on Bit 7 here would disable NMI + */ + outb(reg & 0x7f, clock_ctl_addr); + outb(val, clock_data_addr); +#endif +} + + + +static inline int +hclock_read_bcd (int addr) { + int b; + b = hclock_read(addr); + return (b & 15) + (b >> 4) * 10; +} + +static inline void +hclock_write_bcd(int addr, int value) { + hclock_write(addr, ((value / 10) << 4) + value % 10); +} + + +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; + + *rc_p = 0; + } else { + adjfile = fopen(ADJPATH, "r"); /* open file for reading */ + if (adjfile == NULL) { + const int fopen_errno = errno; + fprintf(stderr, MYNAME " is unable to open file " ADJPATH ". " + "fopen() errno=%d:%s", fopen_errno, strerror(fopen_errno)); + *rc_p = 2; + } else { + char line1[81]; /* String: first line of adjtime file */ + char line2[81]; /* String: second 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); + + 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); + + *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); + } + } +} + + + +void +synchronize_to_clock_tick_ISA(int *retcode_p) { +/*---------------------------------------------------------------------------- + Same as synchronize_to_clock_tick(), but just for ISA. +-----------------------------------------------------------------------------*/ + int i; /* local loop index */ + + /* 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; !(hclock_read(10) & 0x80) && (i < 10000000); i++); + if (i >= 10000000) *retcode_p = 1; + else { + /* Wait for fall. Should be within 2.228 ms. */ + for (i = 0; (hclock_read(10) & 0x80) && (i < 1000000); i++); + if (i >= 10000000) *retcode_p = 1; + else *retcode_p = 0; + } +} + + + +void +synchronize_to_clock_tick_RTC(int *retcode_p) { +/*---------------------------------------------------------------------------- + Same as synchronize_to_clock_tick(), but just for /dev/rtc. +-----------------------------------------------------------------------------*/ +#if defined(_MC146818RTC_H) + int rc; /* local return code */ + int rtc_fd; /* File descriptor of /dev/rtc */ + + rtc_fd = open("/dev/rtc",O_RDONLY); + if (rtc_fd == -1) { + fprintf(stderr, "open() of /dev/rtc failed, errno = %s (%d).\n", + strerror(errno), errno); + *retcode_p = 1; + } else { + /* Turn on update interrupts (one per second) */ + rc = ioctl(rtc_fd, RTC_UIE_ON, 0); + if (rc == -1) { + fprintf(stderr, "ioctl() to /dev/rtc to turn on update interrupts " + "failed, errno = %s (%d).\n", strerror(errno), errno); + *retcode_p = 1; + } else { + unsigned long dummy; + + /* this blocks */ + rc = read(rtc_fd, &dummy, sizeof(unsigned long)); + if (rc == -1) { + fprintf(stderr, "read() to /dev/rtc to wait for clock tick failed, " + "errno = %s (%d).\n", strerror(errno), errno); + *retcode_p = 1; + } else { + *retcode_p = 0; + + /* Turn off update interrupts */ + rc = ioctl(rtc_fd, RTC_UIE_OFF, 0); + if (rc == -1) { + fprintf(stderr, "ioctl() to /dev/rtc to turn off update interrupts " + "failed, errno = %s (%d).\n", strerror(errno), errno); + } + } + } + close(rtc_fd); + } +#else +/* This function should never be called. It is here just to make the + program compile. +*/ +#endif +} + + + +int +synchronize_to_clock_tick(enum clock_access_method clock_access) { +/*----------------------------------------------------------------------------- + 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. + + For the KD clock access method, we have no way to synchronize, so we + just return immediately. This will mess some things up, but it's the + best we can do. + + Return 1 if something weird goes wrong (nothing can normally go wrong), + 0 if everything OK. + +-----------------------------------------------------------------------------*/ + int retcode; /* our eventual return code */ + + if (debug) printf("Waiting for clock tick...\n"); + + switch (clock_access) { + case ISA: synchronize_to_clock_tick_ISA(&retcode); break; + case RTC_IOCTL: synchronize_to_clock_tick_RTC(&retcode); break; + case KD: + if (debug) + printf("Can't wait for clock tick because we're using the Alpha " + "/dev/console clock! Assuming a clock tick.\n"); + retcode = 1; + break; + default: + fprintf(stderr, "Internal error in synchronize_to_clock_tick. Invalid " + "value for clock_access argument.\n"); + retcode = 1; + } + if (debug) printf("...got clock tick\n"); + return(retcode); +} + + + +time_t +mktime_tz(struct tm tm, const bool universal) { +/*----------------------------------------------------------------------------- + Convert a time in broken down format (hours, minutes, etc.) into standard + unix time (seconds into epoch). + + The broken down time is argument <tm>. 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. +-----------------------------------------------------------------------------*/ + time_t systime; /* our eventual return value */ + 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 */ + (void) putenv("TZ="); + /* Note: tzset() gets called implicitly by the time code, but only the + first time. When changing the environment variable, better call + tzset() explicitly. + */ + tzset(); + } + systime = mktime(&tm); + if (systime == -1) { + /* We don't expect this to happen. Consider this a crash */ + fprintf(stderr, "mktime() failed unexpectedly (rc -1). Aborting.\n"); + exit(2); + } + + /* now put back the original zone. */ + if (zone) + setenv ("TZ", zone, 1); + else + putenv ("TZ"); + tzset(); + + if (debug) + printf("Hw clock time : %.2d:%.2d:%.2d = %d seconds since 1969\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, (int) systime); + + return(systime); +} + + + +void +read_hardware_clock_kd(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via <tm> + argument. Use ioctls to /dev/console on what we assume is an Alpha + machine. +-----------------------------------------------------------------------------*/ +#ifdef KDGHWCLK + int con_fd; + struct hwclk_time t; + + con_fd = open("/dev/console", O_RDONLY); + if (con_fd < 0) { + fprintf(stderr, "open() failed to open /dev/console, errno = %s (%d).\n", + strerror(errno), errno); + exit(5); + } else { + int rc; /* return code from ioctl() */ + + rc = ioctl(con_fd, kdghwclk_ioctl, &t); + if (rc == -1) { + fprintf(stderr, "ioctl() failed to read time from /dev/console, " + "errno = %s (%d).\n", + strerror(errno), errno); + exit(5); + } + close(con_fd); + } + + 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 */ +#else + /* This routine should never be invoked. It is here just to make the + program compile. + */ +#endif +} + + + +void +read_hardware_clock_rtc_ioctl(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via <tm> + argument. Use ioctls to "rtc" device /dev/rtc. +-----------------------------------------------------------------------------*/ +#if defined(_MC146818RTC_H) + int rc; /* Local return code */ + int rtc_fd; /* File descriptor of /dev/rtc */ + + rtc_fd = open("/dev/rtc",O_RDONLY); + if (rtc_fd == -1) { + fprintf(stderr, "open() of /dev/rtc failed, errno = %s (%d).\n", + strerror(errno), errno); + exit(5); + } else { + /* Read the RTC time/date */ + rc = ioctl(rtc_fd, RTC_RD_TIME, tm); + if (rc == -1) { + fprintf(stderr, "ioctl() to /dev/rtc to read the time failed, " + "errno = %s (%d).\n", strerror(errno), errno); + exit(5); + } + close(rtc_fd); + } + tm->tm_isdst = -1; /* don't know whether it's daylight */ +#else + /* This function should never be called. It exists just to make the + program compile. + */ +#endif +} + + + +void +read_hardware_clock_isa(struct tm *tm) { +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via <tm> argument. + Assume we have an ISA machine and read the clock directly with CPU I/O + instructions. +-----------------------------------------------------------------------------*/ + /* The loop here is just for integrity. In theory it should never run + more than once + */ + do { + tm->tm_sec = hclock_read_bcd(0); + tm->tm_min = hclock_read_bcd(2); + tm->tm_hour = hclock_read_bcd(4); + tm->tm_wday = hclock_read_bcd(6); + tm->tm_mday = hclock_read_bcd(7); + tm->tm_mon = hclock_read_bcd(8); + tm->tm_year = hclock_read_bcd(9); + if (hclock_read_bcd(50) == 0) { + /* I suppose Linux could run on an old machine that doesn't implement + the Byte 50 century value, and that if it does, that machine puts + zero in Byte 50. If so, this could could be useful, in that it + makes values 70-99 -> 1970-1999 and 00-69 -> 2000-2069. + */ + if (hclock_read_bcd(9) >= 70) tm->tm_year = hclock_read_bcd(9); + else tm->tm_year = hclock_read_bcd(9) + 100; + } else { + tm->tm_year = hclock_read_bcd(50) * 100 + hclock_read_bcd(9) - 1900; + /* Note: Byte 50 contains centuries since A.D. Byte 9 contains + years since beginning of century. tm_year contains years + since 1900. At least we _assume_ that's what tm_year + contains. It is documented only as "year", and it could + conceivably be years since the beginning of the current + century. If so, this code won't work after 1999. + */ + } + } while (tm->tm_sec != hclock_read_bcd (0)); + + tm->tm_mon--; /* DOS uses 1 base */ + tm->tm_wday -= 3; /* DOS uses 3 - 9 for week days */ + tm->tm_isdst = -1; /* don't know whether it's daylight */ +} + + + +void +read_hardware_clock(const enum clock_access_method method, struct tm *tm){ +/*---------------------------------------------------------------------------- + Read the hardware clock and return the current time via <tm> argument. + + Use the method indicated by <method> argument to access the hardware clock. +-----------------------------------------------------------------------------*/ + switch (method) { + case ISA: + read_hardware_clock_isa(tm); + break; + case RTC_IOCTL: + read_hardware_clock_rtc_ioctl(tm); + break; + case KD: + read_hardware_clock_kd(tm); + break; + default: + fprintf(stderr, + "Internal error: invalid value for clock access method.\n"); + exit(5); + } + if (debug) + printf ("Time read from Hardware Clock: %02d:%02d:%02d\n", + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + + + +void +set_hardware_clock_kd(const struct tm new_broken_time, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time <new_broken_time>. Use ioctls to + /dev/console on what we assume is an Alpha machine. +----------------------------------------------------------------------------*/ +#ifdef KDGHWCLK + int con_fd; /* File descriptor of /dev/console */ + struct hwclk_time t; + + con_fd = open("/dev/console", O_RDONLY); + if (con_fd < 0) { + fprintf(stderr, "Error opening /dev/console. Errno: %s (%d)\n", + strerror(errno), errno); + exit(1); + } else { + int rc; /* locally used return code */ + + 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 (testing) + printf("Not setting Hardware Clock because running in test mode.\n"); + else { + rc = ioctl(con_fd, kdshwclk_ioctl, &t ); + if (rc < 0) { + fprintf(stderr, "ioctl() to open /dev/console failed. " + "Errno: %s (%d)\n", + strerror(errno), errno); + exit(1); + } + } + close(con_fd); + } +#else + /* This function should never be invoked. It is here just to make the + program compile. + */ +#endif +} + + + +void +set_hardware_clock_rtc_ioctl(const struct tm new_broken_time, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the broken down time <new_broken_time>. + Use ioctls to "rtc" device /dev/rtc. +----------------------------------------------------------------------------*/ + int rc; + int rtc_fd; + + rtc_fd = open("/dev/rtc", O_RDONLY); + if (rtc_fd < 0) { + fprintf(stderr, "Unable to open /dev/rtc, open() errno = %s (%d)\n", + strerror(errno), errno); + exit(5); + } else { + rc = ioctl(rtc_fd, RTC_SET_TIME, &new_broken_time); + if (rc == -1) { + fprintf(stderr, "ioctl() (RTC_SET_TIME) to /dev/rtc to set time failed, " + "errno = %s (%d).\n", strerror(errno), errno); + exit(5); + } else { + if (debug) + fprintf(stderr, "ioctl(RTC_SET_TIME) was successful.\n"); + } + close(rtc_fd); + } +} + + + +void +set_hardware_clock_isa(const struct tm new_broken_time, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time (in broken down format) + new_broken_time. Use direct I/O instructions to what we assume is + an ISA Hardware Clock. +----------------------------------------------------------------------------*/ + unsigned char save_control, save_freq_select; + + if (testing) + printf("Not setting Hardware Clock because running in test mode.\n"); + else { +#ifdef __i386__ + __asm__ volatile ("cli"); +#endif + save_control = hclock_read(11); /* tell the clock it's being set */ + hclock_write(11, (save_control | 0x80)); + save_freq_select = hclock_read(10); /* stop and reset prescaler */ + hclock_write (10, (save_freq_select | 0x70)); + + hclock_write_bcd(0, new_broken_time.tm_sec); + hclock_write_bcd(2, new_broken_time.tm_min); + hclock_write_bcd(4, new_broken_time.tm_hour); + hclock_write_bcd(6, new_broken_time.tm_wday + 3); + hclock_write_bcd(7, new_broken_time.tm_mday); + hclock_write_bcd(8, new_broken_time.tm_mon + 1); + hclock_write_bcd(9, new_broken_time.tm_year%100); + hclock_write_bcd(50, (1900+new_broken_time.tm_year)/100); + + /* 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 + + Hence, they will also be done in this order here. + faith@cs.unc.edu, Thu Nov 9 08:26:37 1995 + */ + + hclock_write (11, save_control); + hclock_write (10, save_freq_select); +#ifdef __i386__ + __asm__ volatile ("sti"); +#endif + } +} + + +void +set_hardware_clock(const enum clock_access_method method, + const time_t newtime, + const bool universal, + const bool testing) { +/*---------------------------------------------------------------------------- + Set the Hardware Clock to the time <newtime>, in local time zone or UTC, + according to <universal>. + + Use the method indicated by the <method> argument. +----------------------------------------------------------------------------*/ + + 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); + + switch (method) { + case ISA: + set_hardware_clock_isa(new_broken_time, testing); + break; + case RTC_IOCTL: + set_hardware_clock_rtc_ioctl(new_broken_time, testing); + break; + case KD: + set_hardware_clock_kd(new_broken_time, testing); + break; + default: + fprintf(stderr, + "Internal error: invalid value for clock access method.\n"); + exit(5); + } +} + + + +void +set_hardware_clock_exact(const time_t settime, + const struct timeval ref_time, + const enum clock_access_method clock_access, + 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(clock_access, newtime, universal, testing); +} + + + +void +display_time(const time_t systime, const float sync_duration) { +/*---------------------------------------------------------------------------- + Put the time "systime" on standard output in display format. + + Include in the output the adjustment "sync_duration". +-----------------------------------------------------------------------------*/ + 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)); +} + + + +int +interpret_date_string(const char *date_opt, const time_t *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, "*newtime", 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. + Otherwise, return code is 0 and *newtime 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) { + fprintf(stderr, "Unable to run 'date' program in /bin/sh shell. " + "popen() failed with errno=%d:%s\n", errno, strerror(errno)); + 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 " MYNAME " returned " + "unexpected results.\n" + "The command was:\n %s\nThe response was:\n %s\n", + date_command, date_resp); + retcode = 8; + } else { + rc = sscanf(date_resp + sizeof(magic)-1, "%d", (int *) time_p); + if (rc < 1) { + fprintf(stderr, "The date command issued by " MYNAME " 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", + date_command, date_resp); + retcode = 6; + } else { + retcode = 0; + if (debug) + printf("date string %s equates to %d seconds since 1969.\n", + date_opt, (int) *time_p); + } + } + fclose(date_child_fp); + } + } + return(retcode); +} + + + +int +set_system_clock(const time_t newtime, const int testing) { + + struct timeval tv; + int retcode; /* our eventual return code */ + int rc; /* local return code */ + + tv.tv_sec = newtime; + tv.tv_usec = 0; + + if (debug) { + printf( "Calling settimeofday:\n" ); + /* Note: In Linux 1.2, tv_sec and tv_usec were long int */ + printf( "\ttv.tv_sec = %d, tv.tv_usec = %d\n", + tv.tv_sec, tv.tv_usec ); + } + if (testing) { + printf("Not setting system clock because running in test mode.\n"); + retcode = 0; + } else { + rc = settimeofday(&tv, NULL); + if (rc != 0) { + if (errno == EPERM) + fprintf(stderr, "Must be superuser to set system clock.\n"); + else + fprintf(stderr, + "settimeofday() failed, errno=%d:%s\n", + errno, strerror(errno)); + retcode = 1; + } else retcode = 0; + } + return(retcode); +} + + +void +adjust_drift_factor(struct adjtime *adjtime_p, + const time_t nowtime, + const time_t hclocktime ) { +/*--------------------------------------------------------------------------- + Update the drift factor in <*adjtime_p> to reflect the fact that the + Hardware Clock was calibrated to <nowtime> and before that was set + to <hclocktime>. + + We assume that the user has been doing regular drift adjustments + using the drift factor in the adjtime file, so if <nowtime> and + <clocktime> 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. + +----------------------------------------------------------------------------*/ + if ((hclocktime - adjtime_p->last_calib_time) >= 24 * 60 * 60) { + 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; + } else if (debug) + printf("Not adjusting drift factor because it has been less than a " + "day since the last calibration.\n"); + + adjtime_p->last_calib_time = nowtime; + + adjtime_p->last_adj_time = nowtime; + + adjtime_p->not_adjusted = 0; + + adjtime_p->dirty = TRUE; +} + + + +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); + } +} + + + +void +save_adjtime(const struct adjtime adjtime, const bool testing) { +/*----------------------------------------------------------------------------- + Write the contents of the <adjtime> structure to its disk file. + + But if the contents are clean (unchanged since read from disk), don't + bother. +-----------------------------------------------------------------------------*/ + FILE *adjfile; + char newfile[162]; /* Stuff to write to disk file */ + + int rc; /* locally used: return code from a function */ + + if (adjtime.dirty) { + snprintf(newfile, sizeof(newfile), "%f %d %f\n%d\n", + adjtime.drift_factor, + adjtime.last_adj_time, + adjtime.not_adjusted, + adjtime.last_calib_time ); + + 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 { + adjfile = fopen(ADJPATH, "w"); + if (adjfile == NULL) { + const int fopen_errno = errno; + printf("Could not open file with the clock adjustment parameters " + "in it (%s) for output.\n" + "fopen() returned errno %d: %s.\n" + "Drift adjustment parameters not updated.\n", + ADJPATH, fopen_errno, strerror(errno)); + } else { + rc = fprintf(adjfile, newfile); + if (rc < 0) { + const int fprintf_errno = errno; + printf("Could not update file with the clock adjustment parameters " + "(%s) in it.\n" + "fprintf() returned errno %d: %s.\n" + "Drift adjustment parameters not updated.\n", + ADJPATH, fprintf_errno, strerror(errno)); + } + rc = fclose(adjfile); + if (rc < 0) { + const int fclose_errno = errno; + printf("Could not update file with the clock adjustment parameters " + "(%s) in it.\n" + "fclose() returned errno %d: %s.\n" + "Drift adjustment parameters not updated.\n", + ADJPATH, fclose_errno, strerror(errno)); + } + } + } + } +} + + + +void +do_adjustment(struct adjtime *adjtime_p, + const time_t hclocktime, const struct timeval read_time, + const enum clock_access_method clock_access, + 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. + + arguments <factor> and <last_time> are current values from the adjtime + file. + + <hclocktime> is the current time set in the Hardware Clock. + + <read_time> is the current system time (to be precise, it is the system + time at the time <hclocktime> was read, which due to computational delay + could be a short time ago). + + <universal>: the Hardware Clock is kept in UTC. + + <testing>: 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. + +----------------------------------------------------------------------------*/ + 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 + <adjustment> 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), + clock_access, 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"); +} + + + +void +determine_clock_access_method(const bool user_requests_ISA, + enum clock_access_method *clock_access_p) { +/*---------------------------------------------------------------------------- + Figure out how we're going to access the hardware clock, by seeing + what facilities are available, looking at invocation options, and + using compile-time constants. + + <user_requests_ISA> means the user explicitly asked for the ISA method. +-----------------------------------------------------------------------------*/ + bool rtc_works; + /* The /dev/rtc method is available and seems to work on this machine */ + + if (got_rtc) { + int rtc_fd = open("/dev/rtc", O_RDONLY); + if (rtc_fd > 0) { + rtc_works = TRUE; + close(rtc_fd); + } else { + rtc_works = FALSE; + if (debug) + printf("Open of /dev/rtc failed, errno = %s (%d). " + "falling back to more primitive clock access method.\n", + strerror(errno), errno); + } + } else rtc_works = TRUE; + + if (user_requests_ISA) *clock_access_p = ISA; + else if (rtc_works) *clock_access_p = RTC_IOCTL; + else if (got_kdghwclk) { + int con_fd; + struct hwclk_time t; + + con_fd = open("/dev/console", O_RDONLY); + if (con_fd >= 0) { + if (ioctl( con_fd, kdghwclk_ioctl, &t ) >= 0) + *clock_access_p = KD; + else { + if (errno == EINVAL) { + /* KDGHWCLK not implemented in this kernel... */ + *clock_access_p = ISA; + } else { + *clock_access_p = KD; + fprintf(stderr, + "KDGHWCLK ioctl failed, errno = %s (%d).\n", + strerror(errno), errno); + } + } + } else { + *clock_access_p = KD; + fprintf(stderr, + "Can't open /dev/console. open() errno = %s (%d).\n", + strerror(errno), errno); + } + close(con_fd); + } else { + *clock_access_p = ISA; + } + if (debug) { + switch (*clock_access_p) { + case ISA: printf("Using direct I/O instructions to ISA clock.\n"); break; + case KD: printf("Using /dev/console interface to Alpha clock.\n"); break; + case RTC_IOCTL: printf("Using /dev/rtc interface to clock.\n"); break; + default: + printf("determine_clock_access_method() returned invalid value: %d.\n", + *clock_access_p); + } + } +} + + + +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 enum clock_access_method clock_access, + const bool universal, const bool testing, + int *retcode + ) { +/*--------------------------------------------------------------------------- + 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. */ + struct tm tm; + time_t hclocktime; + /* The time the hardware clock had just after we synchronized to its + next clock tick when we started up. + */ + struct timeval read_time; + /* The time at which we read the Hardware Clock */ + + int rc; /* local return code */ + bool no_auth; /* User lacks necessary authorization to access the clock */ + + if (clock_access == ISA) { + rc = iopl(3); + if (rc != 0) { + fprintf(stderr, MYNAME " is unable to get I/O port access. " + "I.e. iopl(3) returned nonzero return code %d.\n" + "This is often because the program isn't running " + "with superuser privilege, which it needs.\n", + rc); + no_auth = TRUE; + } else no_auth = FALSE; + } else no_auth = FALSE; + + if (no_auth) *retcode = 1; + else { + if (adjust || set) + 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 = 2; + else { + synchronize_to_clock_tick(clock_access); /* this takes up to 1 second */ + + /* Get current time from Hardware Clock, in case we need it */ + gettimeofday(&read_time, NULL); + read_hardware_clock(clock_access, &tm); + hclocktime = mktime_tz(tm, universal); + + if (show) { + display_time(hclocktime, time_diff(read_time, startup_time)); + *retcode = 0; + } else if (set) { + set_hardware_clock_exact(set_time, startup_time, + clock_access, universal, testing); + adjust_drift_factor(&adjtime, set_time, hclocktime); + *retcode = 0; + } else if (adjust) { + do_adjustment(&adjtime, hclocktime, read_time, clock_access, + universal, testing); + *retcode = 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, + clock_access, universal, testing); + *retcode = 0; + } else if (hctosys) { + rc = set_system_clock(hclocktime, testing); + if (rc != 0) { + printf("Unable to set system clock.\n"); + *retcode = 1; + } else *retcode = 0; + } + save_adjtime(adjtime, testing); + } + } +} + + + +int +main(int argc, char **argv, char **envp) { +/*---------------------------------------------------------------------------- + MAIN +-----------------------------------------------------------------------------*/ + 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 */ + + enum clock_access_method clock_access; + /* The method that we determine is best for accessing Hardware Clock + on this system. + */ + + 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 <show>, which + may be modified after parsing is complete to effect an implied option. + */ + bool show, set, systohc, hctosys, adjust, version; + bool universal, testing, directisa; + char *date_opt; + + const optStruct option_def[] = { + { '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 }, + { 'a', (char *) "adjust", OPT_FLAG, &adjust, 0 }, + { 'v', (char *) "version", OPT_FLAG, &version, 0 }, + { 0, (char *) "date", OPT_STRING, &date_opt, 0 }, + { 'u', (char *) "utc", OPT_FLAG, &universal, 0 }, + { 0, (char *) "directisa", OPT_FLAG, &directisa, 0 }, + { 0, (char *) "test", OPT_FLAG, &testing, 0 }, + { 'D', (char *) "debug", OPT_FLAG, &debug, 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 */ + + /* set option defaults */ + show = set = systohc = hctosys = adjust = version = universal = + directisa = 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, universal, version, testing, + debug, set, date_opt + */ + + if (argc_parse - 1 > 0) { + fprintf(stderr, MYNAME " takes no non-option arguments. " + "You supplied %d.\n", + argc_parse - 1); + exit(100); + } + + if (show + set + systohc + hctosys + adjust + version > 1) { + fprintf(stderr, "You have specified multiple function options.\n" + "You can only perform one function at a time.\n"); + exit(100); + } + + 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 | version)) + show = 1; /* default to show */ + + if (set || hctosys || systohc || adjust) { + /* program is designed to run setuid, be secure! */ + + if (getuid() != 0) { + fprintf(stderr, + "Sorry, only superuser can change the Hardware Clock.\n"); + permitted = FALSE; + } else permitted = TRUE; + } else permitted = TRUE; + + if (!permitted) retcode = 2; + else { + retcode = 0; + if (version) { + printf(MYNAME " " VERSION "/%s\n",util_linux_version); + } else { + determine_clock_access_method(directisa, &clock_access); + + manipulate_clock(show, adjust, set, set_time, hctosys, systohc, + startup_time, clock_access, universal, testing, &rc); + } + } + exit(retcode); +} + + +/**************************************************************************** + + History of this program: + + 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 <schwab@LS5.informatik.uni-dortmund.de>. + + 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. + + + Bryan Henderson based hwclock on the program "clock", in September + 1996. While remaining mostly backward compatible with clock, + hwclock added the following: + + - You can set the hardware clock without also modifying the Linux + 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. (This + is the drift rate that is used with the --adjust function to + automatically adjust the clock periodically to compensate for drift). + + - More mnemonic GNU-style command line options. + + - Comments describing how the clock and program work to improve + maintainability. + + - Removed the old dead I/O code that worked without the inb/outb + instructions and without the asm/io.h definitions. + + The first version of hwclock was Version 2. + + Here is the history section from the "clock" program at the time it was + used as a basis for hwclock: + + V1.0 + + + V1.0 by Charles Hedrick, hedrick@cs.rutgers.edu, April 1992. + + ******************** + 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. + + ***** + 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. */ + + diff --git a/sys-utils/ipcrm.c b/sys-utils/ipcrm.c index 7273b341a..eceb0b71c 100644 --- a/sys-utils/ipcrm.c +++ b/sys-utils/ipcrm.c @@ -4,6 +4,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <errno.h> #include <sys/shm.h> #include <sys/msg.h> diff --git a/sys-utils/ipcs.c b/sys-utils/ipcs.c index 12df2261a..9505aff55 100644 --- a/sys-utils/ipcs.c +++ b/sys-utils/ipcs.c @@ -1,9 +1,19 @@ /* Original author unknown, but may be "krishna balasub@cis.ohio-state.edu" Modified Sat Oct 9 10:55:28 1993 for 0.99.13 */ -/* Patches from Mike Jagdis (jaggy@purplet.demon.co.uk) applied Wed Feb 8 -12:12:21 1995 by faith@cs.unc.edu to print numeric uids if no passwd file -entry. */ +/* + + Patches from Mike Jagdis (jaggy@purplet.demon.co.uk) applied Wed Feb + 8 12:12:21 1995 by faith@cs.unc.edu to print numeric uids if no + passwd file entry. + + Patch from arnolds@ifns.de (Heinz-Ado Arnolds) applied Mon Jul 1 + 19:30:41 1996 by janl@math.uio.no to add code missing in case PID: + clauses. + + Patched to display the key field -- hy@picksys.com 12/18/96 + +*/ #include <stdio.h> #include <stdlib.h> @@ -18,6 +28,11 @@ entry. */ #include <sys/msg.h> #include <sys/shm.h> +#if defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 +#define KEY __key +#else +#define KEY key +#endif #define LIMITS 1 #define STATUS 2 @@ -196,10 +211,10 @@ void do_shm (char format) case STATUS: printf ("------ Shared Memory Status --------\n"); printf ("segments allocated %d\n", shm_info.used_ids); - printf ("pages allocated %d\n", shm_info.shm_tot); - printf ("pages resident %d\n", shm_info.shm_rss); - printf ("pages swapped %d\n", shm_info.shm_swp); - printf ("Swap performance: %d attempts\t %d successes\n", + printf ("pages allocated %ld\n", shm_info.shm_tot); + printf ("pages resident %ld\n", shm_info.shm_rss); + printf ("pages swapped %ld\n", shm_info.shm_swp); + printf ("Swap performance: %ld attempts\t %ld successes\n", shm_info.swap_attempts, shm_info.swap_successes); return; @@ -222,8 +237,8 @@ void do_shm (char format) default: printf ("------ Shared Memory Segments --------\n"); - printf ("%-10s%-10s%-10s%-10s%-10s%-12s\n", "shmid","owner", - "perms","bytes","nattch","status"); + printf ("%-11s%-10s%-10s%-10s%-10s%-10s%-12s\n", "key","shmid", + "owner","perms","bytes","nattch","status"); break; } @@ -257,6 +272,7 @@ void do_shm (char format) break; default: + printf( "0x%08x ",ipcp->KEY ); if (pw) printf ("%-10d%-10.10s", shmid, pw->pw_name); else @@ -325,8 +341,8 @@ void do_sem (char format) default: printf ("------ Semaphore Arrays --------\n"); - printf ("%-10s%-10s%-10s%-10s%-12s\n", - "semid","owner","perms","nsems","status"); + printf ("%-10s%-10s%-10s%-10s%-10s%-12s\n", + "key","semid","owner","perms","nsems","status"); break; } @@ -354,6 +370,7 @@ void do_sem (char format) break; default: + printf( "0x%08x ",ipcp->KEY ); if (pw) printf ("%-10d%-10.9s", semid, pw->pw_name); else @@ -412,12 +429,14 @@ void do_msg (char format) break; case PID: + printf ("------ Message Queues PIDs --------\n"); + printf ("%-10s%-10s%-10s%-10s\n","msqid","owner","lspid","lrpid"); break; default: printf ("------ Message Queues --------\n"); - printf ("%-10s%-10s%-10s%-12s%-12s\n", "msqid","owner", - "perms", "used-bytes", "messages"); + printf ("%-10s%-10s%-10s%-10s%-12s%-12s\n", "key","msqid", + "owner", "perms", "used-bytes", "messages"); break; } @@ -442,9 +461,16 @@ void do_msg (char format) msgque.msg_ctime ? ctime(&msgque.msg_ctime) + 4 : "Not set"); break; case PID: - break; - + if (pw) + printf ("%-8d%-10.10s", msqid, pw->pw_name); + else + printf ("%-8d%-10d", msqid, ipcp->uid); + printf (" %5d %5d\n", + msgque.msg_lspid, msgque.msg_lrpid); + break; + default: + printf( "0x%08x ",ipcp->KEY ); if (pw) printf ("%-10d%-10.10s", msqid, pw->pw_name); else diff --git a/sys-utils/kbdrate.c b/sys-utils/kbdrate.c index d8632a204..e61fb8906 100644 --- a/sys-utils/kbdrate.c +++ b/sys-utils/kbdrate.c @@ -23,31 +23,55 @@ kbdrate -r 0 -d 0 set rate to 2.0 cps and delay to 250 mS I find it useful to put kbdrate in my /etc/rc file so that the keyboard rate is set to something that I find comfortable at boot time. This sure beats rebuilding the kernel! -*/ -/********************** CUT HERE *****************************/ -/* kbdrate.c -- Set keyboard typematic rate (and delay) - * Created: Thu Apr 23 12:24:30 1992 - * Revised: Wed Jun 22 22:40:46 1994 by faith@cs.unc.edu - * Author: Rickard E. Faith, faith@cs.unc.edu - * Copyright 1992 Rickard E. Faith. Distributed under the GPL. - * This program comes with ABSOLUTELY NO WARRANTY. - * Usage: kbdrate [-r rate] [-d delay] [-s] - * Rate can range from 2.0 to 30.0 (units are characters per second) - * Delay can range from 250 to 1000 (units are milliseconds) - * -s suppressed message - * Compiles under gcc 2.1 for Linux (tested with the pre-0.96 kernel) - * - * Wed Jun 22 21:35:43 1994, faith@cs.unc.edu: - * Changed valid_rates per suggestion by Andries.Brouwer@cwi.nl. - * Wed Jun 22 22:18:29 1994, faith@cs.unc.edu: - * Added patch for AUSTIN notebooks from John Bowman - * (bowman@hagar.ph.utexas.edu) - */ + + kbdrate.c -- Set keyboard typematic rate (and delay) + Created: Thu Apr 23 12:24:30 1992 + Author: Rickard E. Faith, faith@cs.unc.edu + + Copyright 1992 Rickard E. Faith. Distributed under the GPL. + This program comes with ABSOLUTELY NO WARRANTY. + Usage: kbdrate [-r rate] [-d delay] [-s] + Rate can range from 2.0 to 30.0 (units are characters per second) + Delay can range from 250 to 1000 (units are milliseconds) + -s suppressed message + Compiles under gcc 2.1 for Linux (tested with the pre-0.96 kernel) + + Wed Jun 22 21:35:43 1994, faith@cs.unc.edu: + Changed valid_rates per suggestion by Andries.Brouwer@cwi.nl. + Wed Jun 22 22:18:29 1994, faith@cs.unc.edu: + Added patch for AUSTIN notebooks from John Bowman + (bowman@hagar.ph.utexas.edu) + + Linux/68k modifications by Roman Hodek + (Roman.Hodek@informatik.uni-erlangen.de): + + Reading/writing the Intel I/O ports via /dev/port is not the + English way... Such hardware dependant stuff can never work on + other architectures. + + Linux/68k has an new ioctl for setting the keyboard repeat rate + and delay. Both values are counted in msecs, the kernel will do + any rounding to values possible with the underlying hardware. + + kbdrate now first tries if the KDKBDREP ioctl is available. If it + is, it is used, else the old method is applied. + +*/ #include <stdio.h> +#include <unistd.h> #include <stdlib.h> #include <sys/file.h> +#include <sys/ioctl.h> +#include <linux/version.h> +#if LINUX_VERSION_CODE >= 131072 +/* Kd.h is not available with all linux versions. 131072 is equivalent + to linux 2.0.0 */ +#include <linux/kd.h> +#endif + +#define VERSION "1.3" static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150, 133, 120, 109, 100, 92, 86, 80, 75, 67, @@ -58,7 +82,12 @@ static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150, static int valid_delays[] = { 250, 500, 750, 1000 }; #define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int )) -void main( int argc, char **argv ) +#ifdef KDKBDREP +static int ioctl_possible = 0; +struct kbd_repeat kbdrep_s; +#endif + +int main( int argc, char **argv ) { double rate = 10.9; /* Default rate */ int delay = 250; /* Default delay */ @@ -72,7 +101,7 @@ void main( int argc, char **argv ) extern char *optarg; extern int optind; - while ( (c = getopt( argc, argv, "r:d:s" )) != EOF ) + while ( (c = getopt( argc, argv, "r:d:sv" )) != EOF ) switch (c) { case 'r': rate = atof( optarg ); @@ -83,48 +112,89 @@ void main( int argc, char **argv ) case 's': silent = 1; break; + case 'v': + fprintf( stderr, "util-linux kbdrate " VERSION "\n"); + exit(0); } - for (i = 0; i < RATE_COUNT; i++) - if (rate * 10 >= valid_rates[i]) { - value &= 0x60; - value |= i; - break; - } - - for (i = 0; i < DELAY_COUNT; i++) - if (delay <= valid_delays[i]) { - value &= 0x1f; - value |= i << 5; - break; - } - - if ( (fd = open( "/dev/port", O_RDWR )) < 0) { - perror( "Cannot open /dev/port" ); - exit( 1 ); +#ifdef KDKBDREP + kbdrep_s.rate = -1; /* don't change, just test */ + kbdrep_s.delay = -1; + if (ioctl( 0, KDKBDREP, &kbdrep_s )) { + if (errno == EINVAL) + ioctl_possible = 0; + else { + perror( "ioctl(KDKBDREP)" ); + exit( 1 ); + } + } else ioctl_possible = 1; + + if (ioctl_possible) { + kbdrep_s.rate = 1000.0 / rate; /* convert cps to msec */ + if (kbdrep_s.rate < 1) kbdrep_s.rate = 1; + kbdrep_s.delay = delay; + if (kbdrep_s.delay < 1) kbdrep_s.delay = 1; + + if (ioctl( 0, KDKBDREP, &kbdrep_s )) { + perror( "ioctl(KDKBDREP)" ); + exit( 1 ); + } + + if (!silent) + printf( "Typematic Rate set to %.1f cps (delay = %d mS)\n", + 1000.0 / (double)kbdrep_s.rate, kbdrep_s.delay ); + } else { +#endif + + /* The ioport way */ + + for (i = 0; i < RATE_COUNT; i++) + if (rate * 10 >= valid_rates[i]) { + value &= 0x60; + value |= i; + break; + } + + + for (i = 0; i < DELAY_COUNT; i++) + if (delay <= valid_delays[i]) { + value &= 0x1f; + value |= i << 5; + break; + } + + if ( (fd = open( "/dev/port", O_RDWR )) < 0) { + perror( "Cannot open /dev/port" ); + exit( 1 ); + } + + do { + lseek( fd, 0x64, 0 ); + read( fd, &data, 1 ); + } while ((data & 2) == 2 ); /* wait */ + + lseek( fd, 0x60, 0 ); + data = 0xf3; /* set typematic rate */ + write( fd, &data, 1 ); + + do { + lseek( fd, 0x64, 0 ); + read( fd, &data, 1 ); + } while ((data & 2) == 2 ); /* wait */ + + lseek( fd, 0x60, 0 ); + sleep( 1 ); + write( fd, &value, 1 ); + + close( fd ); + + if (!silent) printf( "Typematic Rate set to %.1f cps (delay = %d mS)\n", + valid_rates[value & 0x1f] / 10.0, + valid_delays[ (value & 0x60) >> 5 ] ); + +#ifdef KDKBREP } +#endif - do { - lseek( fd, 0x64, 0 ); - read( fd, &data, 1 ); - } while ((data & 2) == 2 ); /* wait */ - - lseek( fd, 0x60, 0 ); - data = 0xf3; /* set typematic rate */ - write( fd, &data, 1 ); - - do { - lseek( fd, 0x64, 0 ); - read( fd, &data, 1 ); - } while ((data & 2) == 2 ); /* wait */ - - lseek( fd, 0x60, 0 ); - sleep( 1 ); - write( fd, &value, 1 ); - - close( fd ); - - if (!silent) printf( "Typematic Rate set to %.1f cps (delay = %d mS)\n", - valid_rates[value & 0x1f] / 10.0, - valid_delays[ (value & 0x60) >> 5 ] ); + return 0; } diff --git a/sys-utils/rdev.c b/sys-utils/rdev.c index cb3a730ee..77e1a58f5 100644 --- a/sys-utils/rdev.c +++ b/sys-utils/rdev.c @@ -54,8 +54,11 @@ Wed Jun 22 21:12:29 1994: Applied patches from Dave */ +#include <stdio.h> + /* rdev.c - query/set root device. */ +void usage() { @@ -108,7 +111,7 @@ static char *find_dev(int number) if (!number) return "Boot device"; if ((dp = opendir("/dev")) == NULL) die("opendir /dev"); strcpy(name,"/dev/"); - while (dir = readdir(dp)) { + while ((dir = readdir(dp)) != NULL) { strcpy(name+5,dir->d_name); if (stat(name,&s) < 0) die(name); if ((s.st_mode & S_IFMT) == S_IFBLK && s.st_rdev == number) return name; @@ -128,11 +131,12 @@ char *desc[6] = { "Root device", "Video mode", "Ramsize", "Swap device", int main(int argc,char **argv) { int image,offset,dev_nr, i, newoffset=-1; - char *device, cmd = 0, *ptr, tmp[40]; + char *device, *ptr; struct stat s; + int cmd = 0; device = NULL; - if (ptr = strrchr(argv[0],'/')) + if ((ptr = strrchr(argv[0],'/')) != NULL) ptr++; else ptr = argv[0]; diff --git a/sys-utils/readprofile.1 b/sys-utils/readprofile.1 index fd5d7196d..a72113c85 100644 --- a/sys-utils/readprofile.1 +++ b/sys-utils/readprofile.1 @@ -1,4 +1,4 @@ -.TH READPROFILE 1 "January 1995" +.TH READPROFILE 1 "May 1996" .UC 4 .SH NAME readprofile - a tool to read kernel profiling information @@ -9,7 +9,7 @@ readprofile - a tool to read kernel profiling information ] .SH VERSION -This manpage documents version 1.1 of the program. +This manpage documents version 2.0 of the program. .SH DESCRIPTION @@ -33,12 +33,6 @@ Available command line options are the following: .RB -m " mapfile" Specify a mapfile, which by default is .B /usr/src/linux/System.map. -To ease use of -.B readprofile -with kernels in the 1.1.7x series, if the default file can't be opened, -the alternate file -.B /usr/src/linux/zSystem.map -is tried. You should specify the map file on cmdline if your current kernel isn't the last one you compiled. If the name of the map file ends with `.gz' it is decompressed on the fly. @@ -50,10 +44,10 @@ Specify a different profiling buffer, which by default is Using a different pro-file is useful if you want to `freeze' the kernel profiling at some time and read it later. The .B /proc/profile -file can be copied using `cat' or `cp'. If the name of the pro-file -ends by `.gz' it is decompressed on the fly. The pro-file is such that -.B gzip -shrinks it by 50-100 times. +file can be copied using `cat' or `cp'. There is no more support for +compressed profile buffers, like in +.B readprofile-1.1, +because the program needs to know the size of the buffer in advance. .TP .B -i @@ -61,7 +55,8 @@ Info. This makes .B readprofile only print the profiling step used by the kernel. The profiling step is the resolution of the profiling buffer, and -is chosen during kernel configuration (through `make config'). +is chosen during kernel configuration (through `make config'), +or in the kernel's command line. If the .B -t (terse) switch is used together with @@ -77,13 +72,10 @@ ticks are not printed. .B -r Reset the profiling buffer. This can only be invoked by root, because .B /proc/profile -is readable by everybody but writable only by the superuser. - -.TP -.B -t -Terse. This causes the output to be unfilled. It is the format used in the -first release of -.B readprofile. +is readable by everybody but writable only by the superuser. However, +you can make +.B readprofile +setuid 0, in order to reset the buffer without gaining privileges. .TP .B -v @@ -119,9 +111,9 @@ Look at all the kernel information, with ram addresses" readprofile -av | less .fi -Browse a gzipped `freezed' profile buffer for a non current kernel: +Browse a `freezed' profile buffer for a non current kernel: .nf - readprofile -p ~/profile.freeze.gz -m /zImage.map + readprofile -p ~/profile.freeze -m /zImage.map.gz .fi @@ -129,31 +121,30 @@ Browse a gzipped `freezed' profile buffer for a non current kernel: .LP .B readprofile -needs a kernel version 1.1.73 or newer, because +only works with an 1.3.x or newer kernel, +because .B /proc/profile -is absent -in older versions. +changed in the step from 1.2 to 1.3 .LP -To enable profiling, the kernel must be reconfigured, recompiled, and -rebooted. No profiling module is available, and it wouldn't be easy to -build. So this can be construed as a feature. +This program only works with ELF kernels. The change for a.out kernels +is trivial, and left as an exercise to the a.out user. + +.LP +To enable profiling, the kernel must be rebooted, because no profiling module +is available, and it wouldn't be easy to build. To enable profiling, +you can specify "profile=2" (or another number) on the kernel commandline. +The number you specify is the two-exponent used as profiling step. .LP Profiling is disabled when interrupts are inhibited. This means that many profiling ticks happen when interrupts are re-enabled. Watch out for misleading information. -.SH AUTHOR - -Readprofile and /proc/profile are by Alessandro Rubini (rubini@ipvvis.unipv.it) - .SH FILES .nf /proc/profile A binary snapshot of the profiling buffer. /usr/src/linux/System.map The symbol table for the kernel. -/usr/src/linux/zSystem.map Old name for the symbol table. - /usr/src/linux/* The program being profiled :-) .fi diff --git a/sys-utils/readprofile.c b/sys-utils/readprofile.c index 58234f6af..4c52cf1fa 100644 --- a/sys-utils/readprofile.c +++ b/sys-utils/readprofile.c @@ -1,7 +1,7 @@ /* * readprofile.c - used to read /proc/profile * - * Copyright (C) 1994 Alessandro Rubini + * Copyright (C) 1994,1996 Alessandro Rubini (rubini@ipvvis.unipv.it) * * 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 @@ -18,20 +18,23 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <errno.h> #include <stdio.h> #include <stdlib.h> -#include <unistd.h> /* getopt() */ +#include <unistd.h> #include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> -#define RELEASE "1.1, Jan 1995" +#define RELEASE "2.0, May 1996" #define S_LEN 128 static char *prgname; -/* These are the defaults and they cna be changed */ -static char defaultmap1[]="/usr/src/linux/System.map"; -static char defaultmap2[]="/usr/src/linux/zSystem.map"; +/* These are the defaults */ +static char defaultmap[]="/usr/src/linux/System.map"; static char defaultpro[]="/proc/profile"; static char optstring[]="m:p:itvarV"; @@ -42,12 +45,11 @@ void usage() "\t -m <mapfile> (default = \"%s\")\n" "\t -p <pro-file> (default = \"%s\")\n" "\t -i print only info about the sampling step\n" - "\t -t print terse data\n" "\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" - ,prgname,prgname,defaultmap1,defaultpro); + ,prgname,prgname,defaultmap,defaultpro); exit(1); } @@ -56,11 +58,11 @@ FILE *myopen(char *name, char *mode, int *flag) static char cmdline[S_LEN]; if (!strcmp(name+strlen(name)-3,".gz")) - { - *flag=1; - sprintf(cmdline,"zcat %s", name); - return popen(cmdline,mode); - } + { + *flag=1; + sprintf(cmdline,"zcat %s", name); + return popen(cmdline,mode); + } *flag=0; return fopen(name,mode); } @@ -69,24 +71,24 @@ int main (int argc, char **argv) { FILE *pro; FILE *map; -unsigned long l; -char *proFile; -char *mapFile; -int add, step; -int fn_add[2]; /* current and next address */ -char fn_name[2][S_LEN]; /* current and next name */ +int proFd; +char *mapFile, *proFile; +unsigned int len, add0=0, step, index=0; +unsigned int *buf, total, fn_len; +unsigned int fn_add, next_add; /* current and next address */ +char fn_name[S_LEN], next_name[S_LEN]; /* current and next name */ char mode[8]; -int i,c,current=0; -int optAll=0, optInfo=0, optReset=0, optTerse=0, optVerbose=0; +int c; +int optAll=0, optInfo=0, optReset=0, optVerbose=0; char mapline[S_LEN]; int maplineno=1; -int popenMap, popenPro; /* flags to tell if popen() is used */ +int popenMap; /* flag to tell if popen() has been used */ #define next (current^1) prgname=argv[0]; proFile=defaultpro; - mapFile=defaultmap1; + mapFile=defaultmap; while ((c=getopt(argc,argv,optstring))!=-1) { @@ -96,128 +98,121 @@ int popenMap, popenPro; /* flags to tell if popen() is used */ case 'p': proFile=optarg; break; case 'a': optAll++; break; case 'i': optInfo++; break; - case 't': optTerse++; break; - case 'r': optReset++; break; - case 'v': optVerbose++; break; - case 'V': printf("%s Version %s\n",prgname,RELEASE); exit(0); + case 'r': optReset++; break; + case 'v': optVerbose++; break; + case 'V': printf("%s Version %s\n",prgname,RELEASE); exit(0); default: usage(); } } if (optReset) - { - pro=fopen(defaultpro,"w"); - if (!pro) - {perror(proFile); exit(1);} - fprintf(pro,"anything\n"); - fclose(pro); + { + /* try to become root, just in case */ + setuid(0); + pro=fopen(defaultpro,"w"); + if (!pro) + {perror(proFile); exit(1);} + fprintf(pro,"anything\n"); + fclose(pro); exit(0); - } - - if (!(pro=myopen(proFile,"r",&popenPro))) - {fprintf(stderr,"%s: ",prgname);perror(proFile);exit(1);} + } /* - * In opening the map file, try both the default names, but exit - * at first fail if the filename was specified on cmdline + * Use an fd for the profiling buffer, to skip stdio overhead */ - for (map=NULL; map==NULL; ) - { - if (!(map=myopen(mapFile,"r",&popenMap))) - { - fprintf(stderr,"%s: ",prgname);perror(mapFile); - if (mapFile!=defaultmap1) exit(1); - mapFile=defaultmap2; - } - } - -#define NEXT_WORD(where) \ - (fread((void *)where, 1,sizeof(unsigned long),pro), feof(pro) ? 0 : 1) + if ( ((proFd=open(proFile,O_RDONLY)) < 0) + || ((len=lseek(proFd,0,SEEK_END)) < 0) + || (lseek(proFd,0,SEEK_SET)<0) ) + { + fprintf(stderr,"%s: %s: %s\n",prgname,proFile,strerror(errno)); + exit(1); + } - /* - * Init the 'next' field - */ - if (!fgets(mapline,S_LEN,map)) - { - fprintf(stderr,"%s: %s(%i): premature EOF\n",prgname,mapFile,maplineno); - exit(1); - } - if (sscanf(mapline,"%x %s %s",&(fn_add[next]),mode,fn_name[next])!=3) - { - fprintf(stderr,"%s: %s(%i): wrong map line\n",prgname,mapFile, maplineno); - exit(1); - } - - add=0; - - if (!NEXT_WORD(&step)) - { - fprintf(stderr,"%s: %s: premature EOF\n",prgname,proFile); + if ( !(buf=malloc(len)) ) + { fprintf(stderr,"%s: malloc(): %s\n",prgname, strerror(errno)); exit(1); } + + if (read(proFd,buf,len) != len) + { + fprintf(stderr,"%s: %s: %s\n",prgname,proFile,strerror(errno)); exit(1); } + close(proFd); + step=buf[0]; if (optInfo) { - printf(optTerse ? "%i\n" : "The sampling step in the kernel is %i bytes\n", - step); + printf("Sampling_step: %i\n",step); exit(0); } - /* - * The main loop is build around the mapfile - */ - - while(current^=1, maplineno++, fgets(mapline,S_LEN,map)) - { - int fn_len; - int count=0; + total=0; + if (!(map=myopen(mapFile,"r",&popenMap))) + {fprintf(stderr,"%s: ",prgname);perror(mapFile);exit(1);} - if (sscanf(mapline,"%x %s %s",&(fn_add[next]),mode,fn_name[next])!=3) - { - fprintf(stderr,"%s: %s(%i): wrong map line\n", - prgname,mapFile, maplineno); - exit(1); - } + while(fgets(mapline,S_LEN,map)) + { + if (sscanf(mapline,"%x %s %s",&fn_add,mode,fn_name)!=3) + { + fprintf(stderr,"%s: %s(%i): wrong map line\n", + prgname,mapFile, maplineno); + exit(1); + } + if (strcmp(fn_name,"_stext")) /* only elf works like this */ + { + add0=fn_add; + break; + } + } - if (!(fn_len=fn_add[next]-fn_add[current])) - continue; + if (!add0) + { + fprintf(stderr,"%s: can't find \"_stext\" in %s\n",prgname, mapFile); + exit(1); + } - if (*mode=='d' || *mode=='D') break; /* only text is profiled */ + /* + * Main loop. + */ + while(fgets(mapline,S_LEN,map)) + { + unsigned int this=0; - while (add<fn_add[next]) + if (sscanf(mapline,"%x %s %s",&next_add,mode,next_name)!=3) { - if (!NEXT_WORD(&l)) - { - fprintf(stderr,"%s: %s: premature EOF\n",prgname,proFile); - exit(1); - } - count+=l; add+=step; + fprintf(stderr,"%s: %s(%i): wrong map line\n", + prgname,mapFile, maplineno); + exit(1); } + if (*mode!='T' && *mode!='t') break; /* only text is profiled */ + + while (index < (next_add-add0)/step) + this += buf[index++]; + total += this; - if (count || optAll) - { - if (optTerse) - printf("%i %s %lg\n", - count,fn_name[current],count/(double)fn_len); - else if (optVerbose) - printf("%08x %-40s %6i %8.4lf\n", - fn_add[current],fn_name[current],count,count/(double)fn_len); - else - printf("%6i %-40s %8.4lf\n", - count,fn_name[current],count/(double)fn_len); - } - } - - if (feof(map)) - { - fprintf(stderr,"%s: %s(%i): premature EOF\n",prgname,mapFile,maplineno); - exit(1); - } + fn_len = next_add-fn_add; + if (fn_len && (this || optAll)) + { + if (optVerbose) + printf("%08x %-40s %6i %8.4f\n", + fn_add,fn_name,this,this/(double)fn_len); + else + printf("%6i %-40s %8.4f\n", + this,fn_name,this/(double)fn_len); + } + fn_add=next_add; strcpy(fn_name,next_name); + } + /* trailer */ + if (optVerbose) + printf("%08x %-40s %6i %8.4f\n", + 0,"total",total,total/(double)(fn_add-add0)); + else + printf("%6i %-40s %8.4f\n", + total,"total",total/(double)(fn_add-add0)); - popenPro ? pclose(pro) : fclose(pro); popenMap ? pclose(map) : fclose(map); exit(0); } + diff --git a/sys-utils/renice.8 b/sys-utils/renice.8 index 5a260a8db..7c1222cd2 100644 --- a/sys-utils/renice.8 +++ b/sys-utils/renice.8 @@ -124,6 +124,11 @@ to map user names to user ID's .Sh BUGS Non super-users can not increase scheduling priorities of their own processes, even if they were the ones that decreased the priorities in the first place. +.br +The Linux kernel (at least version 2.0.0) and linux libc (at least +version 5.2.18) does not agree entierly on what the specifics of the +systemcall interface to set nice values is. Thus causes renice to +report bogus previous nice values. .Sh HISTORY The .Nm diff --git a/sys-utils/renice.c b/sys-utils/renice.c index 6deba6b00..63af8cd4e 100644 --- a/sys-utils/renice.c +++ b/sys-utils/renice.c @@ -47,12 +47,16 @@ static char sccsid[] = "@(#)renice.c 8.1 (Berkeley) 6/9/93"; #include <stdio.h> #include <pwd.h> +#include <stdlib.h> + +int donice(int,int,int); /* * Change the priority (nice) of processes * or groups of processes which are already * running. */ +void main(argc, argv) char **argv; { @@ -106,6 +110,7 @@ main(argc, argv) exit(errs != 0); } +int donice(which, who, prio) int which, who, prio; { diff --git a/sys-utils/setserial.8 b/sys-utils/setserial.8 deleted file mode 100644 index 539db21a2..000000000 --- a/sys-utils/setserial.8 +++ /dev/null @@ -1,392 +0,0 @@ -.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) -.\" May be distributed under the GNU General Public License -.\" Portions of this text are from the README in setserial-2.01.tar.z, -.\" but I can't figure out who wrote that document. If anyone knows, -.\" please tell me -.\" -.\" [tytso:19940519.2239EDT] I did... - Ted Ts'o (tytso@mit.edu) -.\" Sat Aug 27 17:08:38 1994 Changes from Kai Petzke -.\" (wpp@marie.physik.tu-berlin.de) were applied by Rik Faith -.\" (faith@cs.unc.edu) -.\" " -.TH SETSERIAL 8 "27 August 1994" "Setserial 2.10" "Linux Programmer's Manual" -.SH NAME -setserial \- get/set Linux serial port information -.SH SYNOPSIS -.B setserial -.B "[ \-abqvVW ]" -device -.BR "[ " parameter1 " [ " arg " ] ] ..." - -.B "setserial -g" -.B "[ \-abv ]" -device1 ... -.SH DESCRIPTION -.B setserial -is a program designed to set and/or report the configuration information -associated with a serial port. This information includes what I/O -port and IRQ a particular serial port is using, and whether or not the -break key should be interpreted as the Secure Attention Key, and so -on. - -During the normal bootup process, only COM ports 1-4 are initialized, -using the default I/O ports and IRQ values, as listed below. In order -to initialize any additional serial ports, or to change the COM 1-4 -ports to a nonstadard configuration, the -.B setserial -program should be used. Typically it is called from an -.I rc.serial -script, which is usually run out of -.IR /etc/rc.local . - -The -.I device -argument or arguments specifies the serial device which should be configured or -interrogated. It will usually have the following form: -.BR /dev/cua[0-3] . - -If no parameters are specified, -.B setserial -will print out the port type (i.e., 8250, 16450, 16550, 16550A), the -hardware I/O port, the hardware IRQ line, its "baud base," and some of -its operational flags. - -If the -.B \-g -option is given, the arguments to setserial are interpreted as a list -of devices for which the characteristics of those devices should be -printed. - -Without the -.B \-g -option, the first argument to setserial is interpreted as the device -to be modified or characteristics to be printed, and any additional -arguments are interpreted as parameters which should be assigned -to that serial device. - -For the most part, superuser privilege is required to set the -configuration parameters of a serial port. A few serial port parameters -can be set by normal users, however, and these will be noted as -exceptions in this manual page. - -.SH OPTIONS -.B Setserial -accepts the following options: - -.TP -.B \-a -When reporting the configuration of a serial device, print all -available information. -.TP -.B \-b -When reporting the configuration of a serial device, print a summary -of the device's configuration, which might be suitable for printing -during the bootup process, during the /etc/rc script. -.TP -.B \-q -Be quiet. -.B Setserial -will print fewer lines of output. -.TP -.B \-v -Be verbose. -.B Setserial -will print additional status output. -.TP -.B \-V -Display version and exit. -.TP -.B \-W -Do wild interrupt initialization and exit. - -.SH PARAMETERS -The following parameters can be assigned to a serial port. - -All argument values are assumed to be in decimal unless preceeded by "0x". - -.TP -.BR port " port_number" -The -.B port -option sets the I/O port, as described above. -.TP -.BR irq " irq_number" -The -.B irq -option sets the hardware IRQ, as described above. -.TP -.BR uart " uart_type" -This option is used to set the UART type. The permitted types are -.BR none , -8250, 16450, 16550, and 16550A. Since the 8250 and 16450 UARTS do not have -FIFO's, and since the original 16550 have bugs which make the FIFO's unusable, -the FIFO will only be used on chips identifiied as 16550A UARTs. -Setting the UART type to 8250, 16450, or 16550 will enable the serial -port without trying to use the FIFO. Using UART type -.B none -will disable the port. - -Some internal modems are billed as having a "16550A UART with a 1k -buffer". This is a lie. They do not have really have a 16550A -compatible UART; instead what they have is a 16450 compatible UART -with a 1k receive buffer to prevent receiver overruns. This is -important, because they do not have a transmit FIFO. Hence, they are -not compatible with a 16550A UART, and the autoconfiguration process -will correctly identify them as 16450's. If you attempt to override -this using the -.B uart -parameter, you will see dropped characters during file transmissions. -These UART's usually have other problems: the -.B skip_test -parameter also often must be specified. -.TP -.B autoconfig -When this parameter is given, -.B setserial -will ask the kernel to attempt to automatically configure the serial -port. The I/O port must be correctly set; the kernel will attempt to -determine the UART type, and if the -.B auto_irq -parameter is set, Linux will attempt to automatically determine the -IRQ. The -.B autoconfigure -parameter should be given after the -.BR port , auto_irq ", and" skip_test -parameters have been specified. -.TP -.B auto_irq -During autoconfiguration, try to determine the IRQ. This feature is -not guaranteed to always produce the correct result; some hardware -configurations will fool the Linux kernel. It is generally safer not -to use the -.B auto_irq -feature, but rather to specify the IRQ to be used explicitly, using -the -.B irq -parameter. -.TP -.B ^auto_irq -During autoconfiguration, do -.I not -try to determine the IRQ. -.TP -.B skip_test -During autoconfiguration, skip the UART test. Some internal modems do -not have National Semiconductor compatible UART's, but have cheap -imitations instead. Some of these cheasy imitations UART's do not -fully support the loopback detection mode, which is used by the kernel -to make sure there really is a UART at a particular address before -attempting to configure it. So for certain internal modems you will -need to specify this parameter so Linux can initialize the UART -correctly. -.TP -.B ^skip_test -During autoconfiguration, do -.I not -skip the UART test. -.TP -.BR baud_base " baud_base" -This option sets the base baud rate, which is the clock frequency divided -by 16. Normally this value is 115200, which is also the fastest baud -rate which the UART can support. -.TP -.B -spd_hi -Use 57.6kb when the application requests 38.4kb. -This parameter may be specified by a non-privileged user. -.TP -.B spd_vhi -Use 115kb when the application requests 38.4kb. -This parameter may be specified by a non-privileged user. -.TP -.B spd_cust -Use the custom divisor to set the speed when the application requests -38.4kb. In this case, the baud rate is the -.B baud_base -divided by the -.BR divisor . -This parameter may be specified by a non-privileged user. -.TP -.B spd_normal -Use 38.4kb when the application requests 38.4kb. -This parameter may be specified by a non-privileged user. -.TP -.BR divisor " divisor" -This option sets the custom divison. This divisor will be used then the -.B spd_cust -option is selected and the serial port is set to 38.4kb by the -application. -This parameter may be specified by a non-privileged user. -.TP -.B sak -Set the break key at the Secure Attention Key. -.TP -.B ^sak -disable the Secure Attention Key. -.TP -.B fourport -Configure the port as an AST Fourport card. -.TP -.B ^fourport -Disable AST Fourport configuration. -.TP -.BR close_delay " delay" -Specify the amount of time, in hundredths of a second, that DTR should -remain low on a serial line after the callout device is closed, before -the blocked dialin device raises DTR again. The default value of this -option is 50, or a half-second delay. -.TP -.B session_lockout -Lock out callout port (/dev/cuaXX) accesses across different sessions. -That is, once a process has opened a port, do not allow a process with -a different session ID to open that port until the first process has -closed it. -.TP -.B ^session_lockout -Do not lock out callout port accesses across different sessions. -.TP -.B pgrp_lockout -Lock out callout port (/dev/cuaXX) accesses across different process groups. -That is, once a process has opened a port, do not allow a process in a -different process group to open that port until the first process has -closed it. -.TP -.B ^pgrp_lockout -Do not lock out callout port accesses across different process groups. -.TP -.B hup_notify -Notify a process blocked on opening a dial in line when a process has -finished using a callout line (either by closing it or by the serial -line being hung up) by returning EAGAIN to the open. - -The application of this parameter is for getty's which are blocked on -a serial port's dial in line. This allows the getty to reset the -modem (which may have had its configuration modified by the -application using the callout device) before blocking on the open again. -.TP -.B ^hup_notify -Do not notify a process blocked on opening a dial in line when the -callout device is hung up. -.TP -.B split_termios -Treat the termios settings used by the callout device and the termios -settings used by the dialin devices as separate. -.TP -.B ^split_termios -Use the same termios structure to store both the dialin and callout -ports. This is the default option. -.TP -.B callout_nohup -If this particular serial port is opened as a callout device, do not -hangup the tty when carrier detect is dropped. -.TP -.B ^callout_nohup -Do not skip hanging up the tty when a serial port is opened as a -callout device. Of course, the HUPCL termios flag must be enabled if -the hangup is to occur. -.SH CONSIDERATIONS OF CONFIGURING SERIAL PORTS -It is important to note that setserial merely tells the Linux kernel -where it should expect to find the I/O port and IRQ lines of a -particular serial port. It does *not* configure the hardware, the -actual serial board, to use a particular I/O port. In order to do -that, you will need to physically program the serial board, usually by -setting some jumpers or by switching some DIP switches. - -This section will provide some pointers in helping you decide how you -would like to configure your serial ports. - -The "standard MS-DOS" port associations are given below: - -.nf -.RS -/dev/ttyS0 (COM1), port 0x3f8, irq 4 -/dev/ttyS1 (COM2), port 0x2f8, irq 3 -/dev/ttyS2 (COM3), port 0x3e8, irq 4 -/dev/ttyS3 (COM4), port 0x2e8, irq 3 -.RE -.fi - -Due to the limitations in the design of the AT/ISA bus architecture, -normally an IRQ line may not be shared between two or more serial -ports. If you attempt to do this, one or both serial ports will -become unreliable if you try to use both simultaneously. This -limitation can be overcome by special multi-port serial port boards, -which are designed to share multiple serial ports over a single IRQ -line. Multi-port serial cards supported by Linux include the AST -FourPort, the Accent Async board, the Usenet Serial II board, the -Bocaboard BB-1004, BB-1008, and BB-2016 boards, and the HUB-6 serial -board. - -The selection of an alternative IRQ line -is difficult, since most of them are already used. The following table -lists the "standard MS-DOS" assignments of available IRQ lines: - -.nf -.RS -IRQ 3: COM2 -IRQ 4: COM1 -IRQ 5: LPT2 -IRQ 7: LPT1 -.RE -.fi - -Most people find that IRQ 5 is a good choice, assuming that there is -only one parallel port active in the computer. Another good choice is -IRQ 2 (aka IRQ 9); although this IRQ is sometimes used by network -cards, and very rarely VGA cards will be configured to use IRQ 2 as a -vertical retrace interrupt. If your VGA card is configured this way; -try to disable it so you can reclaim that IRQ line for some other -card. It's not necessary for Linux and most other Operating systems. - -The only other available IRQ lines are 3, 4, and 7, and these are -probably used by the other serial and parallel ports. (If your serial -card has a 16bit card edge connector, and supports higher interrupt -numbers, then IRQ 10, 11, 12, and 15 are also available.) - -On AT class machines, IRQ 2 is seen as IRQ 9, and Linux will interpret it -in this manner. - -IRQ's other than 2 (9), 3, 4, 5, 7, 10, 11, 12, and 15, should -.I not -be used, since they are assigned to other hardware and cannot, in general, -be changed. Here are the "standard" assignments: - -.nf -.RS -IRQ 0 Timer channel 0 -IRQ 1 Keyboard -IRQ 2 Cascade for controller 2 -IRQ 3 Serial port 2 -IRQ 4 Serial port 1 -IRQ 5 Parallel port 2 (Reserved in PS/2) -IRQ 6 Floppy diskette -IRQ 7 Parallel port 1 -IRQ 8 Real-time clock -IRQ 9 Redirected to IRQ2 -IRQ 10 Reserved -IRQ 11 Reserved -IRQ 12 Reserved (Auxillary device in PS/2) -IRQ 13 Math coprocessor -IRQ 14 Hard disk controller -IRQ 15 Reserved -.RE -.fi - - -.SH CAUTION -CAUTION: Using an invalid port can lock up your machine. -.SH FILES -.BR /etc/rc.local -.BR /etc/rc.serial -.SH "SEE ALSO" -.BR tty (4), -.BR ttys (4), -kernel/chr_drv/serial.c -.SH AUTHOR -The original version of setserial was written by Rick Sladkey -(jrs@world.std.com), and was modified by Michael K. Johnson -(johnsonm@stolaf.edu). - -This version has since been rewritten from scratch by Theodore Ts'o -(tytso@mit.edu) on 1/1/93. Any bugs or problems are solely his -responsibility. diff --git a/sys-utils/setserial.c b/sys-utils/setserial.c deleted file mode 100644 index 71179baa8..000000000 --- a/sys-utils/setserial.c +++ /dev/null @@ -1,436 +0,0 @@ -/* setserial.c - get/set Linux serial port info - rick sladkey */ -/* modified to do work again and added setting fast serial speeds, - Michael K. Johnson, johnsonm@stolaf.edu */ -/* - * Very heavily modified --- almost rewritten from scratch --- to have - * a more flexible command structure. Now able to set any of the - * serial-specific options using the TIOCSSERIAL ioctl(). - * Theodore Ts'o, tytso@mit.edu, 1/1/93 - * - * Last modified: [tytso:19940520.0036EDT] - */ - -#include <stdio.h> -#include <fcntl.h> -#include <termios.h> -#include <string.h> -#include <errno.h> - -#include <linux/fs.h> -#include <linux/serial.h> -#include <linux/tty.h> - -#define VERSION_STR "2.10" - -char *progname; - -int verbosity = 1; /* 1 = normal, 0=boot-time, 2=everything */ -int verbose_flag = 0; /* print results after setting a port */ -int quiet_flag = 0; - -struct serial_type_struct { - int id; - char *name; -} serial_type_tbl[] = { - PORT_UNKNOWN, "unknown", - PORT_8250, "8250", - PORT_16450, "16450", - PORT_16550, "16550", - PORT_16550A, "16550A", - PORT_UNKNOWN, "none", - -1, NULL -}; - -#define CMD_FLAG 1 -#define CMD_PORT 2 -#define CMD_IRQ 3 -#define CMD_DIVISOR 4 -#define CMD_TYPE 5 -#define CMD_BASE 6 -#define CMD_DELAY 7 -#define CMD_CONFIG 8 - -#define FLAG_CAN_INVERT 0x0001 -#define FLAG_NEED_ARG 0x0002 - -struct flag_type_table { - int cmd; - char *name; - int bits; - int mask; - int level; - int flags; -} flag_type_tbl[] = { - CMD_FLAG, "spd_normal", 0, ASYNC_SPD_MASK, 2, 0, - CMD_FLAG, "spd_hi", ASYNC_SPD_HI, ASYNC_SPD_MASK, 0, 0, - CMD_FLAG, "spd_vhi", ASYNC_SPD_VHI, ASYNC_SPD_MASK, 0, 0, - CMD_FLAG, "spd_cust", ASYNC_SPD_CUST, ASYNC_SPD_MASK, 0, 0, - - CMD_FLAG, "SAK", ASYNC_SAK, ASYNC_SAK, 0, FLAG_CAN_INVERT, - CMD_FLAG, "Fourport", ASYNC_FOURPORT, ASYNC_FOURPORT, 0, FLAG_CAN_INVERT, - CMD_FLAG, "hup_notify", ASYNC_HUP_NOTIFY, ASYNC_HUP_NOTIFY, 0, FLAG_CAN_INVERT, - CMD_FLAG, "skip_test", ASYNC_SKIP_TEST,ASYNC_SKIP_TEST,2, FLAG_CAN_INVERT, - CMD_FLAG, "auto_irq", ASYNC_AUTO_IRQ, ASYNC_AUTO_IRQ, 2, FLAG_CAN_INVERT, -#ifdef ASYNC_SPLIT_TERMIOS - CMD_FLAG, "split_termios", ASYNC_SPLIT_TERMIOS, ASYNC_SPLIT_TERMIOS, 2, FLAG_CAN_INVERT, -#endif - CMD_FLAG, "session_lockout", ASYNC_SESSION_LOCKOUT, ASYNC_SESSION_LOCKOUT, 2, FLAG_CAN_INVERT, - CMD_FLAG, "pgrp_lockout", ASYNC_PGRP_LOCKOUT, ASYNC_PGRP_LOCKOUT, 2, FLAG_CAN_INVERT, -#ifdef ASYNC_CALLOUT_NOHUP - CMD_FLAG, "callout_nohup", ASYNC_CALLOUT_NOHUP, ASYNC_CALLOUT_NOHUP, 2, FLAG_CAN_INVERT, -#endif - - CMD_PORT, "port", 0, 0, 0, FLAG_NEED_ARG, - CMD_IRQ, "irq", 0, 0, 0, FLAG_NEED_ARG, - CMD_DIVISOR, "divisor", 0, 0, 0, FLAG_NEED_ARG, - CMD_TYPE, "uart", 0, 0, 0, FLAG_NEED_ARG, - CMD_BASE, "base", 0, 0, 0, FLAG_NEED_ARG, - CMD_BASE, "baud_base", 0, 0, 0, FLAG_NEED_ARG, - CMD_DELAY, "close_delay", 0, 0, 0, FLAG_NEED_ARG, - CMD_CONFIG, "autoconfig", 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -}; - -char *serial_type(int id) -{ - int i; - - for (i = 0; serial_type_tbl[i].id != -1; i++) - if (id == serial_type_tbl[i].id) - return serial_type_tbl[i].name; - return "undefined"; -} - -int uart_type(char *name) -{ - int i; - - for (i = 0; serial_type_tbl[i].id != -1; i++) - if (!strcasecmp(name, serial_type_tbl[i].name)) - return serial_type_tbl[i].id; - return -1; -} - - -int atonum(char *s) -{ - int n; - - while (*s == ' ') - s++; - if (strncmp(s, "0x", 2) == 0 || strncmp(s, "0X", 2) == 0) - sscanf(s + 2, "%x", &n); - else if (s[0] == '0' && s[1]) - sscanf(s + 1, "%o", &n); - else - sscanf(s, "%d", &n); - return n; -} - -void print_flags(struct serial_struct *serinfo, - char *prefix, char *postfix) -{ - struct flag_type_table *p; - int flags; - int first = 1; - - flags = serinfo->flags; - - for (p = flag_type_tbl; p->name; p++) { - if (p->cmd != CMD_FLAG) - continue; - if (verbosity < p->level) - continue; - if ((flags & p->mask) == p->bits) { - if (first) { - printf("%s", prefix); - first = 0; - } else - printf(" "); - printf("%s", p->name); - } - } - - if (!first) - printf("%s", postfix); -} - -void get_serial(char *device) -{ - struct serial_struct serinfo; - int fd; - - if ((fd = open(device, O_RDWR|O_NONBLOCK)) < 0) { - perror(device); - return; - } - if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) { - perror("Cannot get serial info"); - close(fd); - return; - } - if (serinfo.irq == 9) - serinfo.irq = 2; /* People understand 2 better than 9 */ - if (verbosity==2) { - printf("%s, Line %d, UART: %s, Port: 0x%.4x, IRQ: %d\n", - device, serinfo.line, serial_type(serinfo.type), - serinfo.port, serinfo.irq); - printf("\tBaud_base: %d, close_delay: %d, divisor: %d\n", - serinfo.baud_base, serinfo.close_delay, - serinfo.custom_divisor); - print_flags(&serinfo, "\tFlags: ", ""); - printf("\n\n"); - } else if (verbosity==0) { - if (serinfo.type) { - printf("%s at 0x%.4x (irq = %d) is a %s", - device, serinfo.port, serinfo.irq, - serial_type(serinfo.type)); - print_flags(&serinfo, " (", ")"); - printf("\n"); - } - } else { - printf("%s, UART: %s, Port: 0x%.4x, IRQ: %d", - device, serial_type(serinfo.type), - serinfo.port, serinfo.irq); - print_flags(&serinfo, ", Flags: ", ""); - printf("\n"); - } - close(fd); -} - -void set_serial(char *device, char ** arg) -{ - struct serial_struct old_serinfo, new_serinfo; - struct flag_type_table *p; - int fd; - int do_invert = 0; - char *word; - - - if ((fd = open(device, O_RDWR|O_NONBLOCK)) < 0) { - if (verbosity==0 && errno==ENOENT) - exit(201); - perror(device); - exit(201); - } - if (ioctl(fd, TIOCGSERIAL, &old_serinfo) < 0) { - perror("Cannot get serial info"); - exit(1); - } - new_serinfo = old_serinfo; - while (*arg) { - do_invert = 0; - word = *arg++; - if (*word == '^') { - do_invert++; - word++; - } - for (p = flag_type_tbl; p->name; p++) { - if (!strcasecmp(p->name, word)) - break; - } - if (!p->name) { - fprintf(stderr, "Invalid flag: %s\n", word); - exit(1); - } - if (do_invert && !(p->flags & FLAG_CAN_INVERT)) { - fprintf(stderr, "This flag can not be inverted: %s\n", word); - exit(1); - } - if ((p->flags & FLAG_NEED_ARG) && !*arg) { - fprintf(stderr, "Missing argument for %s\n", word); - exit(1); - } - switch (p->cmd) { - case CMD_FLAG: - new_serinfo.flags &= ~p->mask; - if (!do_invert) - new_serinfo.flags |= p->bits; - break; - case CMD_PORT: - new_serinfo.port = atonum(*arg++); - break; - case CMD_IRQ: - new_serinfo.irq = atonum(*arg++); - break; - case CMD_DIVISOR: - new_serinfo.custom_divisor = atonum(*arg++); - break; - case CMD_TYPE: - new_serinfo.type = uart_type(*arg++); - if (new_serinfo.type < 0) { - fprintf(stderr, "Illegal UART type: %s", *--arg); - exit(1); - } - break; - case CMD_BASE: - new_serinfo.baud_base = atonum(*arg++); - break; - case CMD_DELAY: - new_serinfo.close_delay = atonum(*arg++); - break; - case CMD_CONFIG: - if (ioctl(fd, TIOCSSERIAL, &new_serinfo) < 0) { - perror("Cannot set serial info"); - exit(1); - } - if (ioctl(fd, TIOCSERCONFIG) < 0) { - perror("Cannot autoconfigure port"); - exit(1); - } - if (ioctl(fd, TIOCGSERIAL, &new_serinfo) < 0) { - perror("Cannot get serial info"); - exit(1); - } - break; - default: - fprintf(stderr, "Internal error: unhandled cmd #%d\n", p->cmd); - exit(1); - } - } - if (ioctl(fd, TIOCSSERIAL, &new_serinfo) < 0) { - perror("Cannot set serial info"); - exit(1); - } - close(fd); - if (verbose_flag) - get_serial(device); -} - -void do_wild_intr(char *device) -{ - int fd; - int i, mask; - int wild_mask = -1; - - if ((fd = open(device, O_RDWR|O_NONBLOCK)) < 0) { - perror(device); - exit(1); - } - if (ioctl(fd, TIOCSERSWILD, &wild_mask) < 0) { - perror("Cannot scan for wild interrupts"); - exit(1); - } - if (ioctl(fd, TIOCSERGWILD, &wild_mask) < 0) { - perror("Cannot get wild interrupt mask"); - exit(1); - } - close(fd); - if (quiet_flag) - return; - if (wild_mask) { - printf("Wild interrupts found: "); - for (i=0, mask=1; mask <= wild_mask; i++, mask <<= 1) - if (mask & wild_mask) - printf(" %d", i); - printf("\n"); - } else if (verbose_flag) - printf("No wild interrupts found.\n"); - return; -} - - - - -void usage() -{ - fprintf(stderr, "setserial Version %s\n\n", VERSION_STR); - fprintf(stderr, - "usage: %s serial-device [cmd1 [arg]] ... \n\n", progname); - fprintf(stderr, "Available commands: (* = Takes an argument)\n"); - fprintf(stderr, "\t\t(^ = can be preceded by a '^' to turn off the option)\n"); -fprintf(stderr, "\t* port\t\tset the I/O port\n"); - fprintf(stderr, "\t* irq\t\tset the interrupt\n"); - fprintf(stderr, "\t* uart\t\tset UART type (none, 8250, 16450, 16550, 16550A\n"); - fprintf(stderr, "\t* baud_base\tset base baud rate (CLOCK_FREQ / 16)\n"); - fprintf(stderr, "\t* divisor\tset the custom divisor (see spd_custom)\n"); - fprintf(stderr, "\t* close_delay\tset the amount of time (in 1/100 of a\n"); - fprintf(stderr, "\t\t\t\tsecond) that DTR should be kept low\n"); - fprintf(stderr, "\t\t\t\twhile being closed\n"); - - fprintf(stderr, "\t^ fourport\tconfigure the port as an AST Fourport\n"); - fprintf(stderr, "\t autoconfigure\tautomatically configure the serial port\n"); - fprintf(stderr, "\t^ auto_irq\ttry to determine irq during autoconfiguration\n"); - fprintf(stderr, "\t^ skip_test\tskip UART test during autoconfiguration\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "\t^ sak\t\tset the break key as the Secure Attention Key\n"); - fprintf(stderr, "\t^ session_lockout Lock out callout port across different sessions\n"); - fprintf(stderr, "\t^ pgrp_lockout\tLock out callout port across different process groups\n"); -#ifdef ASYNC_CALLOUT_NOHUP - fprintf(stderr, "\t^ callout_nohup\tDon't hangup the tty when carrier detect drops\n"); -#endif - fprintf(stderr, "\t\t\t\t on the callout device\n"); -#ifdef ASYNC_SPLIT_TERMIOS - fprintf(stderr, "\t^ split_termios Use separate termios for callout and dailin lines\n"); -#endif - fprintf(stderr, "\t^ hup_notify\tNotify a process blocked on opening a dial in line\n"); - fprintf(stderr, "\t\t\t\twhen a process has finished using a callout\n"); - fprintf(stderr, "\t\t\t\tline by returning EAGAIN to the open.\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "\t spd_hi\tuse 56kb instead of 38.4kb\n"); - fprintf(stderr, "\t spd_vhi\tuse 115kb instead of 38.4kb\n"); - fprintf(stderr, "\t spd_cust\tuse the custom divisor to set the speed at 38.4kb\n"); - fprintf(stderr, "\t\t\t\t(baud rate = baud_base / custom_divisor)\n"); - fprintf(stderr, "\t spd_normal\tuse 38.4kb when a buad rate of 38.4kb is selected\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Use a leading '0x' for hex numbers.\n"); - fprintf(stderr, "CAUTION: Using an invalid port can lock up your machine!\n"); - exit(1); -} - -main(int argc, char **argv) -{ - int get_flag = 0, wild_intr_flag = 0; - int c; - extern int optind; - extern char *optarg; - - progname = argv[0]; - if (argc == 1) - usage(); - while ((c = getopt(argc, argv, "abgqvVW")) != EOF) { - switch (c) { - case 'a': - verbosity = 2; - break; - case 'b': - verbosity = 0; - break; - case 'q': - quiet_flag++; - break; - case 'v': - verbose_flag++; - break; - case 'g': - get_flag++; - break; - case 'V': - fprintf(stderr, "setserial version %s\n", VERSION_STR); - exit(0); - case 'W': - wild_intr_flag++; - break; - default: - usage(); - } - } - if (get_flag) { - argv += optind; - while (*argv) - get_serial(*argv++); - exit(0); - } - if (argc == optind) - usage(); - if (wild_intr_flag) { - do_wild_intr(argv[optind]); - exit(0); - } - if (argc-optind == 1) - get_serial(argv[optind]); - else - set_serial(argv[optind], argv+optind+1); - exit(0); -} - diff --git a/sys-utils/shhopt-1.1.lsm b/sys-utils/shhopt-1.1.lsm new file mode 100644 index 000000000..a61a26969 --- /dev/null +++ b/sys-utils/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/sys-utils/shhopt.c b/sys-utils/shhopt.c new file mode 100644 index 000000000..6d31225c8 --- /dev/null +++ b/sys-utils/shhopt.c @@ -0,0 +1,467 @@ +/* $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 <sverrehu@ifi.uio.no> + * + **************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#include <limits.h> +#include <errno.h> + +#include "shhopt.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. + * + */ +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/sys-utils/shhopt.h b/sys-utils/shhopt.h new file mode 100644 index 000000000..ca8501ef5 --- /dev/null +++ b/sys-utils/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/sys-utils/sln.1 b/sys-utils/sln.1 new file mode 100644 index 000000000..a89271936 --- /dev/null +++ b/sys-utils/sln.1 @@ -0,0 +1,22 @@ +.\" Nicolai Langfeldt (janl@math.uio.no) +.\" In the public domain. +.TH SLN 8 "20 June 1997" "Linux 2.0" "Linux Programmer's Manual" +.SH NAME +sln \- static ln +.SH SYNOPSIS +.BI sln " source dest" +.SH DESCRIPTION +.B sln +symbolically links +.I dest +to +.I source +It is statically linked, needing no dynamic linking at all. This that +sln is usefull to make symbolic links to dynamic libraries if the +dynamic linking system for some reason is nonfunctional. +.SH "SEE ALSO" +.BR ln(1) +.BR ldconfig(8) +.BR ld.so(8) +.SH AUTHOR +Mike Parker and David MacKenzie. diff --git a/sys-utils/sync.8 b/sys-utils/sync.8 deleted file mode 100644 index f8bb704ff..000000000 --- a/sys-utils/sync.8 +++ /dev/null @@ -1,38 +0,0 @@ -.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) -.\" May be distributed under the GNU General Public License -.TH SYNC 8 "20 November 1993" "Linux 0.99" "Linux Programmer's Manual" -.SH NAME -sync \- flush Linux filesystem buffers -.SH SYNOPSIS -.B sync -.SH DESCRIPTION -.B sync -executes -.BR sync (2), -which flushes the filesystem buffers to disk. -.B sync -should be called before the processor is halted in an unusual manner (i.e., -before causing a kernel panic when debugging new kernel code). In general, -the processor should be halted using the -.BR reboot "(8), or " halt (8) -commands, which will attempt to put the system in a quiescent state before -calling -.BR sync (2). - -From Linus: "Note that -.B sync -is only guaranteed to schedule the dirty blocks for writing: it can -actually take a short time before all the blocks are finally written. If -you are doing the -.B sync -with the expectation of killing the machine soon after, please take this -into account and sleep for a few seconds. [The -.BR reboot (8) -command takes these precautions.] -.SH "SEE ALSO" -.BR sync (2), -.BR update (8), -.BR reboot (8), -.BR halt (8) -.SH AUTHOR -Linus Torvalds (torvalds@cs.helsinki.fi) diff --git a/sys-utils/sync.S b/sys-utils/sync.S deleted file mode 100644 index 5b7fd82b2..000000000 --- a/sys-utils/sync.S +++ /dev/null @@ -1,24 +0,0 @@ -/* File: - * sync.S - * Compile: - * gcc -nostdlib sync.S -o sync - * Author: - * Nick Holloway, with thanks to James Bonfield - * Modified for ELF by Michael Shields - * Rik Faith added __ASSEMBLY__ for gcc 2.5.8 - * Last Changed: - * 1995-07-04 - */ -#include <sys/syscall.h> -#ifndef __ASSEMBLY__ -#define __ASSEMBLY__ -#endif -#include <linux/linkage.h> - - .text -ENTRY(_start) - movl $(SYS_sync),%eax /* sync () */ - int $0x80 - movl $(SYS_exit),%eax /* exit ( 0 ) */ - movl $0,%ebx - int $0x80 diff --git a/sys-utils/tunelp.8 b/sys-utils/tunelp.8 index bff567626..8b148f20a 100644 --- a/sys-utils/tunelp.8 +++ b/sys-utils/tunelp.8 @@ -1,8 +1,8 @@ -.\" This file Copyright 1992 Michael K. Johnson (johnsonm@nigel.vnet.net) -.\" It may be distributed under the GNU Public License, version 2, or -.\" any higher version. See section COPYING of the GNU Public license -.\" for conditions under which this file may be redistributed. -.\" $Id: tunelp.8,v 1.5 1995/03/12 01:34:24 faith Exp $ +.\" This file Copyright (C) 1992-1997 Michael K. Johnson <johnsonm@redhat.com> +.\" It may be distributed under the terms of the GNU General Public License, +.\" version 2, or any higher version. See section COPYING of the GNU General +.\" Public license for conditions under which this file may be redistributed. +.\" $Id: tunelp.8,v 1.6 1997/06/20 16:10:35 janl Exp $ .TH tunelp 8 "26 August 1992" "Cohesive Systems" "Linux Programmer's Manual" .SH NAME tunelp \- set various parameters for the lp device diff --git a/sys-utils/tunelp.c b/sys-utils/tunelp.c index a854b46b1..6bdebda72 100644 --- a/sys-utils/tunelp.c +++ b/sys-utils/tunelp.c @@ -1,18 +1,30 @@ /****************************************************************************\ -* Copyright (C) 1992 by Michael K. Johnson, johnsonm@nigel.vnet.net * +* Copyright (C) 1992-1997 Michael K. Johnson, johnsonm@redhat.com * * * -* This file is placed under the conditions of the GNU public * -* license, version 2, or any later version. See file COPYING * +* This file is licensed under the terms of the GNU General * +* Public License, version 2, or any later version. See file COPYING * * for information on distribution conditions. * \****************************************************************************/ -/* $Id: tunelp.c,v 1.6 1995/06/04 01:47:11 faith Exp $ +/* $Id: tunelp.c,v 1.8 1997/07/06 00:14:06 aebr Exp $ * $Log: tunelp.c,v $ - * Revision 1.6 1995/06/04 01:47:11 faith - * Changes for util-linux-2.4 + * Revision 1.8 1997/07/06 00:14:06 aebr + * Fixes to silence -Wall. * - * Revision 1.5 1995/03/12 01:29:50 faith - * util-linux-2.1 + * Revision 1.7 1997/06/20 16:10:38 janl + * tunelp refreshed from authors archive. + * + * Revision 1.9 1997/06/20 12:56:43 johnsonm + * Finished fixing license terms. + * + * Revision 1.8 1997/06/20 12:34:59 johnsonm + * Fixed copyright and license. + * + * Revision 1.7 1995/03/29 11:16:23 johnsonm + * TYPO fixed... + * + * Revision 1.6 1995/03/29 11:12:15 johnsonm + * Added third argument to ioctl needed with new kernels * * Revision 1.5 1995/01/13 10:33:43 johnsonm * Chris's changes for new ioctl numbers and backwards compatibility @@ -74,7 +86,7 @@ void *mylloc(long size) { long get_val(char *val) { long ret; - if (!(sscanf(val, "%d", &ret) == 1)) { + if (!(sscanf(val, "%ld", &ret) == 1)) { perror("sscanf error"); exit(3); } @@ -198,6 +210,8 @@ int main (int argc, char ** argv) { } /* Allow for binaries compiled under a new kernel to work on the old ones */ + /* The irq argument to ioctl isn't touched by the old kernels, but we don't */ + /* want to cause the kernel to complain if we are using a new kernel */ if (LPGETIRQ >= 0x0600 && ioctl(fd, LPGETIRQ, &irq) < 0 && errno == EINVAL) offset = 0x0600; /* We don't understand the new ioctls */ |