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
@ -59,26 +59,23 @@ static const char rcsid[] =
|
||||
* ignored (exclusive-use, lack of permission, etc.).
|
||||
*/
|
||||
char *
|
||||
ttymsg(iov, iovcnt, line, tmout)
|
||||
struct iovec *iov;
|
||||
int iovcnt;
|
||||
char *line;
|
||||
int tmout;
|
||||
ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
|
||||
{
|
||||
struct iovec localiov[7];
|
||||
int cnt, fd, left, wret;
|
||||
static char device[MAXNAMLEN] = _PATH_DEV;
|
||||
static char errbuf[1024];
|
||||
register int cnt, fd, left, wret;
|
||||
struct iovec localiov[7];
|
||||
int forked = 0;
|
||||
int forked;
|
||||
|
||||
forked = 0;
|
||||
if (iovcnt > sizeof(localiov) / sizeof(localiov[0]))
|
||||
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, '/')) {
|
||||
/* A slash is an attempt to break security... */
|
||||
(void) snprintf(errbuf, sizeof(errbuf), "'/' in \"%s\"",
|
||||
device);
|
||||
(void) snprintf(errbuf, sizeof(errbuf),
|
||||
"Too many '/' in \"%s\"", device);
|
||||
return (errbuf);
|
||||
}
|
||||
|
||||
@ -89,8 +86,8 @@ ttymsg(iov, iovcnt, line, tmout)
|
||||
if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
|
||||
if (errno == EBUSY || errno == EACCES)
|
||||
return (NULL);
|
||||
(void) snprintf(errbuf, sizeof(errbuf),
|
||||
"%s: %s", device, strerror(errno));
|
||||
(void) snprintf(errbuf, sizeof(errbuf), "%s: %s", device,
|
||||
strerror(errno));
|
||||
return (errbuf);
|
||||
}
|
||||
|
||||
@ -104,7 +101,7 @@ ttymsg(iov, iovcnt, line, tmout)
|
||||
if (wret >= 0) {
|
||||
left -= wret;
|
||||
if (iov != localiov) {
|
||||
bcopy(iov, localiov,
|
||||
bcopy(iov, localiov,
|
||||
iovcnt * sizeof(struct iovec));
|
||||
iov = localiov;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
.Nd write a message to users
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl g Ar group
|
||||
.Op Ar file
|
||||
.Sh DESCRIPTION
|
||||
.Nm Wall
|
||||
@ -52,6 +53,12 @@ Only the super-user can write on the
|
||||
terminals of users who have chosen
|
||||
to deny messages or are using a program which
|
||||
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
|
||||
.Xr mesg 1 ,
|
||||
.Xr talk 1 ,
|
||||
|
@ -56,6 +56,7 @@ static const char rcsid[] =
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <grp.h>
|
||||
#include <locale.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
@ -66,38 +67,54 @@ static const char rcsid[] =
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
void makemsg __P((char *));
|
||||
static void usage __P((void));
|
||||
char *ttymsg __P((struct iovec *, int, char *, int));
|
||||
static void makemsg(char *);
|
||||
static void usage(void);
|
||||
char *ttymsg(struct iovec *, int, const char *, int);
|
||||
|
||||
#define IGNOREUSER "sleeper"
|
||||
|
||||
struct wallgroup {
|
||||
struct wallgroup *next;
|
||||
char *name;
|
||||
gid_t gid;
|
||||
} *grouplist;
|
||||
int nobanner;
|
||||
int mbufsize;
|
||||
char *mbuf;
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch;
|
||||
struct iovec iov;
|
||||
struct utmp utmp;
|
||||
gid_t grps[NGROUPS_MAX];
|
||||
int ch;
|
||||
int ingroup, ngrps, i;
|
||||
FILE *fp;
|
||||
struct wallgroup *g;
|
||||
struct group *grp;
|
||||
char *p;
|
||||
struct passwd *pw;
|
||||
char line[sizeof(utmp.ut_line) + 1];
|
||||
char username[sizeof(utmp.ut_name) + 1];
|
||||
|
||||
ingroup = 0;
|
||||
(void)setlocale(LC_CTYPE, "");
|
||||
|
||||
while ((ch = getopt(argc, argv, "n")) != -1)
|
||||
while ((ch = getopt(argc, argv, "g:n")) != -1)
|
||||
switch (ch) {
|
||||
case 'n':
|
||||
/* undoc option for shutdown: suppress banner */
|
||||
if (geteuid() == 0)
|
||||
nobanner = 1;
|
||||
break;
|
||||
case 'g':
|
||||
g = (struct wallgroup *)malloc(sizeof *g);
|
||||
g->next = grouplist;
|
||||
g->name = optarg;
|
||||
g->gid = -1;
|
||||
grouplist = g;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@ -107,6 +124,12 @@ main(argc, argv)
|
||||
if (argc > 1)
|
||||
usage();
|
||||
|
||||
for (g = grouplist; g; g = g->next) {
|
||||
grp = getgrnam(g->name);
|
||||
if (grp)
|
||||
g->gid = grp->gr_gid;
|
||||
}
|
||||
|
||||
makemsg(*argv);
|
||||
|
||||
if (!(fp = fopen(_PATH_UTMP, "r")))
|
||||
@ -118,6 +141,24 @@ main(argc, argv)
|
||||
if (!utmp.ut_name[0] ||
|
||||
!strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name)))
|
||||
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));
|
||||
line[sizeof(utmp.ut_line)] = '\0';
|
||||
if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL)
|
||||
@ -134,11 +175,10 @@ usage()
|
||||
}
|
||||
|
||||
void
|
||||
makemsg(fname)
|
||||
char *fname;
|
||||
makemsg(char *fname)
|
||||
{
|
||||
register int cnt;
|
||||
register unsigned char ch;
|
||||
int cnt;
|
||||
unsigned char ch;
|
||||
struct tm *lt;
|
||||
struct passwd *pw;
|
||||
struct stat sbuf;
|
||||
|
Loading…
Reference in New Issue
Block a user