o Add support for wall -g. This will send a message to all members of
a given group. o Minor code style cleanups while I'm here Reviewed by: bde, kris, markm, audit@
This commit is contained in:
parent
45d8008748
commit
6a20d55a59
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=73255
@ -59,26 +59,23 @@ static const char rcsid[] =
|
|||||||
* ignored (exclusive-use, lack of permission, etc.).
|
* ignored (exclusive-use, lack of permission, etc.).
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
ttymsg(iov, iovcnt, line, tmout)
|
ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
|
||||||
struct iovec *iov;
|
|
||||||
int iovcnt;
|
|
||||||
char *line;
|
|
||||||
int tmout;
|
|
||||||
{
|
{
|
||||||
|
struct iovec localiov[7];
|
||||||
|
int cnt, fd, left, wret;
|
||||||
static char device[MAXNAMLEN] = _PATH_DEV;
|
static char device[MAXNAMLEN] = _PATH_DEV;
|
||||||
static char errbuf[1024];
|
static char errbuf[1024];
|
||||||
register int cnt, fd, left, wret;
|
int forked;
|
||||||
struct iovec localiov[7];
|
|
||||||
int forked = 0;
|
|
||||||
|
|
||||||
|
forked = 0;
|
||||||
if (iovcnt > sizeof(localiov) / sizeof(localiov[0]))
|
if (iovcnt > sizeof(localiov) / sizeof(localiov[0]))
|
||||||
return ("too many iov's (change code in wall/ttymsg.c)");
|
return ("too many iov's (change code in wall/ttymsg.c)");
|
||||||
|
|
||||||
(void) strcpy(device + sizeof(_PATH_DEV) - 1, line);
|
strlcat(device, line, sizeof(device));
|
||||||
if (strchr(device + sizeof(_PATH_DEV) - 1, '/')) {
|
if (strchr(device + sizeof(_PATH_DEV) - 1, '/')) {
|
||||||
/* A slash is an attempt to break security... */
|
/* A slash is an attempt to break security... */
|
||||||
(void) snprintf(errbuf, sizeof(errbuf), "'/' in \"%s\"",
|
(void) snprintf(errbuf, sizeof(errbuf),
|
||||||
device);
|
"Too many '/' in \"%s\"", device);
|
||||||
return (errbuf);
|
return (errbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,8 +86,8 @@ ttymsg(iov, iovcnt, line, tmout)
|
|||||||
if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
|
if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
|
||||||
if (errno == EBUSY || errno == EACCES)
|
if (errno == EBUSY || errno == EACCES)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
(void) snprintf(errbuf, sizeof(errbuf),
|
(void) snprintf(errbuf, sizeof(errbuf), "%s: %s", device,
|
||||||
"%s: %s", device, strerror(errno));
|
strerror(errno));
|
||||||
return (errbuf);
|
return (errbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +101,7 @@ ttymsg(iov, iovcnt, line, tmout)
|
|||||||
if (wret >= 0) {
|
if (wret >= 0) {
|
||||||
left -= wret;
|
left -= wret;
|
||||||
if (iov != localiov) {
|
if (iov != localiov) {
|
||||||
bcopy(iov, localiov,
|
bcopy(iov, localiov,
|
||||||
iovcnt * sizeof(struct iovec));
|
iovcnt * sizeof(struct iovec));
|
||||||
iov = localiov;
|
iov = localiov;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
.Nd write a message to users
|
.Nd write a message to users
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
|
.Op Fl g Ar group
|
||||||
.Op Ar file
|
.Op Ar file
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm Wall
|
.Nm Wall
|
||||||
@ -52,6 +53,12 @@ Only the super-user can write on the
|
|||||||
terminals of users who have chosen
|
terminals of users who have chosen
|
||||||
to deny messages or are using a program which
|
to deny messages or are using a program which
|
||||||
automatically denies messages.
|
automatically denies messages.
|
||||||
|
.Bl -tag -width indent
|
||||||
|
.It Fl g
|
||||||
|
Send messages to users in this group. This option may be specified
|
||||||
|
multiple times, and any user in any of the specified groups will
|
||||||
|
receive the message.
|
||||||
|
.El
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr mesg 1 ,
|
.Xr mesg 1 ,
|
||||||
.Xr talk 1 ,
|
.Xr talk 1 ,
|
||||||
|
@ -56,6 +56,7 @@ static const char rcsid[] =
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <grp.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
@ -66,38 +67,54 @@ static const char rcsid[] =
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utmp.h>
|
#include <utmp.h>
|
||||||
|
|
||||||
void makemsg __P((char *));
|
static void makemsg(char *);
|
||||||
static void usage __P((void));
|
static void usage(void);
|
||||||
char *ttymsg __P((struct iovec *, int, char *, int));
|
char *ttymsg(struct iovec *, int, const char *, int);
|
||||||
|
|
||||||
#define IGNOREUSER "sleeper"
|
#define IGNOREUSER "sleeper"
|
||||||
|
|
||||||
|
struct wallgroup {
|
||||||
|
struct wallgroup *next;
|
||||||
|
char *name;
|
||||||
|
gid_t gid;
|
||||||
|
} *grouplist;
|
||||||
int nobanner;
|
int nobanner;
|
||||||
int mbufsize;
|
int mbufsize;
|
||||||
char *mbuf;
|
char *mbuf;
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
int
|
int
|
||||||
main(argc, argv)
|
main(int argc, char *argv[])
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
{
|
{
|
||||||
int ch;
|
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
struct utmp utmp;
|
struct utmp utmp;
|
||||||
|
gid_t grps[NGROUPS_MAX];
|
||||||
|
int ch;
|
||||||
|
int ingroup, ngrps, i;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
struct wallgroup *g;
|
||||||
|
struct group *grp;
|
||||||
char *p;
|
char *p;
|
||||||
|
struct passwd *pw;
|
||||||
char line[sizeof(utmp.ut_line) + 1];
|
char line[sizeof(utmp.ut_line) + 1];
|
||||||
|
char username[sizeof(utmp.ut_name) + 1];
|
||||||
|
|
||||||
|
ingroup = 0;
|
||||||
(void)setlocale(LC_CTYPE, "");
|
(void)setlocale(LC_CTYPE, "");
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "n")) != -1)
|
while ((ch = getopt(argc, argv, "g:n")) != -1)
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'n':
|
case 'n':
|
||||||
/* undoc option for shutdown: suppress banner */
|
/* undoc option for shutdown: suppress banner */
|
||||||
if (geteuid() == 0)
|
if (geteuid() == 0)
|
||||||
nobanner = 1;
|
nobanner = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'g':
|
||||||
|
g = (struct wallgroup *)malloc(sizeof *g);
|
||||||
|
g->next = grouplist;
|
||||||
|
g->name = optarg;
|
||||||
|
g->gid = -1;
|
||||||
|
grouplist = g;
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
@ -107,6 +124,12 @@ main(argc, argv)
|
|||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
for (g = grouplist; g; g = g->next) {
|
||||||
|
grp = getgrnam(g->name);
|
||||||
|
if (grp)
|
||||||
|
g->gid = grp->gr_gid;
|
||||||
|
}
|
||||||
|
|
||||||
makemsg(*argv);
|
makemsg(*argv);
|
||||||
|
|
||||||
if (!(fp = fopen(_PATH_UTMP, "r")))
|
if (!(fp = fopen(_PATH_UTMP, "r")))
|
||||||
@ -118,6 +141,24 @@ main(argc, argv)
|
|||||||
if (!utmp.ut_name[0] ||
|
if (!utmp.ut_name[0] ||
|
||||||
!strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name)))
|
!strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name)))
|
||||||
continue;
|
continue;
|
||||||
|
if (grouplist) {
|
||||||
|
strlcpy(username, utmp.ut_name, sizeof(utmp.ut_name));
|
||||||
|
pw = getpwnam(username);
|
||||||
|
if (!pw)
|
||||||
|
continue;
|
||||||
|
ngrps = getgroups(pw->pw_gid, grps);
|
||||||
|
for (g = grouplist; g && ingroup == 0; g = g->next) {
|
||||||
|
if (g->gid == -1)
|
||||||
|
continue;
|
||||||
|
if (g->gid == pw->pw_gid)
|
||||||
|
ingroup = 1;
|
||||||
|
for (i = 0; i < ngrps && ingroup == 0; i++)
|
||||||
|
if (g->gid == grps[i])
|
||||||
|
ingroup = 1;
|
||||||
|
}
|
||||||
|
if (ingroup == 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
strncpy(line, utmp.ut_line, sizeof(utmp.ut_line));
|
strncpy(line, utmp.ut_line, sizeof(utmp.ut_line));
|
||||||
line[sizeof(utmp.ut_line)] = '\0';
|
line[sizeof(utmp.ut_line)] = '\0';
|
||||||
if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL)
|
if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL)
|
||||||
@ -134,11 +175,10 @@ usage()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
makemsg(fname)
|
makemsg(char *fname)
|
||||||
char *fname;
|
|
||||||
{
|
{
|
||||||
register int cnt;
|
int cnt;
|
||||||
register unsigned char ch;
|
unsigned char ch;
|
||||||
struct tm *lt;
|
struct tm *lt;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct stat sbuf;
|
struct stat sbuf;
|
||||||
|
Loading…
Reference in New Issue
Block a user