diff options
| author | Richard Maw <richard.maw@codethink.co.uk> | 2014-06-12 12:04:01 +0100 |
|---|---|---|
| committer | Richard Maw <richard.maw@codethink.co.uk> | 2014-06-12 12:04:01 +0100 |
| commit | c5c1033c5c7deda8abe3448ec81bbb33c72219e0 (patch) | |
| tree | 6e5cef29b85161eea8a7488a029f5a32f982c6ab /term-utils | |
| parent | 462008f79be9e195670b202cb43827b8aeb1e60b (diff) | |
| parent | 2fb567c080e1762ec6a2147564f03068f55d4f14 (diff) | |
| download | util-linux-baserock/morph.tar.gz | |
Merge branch 'baserock/richardmaw/yakshave/util-linux-blkid' into baserock/morphbaserock/morph
Reviewed-by: Lars Wirzenius
Reviewed-by: Sam Thursfield
Diffstat (limited to 'term-utils')
| -rw-r--r-- | term-utils/Makemodule.am | 8 | ||||
| -rw-r--r-- | term-utils/agetty.8 | 242 | ||||
| -rw-r--r-- | term-utils/agetty.c | 249 | ||||
| -rw-r--r-- | term-utils/mesg.1 | 4 | ||||
| -rw-r--r-- | term-utils/mesg.c | 25 | ||||
| -rw-r--r-- | term-utils/script.1 | 4 | ||||
| -rw-r--r-- | term-utils/script.c | 53 | ||||
| -rw-r--r-- | term-utils/scriptreplay.1 | 2 | ||||
| -rw-r--r-- | term-utils/scriptreplay.c | 5 | ||||
| -rw-r--r-- | term-utils/setterm.1 | 6 | ||||
| -rw-r--r-- | term-utils/setterm.c | 7 | ||||
| -rw-r--r-- | term-utils/ttymsg.c | 5 | ||||
| -rw-r--r-- | term-utils/wall.1 | 53 | ||||
| -rw-r--r-- | term-utils/wall.c | 147 | ||||
| -rw-r--r-- | term-utils/write.1 | 2 | ||||
| -rw-r--r-- | term-utils/write.c | 15 |
16 files changed, 555 insertions, 272 deletions
diff --git a/term-utils/Makemodule.am b/term-utils/Makemodule.am index 470987344..e53471f23 100644 --- a/term-utils/Makemodule.am +++ b/term-utils/Makemodule.am @@ -28,10 +28,14 @@ if BUILD_SETTERM usrbin_exec_PROGRAMS += setterm dist_man_MANS += term-utils/setterm.1 setterm_SOURCES = term-utils/setterm.c +setterm_CFLAGS = $(AM_CFLAGS) +setterm_LDADD = $(LDADD) if HAVE_TINFO -setterm_LDADD = $(LDADD) -ltinfo +setterm_LDADD += $(TINFO_LIBS) +setterm_CFLAGS += $(TINFO_CFLAGS) else -setterm_LDADD = $(LDADD) @NCURSES_LIBS@ +setterm_LDADD += $(NCURSES_LIBS) +setterm_CFLAGS += $(NCURSES_CFLAGS) endif endif diff --git a/term-utils/agetty.8 b/term-utils/agetty.8 index 64a1dd289..ad0bfa02b 100644 --- a/term-utils/agetty.8 +++ b/term-utils/agetty.8 @@ -3,51 +3,46 @@ agetty \- alternative Linux getty .SH SYNOPSIS -.BR "agetty " [\-8chiLmnsUw] -.RI "[\-a " user ] -.RI "[\-f " issue_file ] -.RI "[\-H " login_host ] -.RI "[\-I " init ] -.RI "[\-l " login_program ] -.RI "[\-t " timeout ] +.B agetty +.RB [ options ] .I port -.I baud_rate,... +.RI [ baud_rate ...] .RI [ term ] .SH DESCRIPTION .ad .fi \fBagetty\fP opens a tty port, prompts for a login name and invokes -the /bin/login command. It is normally invoked by \fIinit(8)\fP. +the /bin/login command. It is normally invoked by \fBinit\fP(8). \fBagetty\fP has several \fInon-standard\fP features that are useful -for hard-wired and for dial-in lines: -.IP o +for hardwired and for dial-in lines: +.IP \(bu Adapts the tty settings to parity bits and to erase, kill, end-of-line and uppercase characters when it reads a login name. The program can handle 7-bit characters with even, odd, none or space parity, and 8-bit characters with no parity. The following special characters are recognized: Control-U (kill); DEL and -back space (erase); carriage return and line feed (end of line). -See also \fB\-\-erase-chars\fP and \fB\-\-kill-chars\fP options. -.IP o +backspace (erase); carriage return and line feed (end of line). +See also the \fB\-\-erase-chars\fP and \fB\-\-kill-chars\fP options. +.IP \(bu Optionally deduces the baud rate from the CONNECT messages produced by Hayes(tm)-compatible modems. -.IP o +.IP \(bu Optionally does not hang up when it is given an already opened line (useful for call-back applications). -.IP o +.IP \(bu Optionally does not display the contents of the \fI/etc/issue\fP file. -.IP o +.IP \(bu Optionally displays an alternative issue file instead of \fI/etc/issue\fP. -.IP o +.IP \(bu Optionally does not ask for a login name. -.IP o +.IP \(bu Optionally invokes a non-standard login program instead of \fI/bin/login\fP. -.IP o -Optionally turns on hard-ware flow control -.IP o +.IP \(bu +Optionally turns on hardware flow control +.IP \(bu Optionally forces the line to be local with no need for carrier detect. .PP This program does not use the \fI/etc/gettydefs\fP (System V) or @@ -73,11 +68,17 @@ A comma-separated list of one or more baud rates. Each time the list, which is treated as if it were circular. .sp Baud rates should be specified in descending order, so that the -null character (Ctrl\-@) can also be used for baud rate switching. +null character (Ctrl\-@) can also be used for baud-rate switching. +.sp +This argument is optional and unnecessary for virtual terminals. +The default for serial terminals is '9600'. .TP term The value to be used for the TERM environment variable. This overrides whatever init(8) may have set, and is inherited by login and the shell. +.sp +The default is 'vt100', or 'linux' for Linux on a virtual terminal, +or 'hurd' for GNU Hurd on a virtual terminal. .SH OPTIONS .na .nf @@ -95,12 +96,12 @@ behaviour and then only \\u is replaced by the \fIusername\fP and no other option is added to the login command line. .TP \-c, \-\-noreset -Don't reset terminal cflags (control modes). See \fItermios(3)\fP for more +Don't reset terminal cflags (control modes). See \fBtermios\fP(3) for more details. .TP \-E, \-\-remote -If \-H \fIfakehost\fP option is given then \-r \fIfakehost\fP options is -added to the \fB/bin/login\fP command line. +If an \fB\-H\fP \fIfakehost\fP option is given, then an \fB\-r\fP +\fIfakehost\fP option is added to the \fB/bin/login\fP command line. .TP \-f, \-\-issue\-file \fIissue_file\fP Display the contents of \fIissue_file\fP instead of \fI/etc/issue\fP. @@ -113,10 +114,10 @@ application to disable software (XON/XOFF) flow protocol where appropriate. .TP \-H, \-\-host \fIlogin_host\fP -Write the specified \fIlogin_host\fP into the utmp file. (Normally, +Write the specified \fIlogin_host\fP into the utmp file. (Normally, no login host is given, since \fBagetty\fP is used for local hardwired connections and consoles. However, this option can be useful for -identifying terminal concentrators and the like. +identifying terminal concentrators and the like.) .TP \-i, \-\-noissue Do not display the contents of \fI/etc/issue\fP (or other) before writing the @@ -126,10 +127,10 @@ may fail if the login prompt is preceded by too much text. .TP \-I, \-\-init\-string \fIinitstring\fP Set an initial string to be sent to the tty or modem before sending -anything else. This may be used to initialize a modem. Non printable +anything else. This may be used to initialize a modem. Non-printable characters may be sent by writing their octal code preceded by a -backslash (\\). For example to send a linefeed character (ASCII 10, -octal 012) write \\012. +backslash (\\). For example, to send a linefeed character (ASCII 10, +octal 012), write \\012. .PP .TP \-l, \-\-login\-program \fIlogin_program\fP @@ -138,34 +139,44 @@ This allows the use of a non-standard login program (for example, one that asks for a dial-up password or that uses a different password file). .TP -\-L, \-\-local\-line -Force the line to be a local line with no need for carrier detect. This can -be useful when you have a locally attached terminal where the serial line -does not set the carrier detect signal. +\-L, \-\-local\-line[=\fImode\fP] +Control the CLOCAL line flag. The optional \fImode\fP argument is 'auto', 'always' or 'never'. +If the \fImode\fP argument is omitted, then the default is 'always'. If the +\-\-local\-line option is not given at all, then the default is 'auto'. + +The \fImode\fP 'always' forces the line to be a local line with no need for carrier detect. +This can be useful when you have a locally attached terminal where the serial line +does not set the carrier-detect signal. + +The \fImode\fP 'never' explicitly clears the CLOCAL flag from the line setting and +the carrier-detect signal is expected on the line. + +The \fImode\fP 'auto' (agetty default) does not modify the CLOCAL setting +and follows the setting enabled by the kernel. .TP \-m, \-\-extract\-baud -Try to extract the baud rate the CONNECT status message +Try to extract the baud rate from the CONNECT status message produced by Hayes(tm)\-compatible modems. These status messages are of the form: "<junk><speed><junk>". \fBagetty\fP assumes that the modem emits its status message at the same speed as specified with (the first) \fIbaud_rate\fP value on the command line. .sp -Since the \fI\-m\fP feature may fail on heavily-loaded systems, +Since the \fB\-m\fP feature may fail on heavily-loaded systems, you still should enable BREAK processing by enumerating all expected baud rates on the command line. .TP \-n, \-\-skip\-login Do not prompt the user for a login name. This can be used in -connection with \-l option to invoke a non-standard login process such +connection with the \fB\-l\fP option to invoke a non-standard login process such as a BBS system. Note that with the \-n option, \fBagetty\fR gets no input from -user who logs in and therefore won't be able to figure out parity, +the user who logs in and therefore won't be able to figure out parity, character size, and newline processing of the connection. It defaults to space parity, 7 bit characters, and ASCII CR (13) end-of-line character. Beware that the program that \fBagetty\fR starts (usually /bin/login) is run as root. .TP -\-o, \-\-login\-options \fI"login_options"\fP +\-o, \-\-login\-options "\fIlogin_options\fP" Options that are passed to the login program. \\u is replaced by the login name. The default \fB/bin/login\fP command line is "/bin/login -- <username>". @@ -176,11 +187,11 @@ Please read the SECURITY NOTICE below if you want to use this. Wait for any key before dropping to the login prompt. Can be combined with \fB\-\-autologin\fP to save memory by lazily spawning shells. .TP -\-r, \-\-chroot \fI"directory"\fP +\-r, \-\-chroot \fIdirectory\fP Change root to the specified directory. .TP \-R, \-\-hangup -Do call vhangup() for a virtually hangup of the specified terminal. +Call vhangup() to do a virtual hangup of the specified terminal. .TP \-s, \-\-keep\-baud Try to keep the existing baud rate. The baud rates from @@ -188,14 +199,14 @@ the command line are used when agetty receives a BREAK character. .TP \-t, \-\-timeout \fItimeout\fP Terminate if no user name could be read within \fItimeout\fP -seconds. This option should probably not be used with hard-wired +seconds. This option should probably not be used with hardwired lines. .TP \-U, \-\-detect\-case -Turn on support for detecting an uppercase only terminal. This setting will -detect a login name containing only capitals as indicating an uppercase -only terminal and turn on some upper to lower case conversions. Note that -this has no support for any unicode characters. +Turn on support for detecting an uppercase-only terminal. This setting +will detect a login name containing only capitals as indicating an +uppercase-only terminal and turn on some upper-to-lower case conversions. +Note that this has no support for any Unicode characters. .TP \-w, \-\-wait\-cr Wait for the user or the modem to send a carriage-return or a @@ -218,52 +229,60 @@ no hostname at all will be shown. .TP \-\-long\-hostname By default the hostname is only printed until the first dot. With -this option enabled, the full qualified hostname by gethostname() -or if not found by getaddrinfo() is shown. +this option enabled, the fully qualified hostname by gethostname() +or (if not found) by getaddrinfo() is shown. .TP \-\-erase\-chars \fIstring\fP -This option specifies additional chars that should be interpreted as a -backspace (ignore previous char) when user specifies login name. The original -default has been \'#\', since util-linux 2.23 no additional erase chars are -enabled by default. +This option specifies additional characters that should be interpreted as a +backspace ("ignore the previous character") when the user types the login name. +The default additional \'erase\' has been \'#\', but since util-linux 2.23 +no additional erase characters are enabled by default. .TP \-\-kill\-chars \fIstring\fP -This option specifies additional chars that should be interpreted as a -kill (ignore all previous chars) when user specifies login name. The original -default has been \'@\', since util-linux 2.23 no additional erase chars are -enabled by default. +This option specifies additional characters that should be interpreted as a +kill ("ignore all previous characters") when the user types the login name. +The default additional \'kill\' has been \'@\', but since util-linux 2.23 +no additional kill characters are enabled by default. .TP \-\-version -Output version information and exit. +Display version information and exit. .TP \-\-help -Output help screen and exit. +Display help text and exit. .PP .SH EXAMPLES This section shows examples for the process field of an entry in the \fI/etc/inittab\fP file. You'll have to prepend appropriate values for the other fields. See \fIinittab(5)\fP for more details. -For a hard-wired line or a console tty: -.ti +5 +For a hardwired line or a console tty: + +.RS /sbin/agetty 9600 ttyS1 +.RE -For a directly connected terminal without proper carriage detect wiring: +For a directly connected terminal without proper carrier-detect wiring (try this if your terminal just sleeps instead of giving you a password: -prompt.) -.ti +5 +prompt): + +.RS /sbin/agetty \-L 9600 ttyS1 vt100 +.RE + +For an old-style dial-in line with a 9600/2400/1200 baud modem: -For a old style dial-in line with a 9600/2400/1200 baud modem: -.ti +5 +.RS /sbin/agetty \-mt60 ttyS1 9600,2400,1200 +.RE -For a Hayes modem with a fixed 115200 bps interface to the machine: +For a Hayes modem with a fixed 115200 bps interface to the machine (the example init string turns off modem echo and result codes, makes modem/computer DCD track modem/modem DCD, makes a DTR drop cause a -dis-connection and turn on auto-answer after 1 ring.) -.ti +5 +disconnection, and turns on auto-answer after 1 ring): + +.RS /sbin/agetty \-w \-I 'ATE0Q1&D2&C1S0=1\\015' 115200 ttyS1 +.RE .SH SECURITY NOTICE If you use the \fB\-\-login\-program\fP and \fB\-\-login\-options\fP options, @@ -279,9 +298,9 @@ not be interpreted as options. Use this feature if available by passing "\-\-" before the username gets passed by \\u. .SH ISSUE ESCAPES -The issue-file (\fI/etc/issue\fP or the file set with the \-f option) -may contain certain escape codes to display the system name, date and -time etc. All escape codes consist of a backslash (\\) immediately +The issue-file (\fI/etc/issue\fP or the file set with the \fB\-f\fP option) +may contain certain escape codes to display the system name, date, time +etcetera. All escape codes consist of a backslash (\\) immediately followed by one of the letters explained below. .TP @@ -301,6 +320,14 @@ Insert the current date. .TP s Insert the system name, the name of the operating system. Same as `uname \-s'. +See also \\S escape code. +.TP +S or S{VARIABLE} +Insert the VARIABLE data from \fI/etc/os-release\fP. If the VARIABLE argument +is not specified then use PRETTY_NAME from the file or the system name (see \\s). +This escape code allows to keep \fI/etc/issue\fP distribution and release +independent. Note that \\S{ANSI_COLOR} is converted to the real terminal +escape sequence. .TP l Insert the name of the current tty line. @@ -332,41 +359,54 @@ users logged in. .TP v Insert the version of the OS, eg. the build-date etc. -.TP +.PP Example: On my system, the following \fI/etc/issue\fP file: - +.sp .na +.RS .nf -.ti +.5 This is \\n.\\o (\\s \\m \\r) \\t -.TP -displays as - -.ti +.5 +.fi +.RE +.PP +displays as: +.sp +.RS +.nf This is thingol.orcan.dk (Linux i386 1.1.9) 18:29:30 - .fi +.RE .SH FILES .na -.nf -/var/run/utmp, the system status file. -/etc/issue, printed before the login prompt. -/dev/console, problem reports (if syslog(3) is not used). -/etc/inittab, \fIinit\fP(8) configuration file. +.TP +.B /var/run/utmp +the system status file. +.TP +.B /etc/issue +printed before the login prompt. +.TP +.B /etc/os-release +operating system identification data. +.TP +.B /dev/console +problem reports (if syslog(3) is not used). +.TP +.B /etc/inittab +\fIinit\fP(8) configuration file for SysV-style init daemon. .SH BUGS .ad .fi -The baud-rate detection feature (the \fI\-m\fP option) requires that +The baud-rate detection feature (the \fB\-m\fP option) requires that \fBagetty\fP be scheduled soon enough after completion of a dial-in call (within 30 ms with modems that talk at 2400 baud). For robustness, -always use the \fI\-m\fP option in combination with a multiple baud +always use the \fB\-m\fP option in combination with a multiple baud rate command-line argument, so that BREAK processing is enabled. The text in the \fI/etc/issue\fP file (or other) and the login prompt are always output with 7-bit characters and space parity. -The baud-rate detection feature (the \fI\-m\fP option) requires that +The baud-rate detection feature (the \fB\-m\fP option) requires that the modem emits its status message \fIafter\fP raising the DCD line. .SH DIAGNOSTICS .ad @@ -376,19 +416,19 @@ written to the console device or reported via the syslog(3) facility. Error messages are produced if the \fIport\fP argument does not specify a terminal device; if there is no utmp entry for the current process (System V only); and so on. -.SH AUTHOR(S) -.na -.nf -W.Z. Venema <wietse@wzv.win.tue.nl> -Eindhoven University of Technology -Department of Mathematics and Computer Science -Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands - -Peter Orbaek <poe@daimi.aau.dk> -Linux port and more options. Still maintains the code. - -Eric Rasmussen <ear@usfirst.org> -Added \-f option to display custom login messages on different terminals. +.SH AUTHORS +.UR werner@suse.de +Werner Fink +.UE +.br +.UR kzak@redhat.com +Karel Zak +.UE +.sp +The original +.B agetty +for serial terminals was written by W.Z. Venema <wietse@wzv.win.tue.nl> +and ported to Linux by Peter Orbaek <poe@daimi.aau.dk>. .SH AVAILABILITY The agetty command is part of the util-linux package and is available from diff --git a/term-utils/agetty.c b/term-utils/agetty.c index a23cf6dc2..c881f3d4a 100644 --- a/term-utils/agetty.c +++ b/term-utils/agetty.c @@ -49,6 +49,10 @@ # ifndef DEFAULT_VCTERM # define DEFAULT_VCTERM "linux" # endif +# if defined (__s390__) || defined (__s390x__) +# define DEFAULT_TTYS0 "ibm327x" +# define DEFAULT_TTYS1 "vt220" +# endif # ifndef DEFAULT_STERM # define DEFAULT_STERM "vt102" # endif @@ -129,16 +133,24 @@ struct options { char *issue; /* alternative issue file */ char *erasechars; /* string with erase chars */ char *killchars; /* string with kill chars */ + char *osrelease; /* /etc/os-release data */ int delay; /* Sleep seconds before prompt */ int nice; /* Run login with this priority */ int numspeed; /* number of baud rates to try */ + int clocal; /* CLOCAL_MODE_* */ speed_t speeds[MAX_SPEED]; /* baud rates to be tried */ }; +enum { + CLOCAL_MODE_AUTO = 0, + CLOCAL_MODE_ALWAYS, + CLOCAL_MODE_NEVER +}; + #define F_PARSE (1<<0) /* process modem status messages */ #define F_ISSUE (1<<1) /* display /etc/issue */ #define F_RTSCTS (1<<2) /* enable RTS/CTS flow control */ -#define F_LOCAL (1<<3) /* force local */ + #define F_INITSTRING (1<<4) /* initstring is set */ #define F_WAITCRLF (1<<5) /* wait for CR or LF */ #define F_CUSTISSUE (1<<6) /* give alternative issue file */ @@ -180,16 +192,14 @@ static const struct Speedtab speedtab[] = { {2400, B2400}, {4800, B4800}, {9600, B9600}, -#ifdef B19200 +#ifdef B19200 {19200, B19200}, -#endif -#ifdef B38400 - {38400, B38400}, -#endif -#ifdef EXTA +#elif defined(EXTA) {19200, EXTA}, #endif -#ifdef EXTB +#ifdef B38400 + {38400, B38400}, +#elif defined(EXTB) {38400, EXTB}, #endif #ifdef B57600 @@ -201,6 +211,42 @@ static const struct Speedtab speedtab[] = { #ifdef B230400 {230400, B230400}, #endif +#ifdef B460800 + {460800, B460800}, +#endif +#ifdef B500000 + {500000, B500000}, +#endif +#ifdef B576000 + {576000, B576000}, +#endif +#ifdef B921600 + {921600, B921600}, +#endif +#ifdef B1000000 + {1000000, B1000000}, +#endif +#ifdef B1152000 + {1152000, B1152000}, +#endif +#ifdef B1500000 + {1500000, B1500000}, +#endif +#ifdef B2000000 + {2000000, B2000000}, +#endif +#ifdef B2500000 + {2500000, B2500000}, +#endif +#ifdef B3000000 + {3000000, B3000000}, +#endif +#ifdef B3500000 + {3500000, B3500000}, +#endif +#ifdef B4000000 + {4000000, B4000000}, +#endif {0, 0}, }; @@ -235,10 +281,13 @@ static void login_options_to_argv(char *argv[], int *argc, char *str, char *user static char *fakehost; #ifdef DEBUGGING -#define debug(s) do { fprintf(dbf,s); fflush(dbf); } while (0) +# ifndef DEBUG_OUTPUT +# define DEBUG_OUTPUT "/dev/ttyp0" +# endif +# define debug(s) do { fprintf(dbf,s); fflush(dbf); } while (0) FILE *dbf; #else -#define debug(s) do { ; } while (0) +# define debug(s) do { ; } while (0) #endif int main(int argc, char **argv) @@ -270,7 +319,7 @@ int main(int argc, char **argv) sigaction(SIGINT, &sa, &sa_int); #ifdef DEBUGGING - dbf = fopen("/dev/ttyp0", "w"); + dbf = fopen(DEBUG_OUTPUT, "w"); for (int i = 1; i < argc; i++) debug(argv[i]); #endif /* DEBUGGING */ @@ -311,8 +360,10 @@ int main(int argc, char **argv) strlen(options.initstring)); } - if (!serial_tty_option(&options, F_LOCAL)) - /* Go to blocking write mode unless -L is specified. */ + if (options.flags & F_VCONSOLE || options.clocal != CLOCAL_MODE_ALWAYS) + /* Go to blocking mode unless -L is specified, this change + * affects stdout, stdin and stderr as all the file descriptors + * are created by dup(). */ fcntl(STDOUT_FILENO, F_SETFL, fcntl(STDOUT_FILENO, F_GETFL, 0) & ~O_NONBLOCK); @@ -419,6 +470,13 @@ int main(int argc, char **argv) log_warn(_("%s: can't change process priority: %m"), options.tty); } + if (options.osrelease) + free(options.osrelease); +#ifdef DEBUGGING + fprintf(dbf, "read %c\n", ch); + if (close_stream(dbf) != 0) + log_err("write failed: %s", DEBUG_OUTPUT); +#endif /* Let the login program take care of password validation. */ execv(options.login, login_argv); @@ -445,9 +503,11 @@ static char *replace_u(char *str, char *username) } sz = strlen(str); - if (p == str && sz == 2) + if (p == str && sz == 2) { /* 'str' contains only '\u' */ + free(old); return username; + } tp = entry = malloc(sz + usz); if (!tp) @@ -532,7 +592,7 @@ static void parse_args(int argc, char **argv, struct options *op) { "init-string", required_argument, 0, 'I' }, { "noclear", no_argument, 0, 'J' }, { "login-program", required_argument, 0, 'l' }, - { "local-line", no_argument, 0, 'L' }, + { "local-line", optional_argument, 0, 'L' }, { "extract-baud", no_argument, 0, 'm' }, { "skip-login", no_argument, 0, 'n' }, { "nonewline", no_argument, 0, 'N' }, @@ -556,7 +616,7 @@ static void parse_args(int argc, char **argv, struct options *op) }; while ((c = getopt_long(argc, argv, - "8a:cC:d:Ef:hH:iI:Jl:LmnNo:pP:r:Rst:Uw", longopts, + "8a:cC:d:Ef:hH:iI:Jl:L::mnNo:pP:r:Rst:Uw", longopts, NULL)) != -1) { switch (c) { case '8': @@ -601,7 +661,18 @@ static void parse_args(int argc, char **argv, struct options *op) op->login = optarg; break; case 'L': - op->flags |= F_LOCAL; + /* -L and -L=always have the same meaning */ + op->clocal = CLOCAL_MODE_ALWAYS; + if (optarg) { + if (strcmp(optarg, "=always") == 0) + op->clocal = CLOCAL_MODE_ALWAYS; + else if (strcmp(optarg, "=never") == 0) + op->clocal = CLOCAL_MODE_NEVER; + else if (strcmp(optarg, "=auto") == 0) + op->clocal = CLOCAL_MODE_AUTO; + else + log_err(_("invalid argument of --local-line")); + } break; case 'm': op->flags |= F_PARSE; @@ -818,7 +889,11 @@ static void update_utmp(struct options *op) if (fakehost) strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host)); time(&t); +#if defined(_HAVE_UT_TV) + ut.ut_tv.tv_sec = t; +#else ut.ut_time = t; +#endif ut.ut_type = LOGIN_PROCESS; ut.ut_pid = pid; ut.ut_session = sid; @@ -981,6 +1056,20 @@ static void open_tty(char *tty, struct termios *tp, struct options *op) if (tcgetattr(STDIN_FILENO, tp) < 0) log_err(_("%s: failed to get terminal attributes: %m"), tty); +#if defined (__s390__) || defined (__s390x__) + if (!op->term) { + /* + * Special terminal on first serial line on a S/390(x) which + * is due legacy reasons a block terminal of type 3270 or + * higher. Whereas the second serial line on a S/390(x) is + * a real character terminal which is compatible with VT220. + */ + if (strcmp(op->tty, "ttyS0") == 0) + op->term = DEFAULT_TTYS0; + else if (strcmp(op->tty, "ttyS1") == 0) + op->term = DEFAULT_TTYS1; + } +#endif /* * Detect if this is a virtual console or serial/modem line. * In case of a virtual console the ioctl TIOCMGET fails and @@ -1088,8 +1177,19 @@ static void termio_init(struct options *op, struct termios *tp) cfsetispeed(tp, ispeed); cfsetospeed(tp, ospeed); - if (op->flags & F_LOCAL) - tp->c_cflag |= CLOCAL; + /* The default is to follow setting from kernel, but it's possible + * to explicitly remove/add CLOCAL flag by -L[=<mode>]*/ + switch (op->clocal) { + case CLOCAL_MODE_ALWAYS: + tp->c_cflag |= CLOCAL; /* -L or -L=always */ + break; + case CLOCAL_MODE_NEVER: + tp->c_cflag &= ~CLOCAL; /* -L=never */ + break; + case CLOCAL_MODE_AUTO: /* -L=auto */ + break; + } + #ifdef HAVE_STRUCT_TERMIOS_C_LINE tp->c_line = 0; #endif @@ -1237,6 +1337,84 @@ static char *xgetdomainname(void) return NULL; } +static char *read_os_release(struct options *op, const char *varname) +{ + int fd = -1; + struct stat st; + size_t varsz = strlen(varname); + char *p, *buf = NULL, *ret = NULL; + + /* read the file only once */ + if (!op->osrelease) { + fd = open(_PATH_OS_RELEASE, O_RDONLY); + if (fd == -1) { + log_warn(_("cannot open: %s: %m"), _PATH_OS_RELEASE); + return NULL; + } + + if (fstat(fd, &st) < 0 || st.st_size > 4 * 1024 * 1024) + goto done; + + op->osrelease = malloc(st.st_size + 1); + if (!op->osrelease) + log_err(_("failed to allocate memory: %m")); + if (read_all(fd, op->osrelease, st.st_size) != (ssize_t) st.st_size) { + free(op->osrelease); + op->osrelease = NULL; + goto done; + } + op->osrelease[st.st_size] = 0; + } + buf = strdup(op->osrelease); + if (!buf) + log_err(_("failed to allocate memory: %m")); + p = buf; + + for (;;) { + char *eol, *eon; + + p += strspn(p, "\n\r"); + p += strspn(p, " \t\n\r"); + if (!*p) + break; + if (strspn(p, "#;\n") != 0) { + p += strcspn(p, "\n\r"); + continue; + } + if (strncmp(p, varname, varsz) != 0) { + p += strcspn(p, "\n\r"); + continue; + } + p += varsz; + p += strspn(p, " \t\n\r=\""); + eol = p + strcspn(p, "\n\r"); + *eol = '\0'; + eon = eol-1; + while (eon > p) { + if (*eon == '\t' || *eon == ' ') { + eon--; + continue; + } + if (*eon == '"') { + *eon = '\0'; + break; + } + break; + } + if (ret) + free(ret); + ret = strdup(p); + if (!ret) + log_err(_("failed to allocate memory: %m")); + p = eol + 1; + } +done: + free(buf); + if (fd >= 0) + close(fd); + return ret; +} + /* Show login prompt, optionally preceded by /etc/issue contents. */ static void do_prompt(struct options *op, struct termios *tp) { @@ -1410,9 +1588,10 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata if (read(STDIN_FILENO, &c, 1) < 1) { - /* Do not report trivial like EINTR/EIO errors. */ + /* The terminal could be open with O_NONBLOCK when + * -L (force CLOCAL) is specified... */ if (errno == EINTR || errno == EAGAIN) { - usleep(1000); + usleep(250000); continue; } switch (errno) { @@ -1633,8 +1812,8 @@ static speed_t bcode(char *s) static void __attribute__ ((__noreturn__)) usage(FILE *out) { fputs(USAGE_HEADER, out); - fprintf(out, _(" %1$s [options] line baud_rate,... [termtype]\n" - " %1$s [options] baud_rate,... line [termtype]\n"), program_invocation_short_name); + fprintf(out, _(" %1$s [options] <line> [<baud_rate>,...] [<termtype>]\n" + " %1$s [options] <baud_rate>,... <line> [<termtype>]\n"), program_invocation_short_name); fputs(USAGE_OPTIONS, out); fputs(_(" -8, --8bits assume 8-bit tty\n"), out); fputs(_(" -a, --autologin <user> login the specified user automatically\n"), out); @@ -1646,11 +1825,11 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out) fputs(_(" -i, --noissue do not display issue file\n"), out); fputs(_(" -I, --init-string <string> set init string\n"), out); fputs(_(" -l, --login-program <file> specify login program\n"), out); - fputs(_(" -L, --local-line force local line\n"), out); + fputs(_(" -L, --local-line[=<mode>] control the local line flag\n"), out); fputs(_(" -m, --extract-baud extract baud rate during connect\n"), out); fputs(_(" -n, --skip-login do not prompt for login\n"), out); fputs(_(" -o, --login-options <opts> options that are passed to login\n"), out); - fputs(_(" -p, --loginpause wait for any key before the login\n"), out); + fputs(_(" -p, --login-pause wait for any key before the login\n"), out); fputs(_(" -r, --chroot <dir> change root to the directory\n"), out); fputs(_(" -R, --hangup do virtually hangup on the tty\n"), out); fputs(_(" -s, --keep-baud try to keep baud rate after break\n"), out); @@ -1660,7 +1839,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out) fputs(_(" --noclear do not clear the screen before prompt\n"), out); fputs(_(" --nohints do not print hints\n"), out); fputs(_(" --nonewline do not print a newline before issue\n"), out); - fputs(_(" --no-hostname no hostname at all will be shown\n"), out); + fputs(_(" --nohostname no hostname at all will be shown\n"), out); fputs(_(" --long-hostname show full qualified hostname\n"), out); fputs(_(" --erase-chars <string> additional backspace chars\n"), out); fputs(_(" --kill-chars <string> additional kill chars\n"), out); @@ -1925,6 +2104,24 @@ static void output_special_char(unsigned char c, struct options *op, } break; } + case 'S': + { + char *var = NULL, varname[64]; + + if (get_escape_argument(fp, varname, sizeof(varname))) + var = read_os_release(op, varname); + else if (!(var = read_os_release(op, "PRETTY_NAME"))) + var = uts.sysname; + if (var) { + if (strcmp(varname, "ANSI_COLOR") == 0) + printf("\033[%sm", var); + else + printf("%s", var); + if (var != uts.sysname) + free(var); + } + break; + } case 'u': case 'U': { diff --git a/term-utils/mesg.1 b/term-utils/mesg.1 index 60d942339..f7ebf4195 100644 --- a/term-utils/mesg.1 +++ b/term-utils/mesg.1 @@ -73,10 +73,10 @@ Permits messages to be displayed. Explain what is being done. .TP .B \-V, \-\-verbose -Output version information and exit. +Display version information and exit. .TP .B \-h, \-\-help -Output help screen and exit. +Display help text and exit. .PP If no arguments are given, .B mesg diff --git a/term-utils/mesg.c b/term-utils/mesg.c index 430236fac..12e4e0e8c 100644 --- a/term-utils/mesg.c +++ b/term-utils/mesg.c @@ -68,16 +68,16 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out) { - fputs(_("\nUsage:\n"), out); + fputs(USAGE_HEADER, out); /* TRANSLATORS: this program uses for y and n rpmatch(3), * which means they can be translated. */ fprintf(out, _(" %s [options] [y | n]\n"), program_invocation_short_name); - - fputs(_("\nOptions:\n"), out); - fputs(_(" -v, --verbose explain what is being done\n" - " -V, --version output version information and exit\n" - " -h, --help output help screen and exit\n\n"), out); + fputs(USAGE_OPTIONS, out); + fputs(_(" -v, --verbose explain what is being done\n"), out); + fputs(USAGE_HELP, out); + fputs(USAGE_VERSION, out); + fprintf(out, USAGE_MAN_TAIL("mesg(1)")); exit(out == stderr ? MESG_EXIT_FAILURE : EXIT_SUCCESS); } @@ -88,11 +88,6 @@ int main(int argc, char *argv[]) char *tty; int ch, verbose = FALSE; - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - atexit(close_stdout); - static const struct option longopts[] = { { "verbose", no_argument, 0, 'v' }, { "version", no_argument, 0, 'V' }, @@ -100,14 +95,18 @@ int main(int argc, char *argv[]) { NULL, 0, 0, 0 } }; + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); + while ((ch = getopt_long(argc, argv, "vVh", longopts, NULL)) != -1) switch (ch) { case 'v': verbose = TRUE; break; case 'V': - printf(_("%s from %s\n"), program_invocation_short_name, - PACKAGE_STRING); + printf(UTIL_LINUX_VERSION); exit(EXIT_SUCCESS); case 'h': usage(stdout); diff --git a/term-utils/script.1 b/term-utils/script.1 index 1e430d845..60a0e53a0 100644 --- a/term-utils/script.1 +++ b/term-utils/script.1 @@ -93,10 +93,10 @@ field indicates how many characters were output this time. This information can be used to replay typescripts with realistic typing and output delays. .TP \fB\-V\fR, \fB\-\-version\fR -Output version information and exit. +Display version information and exit. .TP \fB\-h\fR, \fB\-\-help\fR -Output help and exit. +Display help text and exit. .SH NOTES The script ends when the forked shell exits (a .I control-D diff --git a/term-utils/script.c b/term-utils/script.c index 242b8154a..89eee94e1 100644 --- a/term-utils/script.c +++ b/term-utils/script.c @@ -58,6 +58,7 @@ #include <limits.h> #include <locale.h> #include <stddef.h> +#include <poll.h> #include "closestream.h" #include "nls.h" @@ -308,7 +309,12 @@ doinput(void) { } } else if (cc < 0 && errno == EINTR && resized) + { + /* transmit window change information to the child */ + ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&win); + ioctl(slave, TIOCSWINSZ, (char *)&win); resized = 0; + } else break; } @@ -322,20 +328,20 @@ void finish(int dummy __attribute__ ((__unused__))) { int status; pid_t pid; + int errsv = errno; while ((pid = wait3(&status, WNOHANG, 0)) > 0) if (pid == child) { childstatus = status; die = 1; } + + errno = errsv; } void resize(int dummy __attribute__ ((__unused__))) { resized = 1; - /* transmit window change information to the child */ - ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&win); - ioctl(slave, TIOCSWINSZ, (char *)&win); } /* @@ -354,9 +360,9 @@ dooutput(FILE *timingfd) { char obuf[BUFSIZ]; struct timeval tv; double oldtime=time(NULL), newtime; - int flgs = 0; ssize_t wrt; ssize_t fwrt; + int errsv = 0; close(STDIN_FILENO); #ifdef HAVE_LIBUTIL @@ -367,25 +373,21 @@ dooutput(FILE *timingfd) { fprintf(fscript, _("Script started on %s"), obuf); do { - if (die && flgs == 0) { - /* ..child is dead, but it doesn't mean that there is - * nothing in buffers. - */ - flgs = fcntl(master, F_GETFL, 0); - if (fcntl(master, F_SETFL, (flgs | O_NONBLOCK)) == -1) + if (die || errsv == EINTR) { + struct pollfd fds[] = {{ .fd = master, .events = POLLIN }}; + if (poll(fds, 1, 50) <= 0) break; } - if (tflg) - gettimeofday(&tv, NULL); errno = 0; cc = read(master, obuf, sizeof (obuf)); + errsv = errno; - if (die && errno == EINTR && cc <= 0) - /* read() has been interrupted by SIGCHLD, try it again - * with O_NONBLOCK - */ - continue; + if (tflg) + gettimeofday(&tv, NULL); + + if (errsv == EINTR && cc <= 0) + continue; /* try it again */ if (cc <= 0) break; if (tflg) { @@ -393,22 +395,23 @@ dooutput(FILE *timingfd) { fprintf(timingfd, "%f %zd\n", newtime - oldtime, cc); oldtime = newtime; } - wrt = write(STDOUT_FILENO, obuf, cc); - if (wrt < 0) { - warn (_("write failed")); - fail(); - } fwrt = fwrite(obuf, 1, cc, fscript); if (fwrt < cc) { warn (_("cannot write script file")); fail(); } - if (fflg) + if (fflg) { fflush(fscript); + if (tflg) + fflush(timingfd); + } + wrt = write(STDOUT_FILENO, obuf, cc); + if (wrt < 0) { + warn (_("write failed")); + fail(); + } } while(1); - if (flgs) - fcntl(master, F_SETFL, flgs); if (close_stream(timingfd) != 0) errx(EXIT_FAILURE, _("write error")); done(); diff --git a/term-utils/scriptreplay.1 b/term-utils/scriptreplay.1 index 343f436cd..20b6d93bc 100644 --- a/term-utils/scriptreplay.1 +++ b/term-utils/scriptreplay.1 @@ -60,7 +60,7 @@ because it divides the timings by this factor. Display version information and exit. .TP .BR \-h , " \-\-help" -Display a help message and exit. +Display help text and exit. .SH "EXAMPLE" .nf % script --timing=file.tm script.out diff --git a/term-utils/scriptreplay.c b/term-utils/scriptreplay.c index 46468be24..260ea84a6 100644 --- a/term-utils/scriptreplay.c +++ b/term-utils/scriptreplay.c @@ -133,7 +133,6 @@ main(int argc, char *argv[]) double divi = 1; int c, diviopt = FALSE, idx; unsigned long line; - size_t oldblk = 0; char ch; static const struct option longopts[] = { @@ -222,9 +221,7 @@ main(int argc, char *argv[]) if (delay > SCRIPT_MIN_DELAY) delay_for(delay); - if (oldblk) - emit(sfile, sname, oldblk); - oldblk = blk; + emit(sfile, sname, blk); } fclose(sfile); diff --git a/term-utils/setterm.1 b/term-utils/setterm.1 index cde41143a..9f5b2292d 100644 --- a/term-utils/setterm.1 +++ b/term-utils/setterm.1 @@ -101,7 +101,7 @@ Turns the terminal's cursor on or off. Sets the terminal's rendering options to the default values. .TP .BR \-dump " [\fI1-NR_CONS\fP]" -Writes a snapshot of the given virtual console (with attributes) to the file +Writes a snapshot of the given virtual console to the file specified in the \fB\-file\fP option, overwriting its contents; the default is screen.dump. Without an argument, dumps the current virtual console. Overrides \fB\-append\fP. @@ -180,10 +180,10 @@ Overrides the TERM environment variable. Sets the color for underlined characters. .TP .BR \-version -Output version information and exit. +Display version information and exit. .TP .BR \-help -Output help screen and exit. +Display help text and exit. .SH "SEE ALSO" .BR tput (1), .BR stty (1), diff --git a/term-utils/setterm.c b/term-utils/setterm.c index 310c3fab0..f179ea8ac 100644 --- a/term-utils/setterm.c +++ b/term-utils/setterm.c @@ -100,16 +100,17 @@ #include <termios.h> #include <string.h> #include <fcntl.h> + #ifndef NCURSES_CONST #define NCURSES_CONST const /* define before including term.h */ #endif -#include <term.h> - #ifdef HAVE_NCURSES_H #include <ncurses.h> #elif defined(HAVE_NCURSES_NCURSES_H) #include <ncurses/ncurses.h> #endif +/* must include after ncurses.h */ +#include <term.h> #include <sys/param.h> /* for MAXPATHLEN */ #include <sys/ioctl.h> @@ -123,7 +124,7 @@ #include "nls.h" #include "closestream.h" -#if __GNU_LIBRARY__ < 5 +#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 5 #ifndef __alpha__ # include <linux/unistd.h> #define __NR_klogctl __NR_syslog diff --git a/term-utils/ttymsg.c b/term-utils/ttymsg.c index 66b61b491..8bf993c2f 100644 --- a/term-utils/ttymsg.c +++ b/term-utils/ttymsg.c @@ -41,6 +41,7 @@ */ #include <sys/types.h> +#include <sys/param.h> #include <sys/uio.h> #include <signal.h> #include <fcntl.h> @@ -169,7 +170,8 @@ ttymsg(struct iovec *iov, size_t iovcnt, char *line, int tmout) { */ if (errno == ENODEV || errno == EIO) break; - (void) close(fd); + if (close_fd(fd) != 0) + warn(_("write failed: %s"), device); if (forked) _exit(EXIT_FAILURE); if (strlen(strerror(errno)) > 1000) @@ -184,7 +186,6 @@ ttymsg(struct iovec *iov, size_t iovcnt, char *line, int tmout) { return (errbuf); } - (void) close(fd); if (forked) _exit(EXIT_SUCCESS); return (NULL); diff --git a/term-utils/wall.1 b/term-utils/wall.1 index 88e816cdc..65f0ee8ce 100644 --- a/term-utils/wall.1 +++ b/term-utils/wall.1 @@ -33,43 +33,54 @@ .\" .\" Modified for Linux, Mon Mar 8 18:07:38 1993, faith@cs.unc.edu .\" -.TH WALL "1" "September 2011" "util-linux" "User Commands" +.TH WALL "1" "August 2013" "util-linux" "User Commands" .SH NAME wall \- write a message to users .SH SYNOPSIS .B wall -[-n] [-t TIMEOUT] [file] +.RB [ \-n ] +.RB [ \-t +.IR timeout ] +.RI [ message " | " file ] .SH DESCRIPTION -.B Wall -displays the contents of +.B wall +displays a +.I message +or the contents of a .I file or, by default, its standard input, on the terminals of all currently logged -in users. The command will cut over 79 character long lines to new lines. -Short lines are white space padded to have 79 characters. The command will -always put carriage return and new line at the end of each line. +in users. The command will wrap lines that are longer than 79 characters. +Short lines are whitespace padded to have 79 characters. The command will +always put a carriage return and new line at the end of each line. .PP -Only the super-user can write on the terminals of users who have chosen to +Only the superuser can write on the terminals of users who have chosen to deny messages or are using a program which automatically denies messages. .PP -Reading from a file is refused when the invoker is not superuser and the -program is suid or sgid. +Reading from a +.I file +is refused when the invoker is not superuser and the program is suid or sgid. .SH OPTIONS .TP -\fB\-n\fR, \fB\-\-nobanner\fR -Suppress banner +.BR \-n , " \-\-nobanner" +Suppress the banner. .TP -\fB\-t\fR, \fB\-\-timeout\fR \fItimeout\fR -Write -.I timeout -to terminals in seconds. Argument must be positive integer. Default value -is 300 seconds, which is a legacy from time when people ran terminals over +.BR \-t , " \-\-timeout " \fItimeout\fR +Abandon the write attempt to the terminals after \fItimeout\fR seconds. +This \fItimeout\fR must be a positive integer. The default value +is 300 seconds, which is a legacy from the time when people ran terminals over modem lines. .TP -\fB\-V\fR, \fB\-\-version\fR -Output version and exit. +.BR \-V , " \-\-version" +Display version information and exit. .TP -\fB\-h\fR, \fB\-\-help\fR -Output help and exit. +.BR \-h , " \-\-help" +Display help text and exit. +.SH NOTES +Some sessions, such as wdm, that have in the beginning of +.BR utmp (5) +ut_type data a ':' character will not get the message from +.BR wall . +This is done to avoid write errors. .SH SEE ALSO .BR mesg (1), .BR talk (1), diff --git a/term-utils/wall.c b/term-utils/wall.c index 4865ac7a1..20a2891f2 100644 --- a/term-utils/wall.c +++ b/term-utils/wall.c @@ -69,39 +69,41 @@ #include "fileutils.h" #include "closestream.h" -#define IGNOREUSER "sleeper" #define WRITE_TIME_OUT 300 /* in seconds */ /* Function prototypes */ -char *makemsg(char *fname, size_t *mbufsize, int print_banner); -static void usage(FILE *out); +static char *makemsg(char *fname, char **mvec, int mvecsz, + size_t *mbufsize, int print_banner); static void __attribute__((__noreturn__)) usage(FILE *out) { - fputs(_("\nUsage:\n"), out); + fputs(USAGE_HEADER, out); fprintf(out, - _(" %s [options] [<file>]\n"),program_invocation_short_name); - - fputs(_("\nOptions:\n"), out); - fputs(_(" -n, --nobanner do not print banner, works only for root\n" - " -t, --timeout <timeout> write timeout in seconds\n" - " -V, --version output version information and exit\n" - " -h, --help display this help and exit\n\n"), out); + _(" %s [options] [<file> | <message>]\n"), program_invocation_short_name); + fputs(USAGE_OPTIONS, out); + fputs(_(" -n, --nobanner do not print banner, works only for root\n"), out); + fputs(_(" -t, --timeout <timeout> write timeout in seconds\n"), out); + fputs(USAGE_SEPARATOR, out); + fputs(USAGE_HELP, out); + fputs(USAGE_VERSION, out); + fprintf(out, USAGE_MAN_TAIL("wall(1)")); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } -int -main(int argc, char **argv) { +int main(int argc, char **argv) +{ int ch; struct iovec iov; struct utmp *utmpptr; char *p; char line[sizeof(utmpptr->ut_line) + 1]; int print_banner = TRUE; - char *mbuf; + char *mbuf, *fname = NULL; size_t mbufsize; unsigned timeout = WRITE_TIME_OUT; + char **mvec = NULL; + int mvecsz = 0; static const struct option longopts[] = { { "nobanner", no_argument, 0, 'n' }, @@ -130,8 +132,7 @@ main(int argc, char **argv) { errx(EXIT_FAILURE, _("invalid timeout argument: %s"), optarg); break; case 'V': - printf(_("%s from %s\n"), program_invocation_short_name, - PACKAGE_STRING); + printf(UTIL_LINUX_VERSION); exit(EXIT_SUCCESS); case 'h': usage(stdout); @@ -141,23 +142,25 @@ main(int argc, char **argv) { } argc -= optind; argv += optind; - if (argc > 1) - usage(stderr); - mbuf = makemsg(*argv, &mbufsize, print_banner); + if (argc == 1 && access(argv[0], F_OK) == 0) + fname = argv[0]; + else if (argc >= 1) { + mvec = argv; + mvecsz = argc; + } + + mbuf = makemsg(fname, mvec, mvecsz, &mbufsize, print_banner); iov.iov_base = mbuf; iov.iov_len = mbufsize; while((utmpptr = getutent())) { - if (!utmpptr->ut_name[0] || - !strncmp(utmpptr->ut_name, IGNOREUSER, - sizeof(utmpptr->ut_name))) + if (!utmpptr->ut_user[0]) continue; #ifdef USER_PROCESS if (utmpptr->ut_type != USER_PROCESS) continue; #endif - /* Joey Hess reports that use-sessreg in /etc/X11/wdm/ produces ut_line entries like :0, and a write to /dev/:0 fails. */ @@ -173,16 +176,13 @@ main(int argc, char **argv) { exit(EXIT_SUCCESS); } -char * -makemsg(char *fname, size_t *mbufsize, int print_banner) +static char *makemsg(char *fname, char **mvec, int mvecsz, + size_t *mbufsize, int print_banner) { register int ch, cnt; - struct tm *lt; - struct passwd *pw; struct stat sbuf; - time_t now; FILE *fp; - char *p, *whom, *where, *lbuf, *tmpname, *mbuf; + char *p, *lbuf, *tmpname, *mbuf; long line_max; line_max = sysconf(_SC_LINE_MAX); @@ -195,6 +195,10 @@ makemsg(char *fname, size_t *mbufsize, int print_banner) if (print_banner == TRUE) { char *hostname = xgethostname(); + char *whom, *where, *date; + struct passwd *pw; + time_t now; + if (!(whom = getlogin()) || !*whom) whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; if (!whom) { @@ -205,9 +209,12 @@ makemsg(char *fname, size_t *mbufsize, int print_banner) if (!where) { where = "somewhere"; warn(_("cannot get tty name")); - } + } else if (strncmp(where, "/dev/", 5) == 0) + where += 5; + time(&now); - lt = localtime(&now); + date = xstrdup(ctime(&now)); + date[strlen(date) - 1] = '\0'; /* * all this stuff is to blank out a square for the message; @@ -219,44 +226,66 @@ makemsg(char *fname, size_t *mbufsize, int print_banner) /* snprintf is not always available, but the sprintf's here will not overflow as long as %d takes at most 100 chars */ fprintf(fp, "\r%79s\r\n", " "); - sprintf(lbuf, _("Broadcast Message from %s@%s"), - whom, hostname); - free(hostname); + sprintf(lbuf, _("Broadcast message from %s@%s (%s) (%s):"), + whom, hostname, where, date); fprintf(fp, "%-79.79s\007\007\r\n", lbuf); - sprintf(lbuf, " (%s) at %d:%02d ...", - where, lt->tm_hour, lt->tm_min); - fprintf(fp, "%-79.79s\r\n", lbuf); + free(hostname); + free(date); } fprintf(fp, "%79s\r\n", " "); + if (mvec) { + /* + * Read message from argv[] + */ + int i; - if (fname) { + for (i = 0; i < mvecsz; i++) { + fputs(mvec[i], fp); + if (i < mvecsz - 1) + fputc(' ', fp); + } + fputc('\r', fp); + fputc('\n', fp); + + } else { /* - * When we are not root, but suid or sgid, refuse to read files - * (e.g. device files) that the user may not have access to. - * After all, our invoker can easily do "wall < file" - * instead of "wall file". + * read message from <file> */ - uid_t uid = getuid(); - if (uid && (uid != geteuid() || getgid() != getegid())) - errx(EXIT_FAILURE, _("will not read %s - use stdin."), - fname); + if (fname) { + /* + * When we are not root, but suid or sgid, refuse to read files + * (e.g. device files) that the user may not have access to. + * After all, our invoker can easily do "wall < file" + * instead of "wall file". + */ + uid_t uid = getuid(); + if (uid && (uid != geteuid() || getgid() != getegid())) + errx(EXIT_FAILURE, _("will not read %s - use stdin."), + fname); - if (!freopen(fname, "r", stdin)) - err(EXIT_FAILURE, _("cannot open %s"), fname); - } + if (!freopen(fname, "r", stdin)) + err(EXIT_FAILURE, _("cannot open %s"), fname); - while (fgets(lbuf, line_max, stdin)) { - for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) { - if (cnt == 79 || ch == '\n') { - for (; cnt < 79; ++cnt) - putc(' ', fp); - putc('\r', fp); - putc('\n', fp); - cnt = 0; + } + + /* + * Read message from stdin. + */ + while (fgets(lbuf, line_max, stdin)) { + for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) { + if (cnt == 79 || ch == '\n') { + for (; cnt < 79; ++cnt) + putc(' ', fp); + putc('\r', fp); + putc('\n', fp); + cnt = 0; + } + if (ch == '\t') + cnt += (7 - (cnt % 8)); + if (ch != '\n') + carefulputc(ch, fp, '^'); } - if (ch != '\n') - carefulputc(ch, fp); } } fprintf(fp, "%79s\r\n", " "); diff --git a/term-utils/write.1 b/term-utils/write.1 index b60657518..33eb91408 100644 --- a/term-utils/write.1 +++ b/term-utils/write.1 @@ -66,7 +66,7 @@ user will see the message .B EOF indicating that the conversation is over. .PP -You can prevent people (other than the super-user) from writing to you with +You can prevent people (other than the superuser) from writing to you with the .BR mesg (1) command. Some commands, for example diff --git a/term-utils/write.c b/term-utils/write.c index 83937d3b3..f5ca34108 100644 --- a/term-utils/write.c +++ b/term-utils/write.c @@ -73,7 +73,7 @@ static void __attribute__ ((__noreturn__)) done(int); int term_chk(char *, int *, time_t *, int); int utmp_chk(char *, char *); -static gid_t myegid; +static gid_t root_access; static void __attribute__ ((__noreturn__)) usage(FILE * out) { @@ -120,7 +120,7 @@ int main(int argc, char **argv) usage(stderr); } - myegid = getegid(); + root_access = !getegid(); /* check that sender has write enabled */ if (isatty(fileno(stdin))) @@ -201,7 +201,7 @@ int utmp_chk(char *user, char *tty) while ((uptr = getutent())) { memcpy(&u, uptr, sizeof(u)); - if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0 && + if (strncmp(user, u.ut_user, sizeof(u.ut_user)) == 0 && strncmp(tty, u.ut_line, sizeof(u.ut_line)) == 0) { res = 0; break; @@ -239,7 +239,7 @@ void search_utmp(char *user, char *tty, char *mytty, uid_t myuid) user_is_me = 0; while ((uptr = getutent())) { memcpy(&u, uptr, sizeof(u)); - if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) { + if (strncmp(user, u.ut_user, sizeof(u.ut_user)) == 0) { ++nloggedttys; strncpy(atty, u.ut_line, sizeof(u.ut_line)); atty[sizeof(u.ut_line)] = '\0'; @@ -299,8 +299,9 @@ int term_chk(char *tty, int *msgsokP, time_t * atimeP, int showerror) return 1; } - /* group write bit and group ownership */ - *msgsokP = (s.st_mode & (S_IWRITE >> 3)) && myegid == s.st_gid; + *msgsokP = !access(path, W_OK); + if (!root_access && *msgsokP) + *msgsokP = s.st_mode & S_IWGRP; *atimeP = s.st_atime; return 0; } @@ -372,7 +373,7 @@ void wr_fputs(char *s) { char c; -#define PUTC(c) if (carefulputc(c, stdout) == EOF) \ +#define PUTC(c) if (carefulputc(c, stdout, '^') == EOF) \ err(EXIT_FAILURE, _("carefulputc failed")); while (*s) { c = *s++; |
