wall: allow to specify <message> on command line
wall(1) from sysvinit supports # wall I love this company! semantic, This patch add this functionally to the util-linux wall. Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
e781a04fec
commit
cdd3cc7fa4
|
@ -33,15 +33,17 @@
|
|||
.\"
|
||||
.\" 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]
|
||||
[-n] [-t TIMEOUT] [file | message]
|
||||
.SH DESCRIPTION
|
||||
.B Wall
|
||||
displays the contents of
|
||||
displays a
|
||||
.I message
|
||||
or contents of
|
||||
.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.
|
||||
|
@ -51,8 +53,9 @@ always put carriage return and new line at the end of each line.
|
|||
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
|
||||
|
|
|
@ -73,14 +73,15 @@
|
|||
#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);
|
||||
fprintf(out,
|
||||
_(" %s [options] [<file>]\n"),program_invocation_short_name);
|
||||
_(" %s [options] [<file> | <message>]\n"),
|
||||
program_invocation_short_name);
|
||||
|
||||
fputs(_("\nOptions:\n"), out);
|
||||
fputs(_(" -n, --nobanner do not print banner, works only for root\n"
|
||||
|
@ -99,9 +100,11 @@ main(int argc, char **argv) {
|
|||
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' },
|
||||
|
@ -141,10 +144,15 @@ 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;
|
||||
|
@ -173,8 +181,7 @@ 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;
|
||||
|
@ -229,34 +236,56 @@ makemsg(char *fname, size_t *mbufsize, int print_banner)
|
|||
}
|
||||
fprintf(fp, "%79s\r\n", " ");
|
||||
|
||||
|
||||
if (fname) {
|
||||
if (mvec) {
|
||||
/*
|
||||
* 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 argv[]
|
||||
*/
|
||||
uid_t uid = getuid();
|
||||
if (uid && (uid != geteuid() || getgid() != getegid()))
|
||||
errx(EXIT_FAILURE, _("will not read %s - use stdin."),
|
||||
fname);
|
||||
int i;
|
||||
|
||||
if (!freopen(fname, "r", stdin))
|
||||
err(EXIT_FAILURE, _("cannot open %s"), fname);
|
||||
}
|
||||
for (i = 0; i < mvecsz; i++) {
|
||||
fputs(mvec[i], fp);
|
||||
if (i < mvecsz - 1)
|
||||
fputc(' ', fp);
|
||||
}
|
||||
fputc('\r', fp);
|
||||
fputc('\n', fp);
|
||||
|
||||
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;
|
||||
} else {
|
||||
/*
|
||||
* read message from <file>
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 != '\n')
|
||||
carefulputc(ch, fp);
|
||||
}
|
||||
if (ch != '\n')
|
||||
carefulputc(ch, fp);
|
||||
}
|
||||
}
|
||||
fprintf(fp, "%79s\r\n", " ");
|
||||
|
|
Loading…
Reference in New Issue