142 lines
3.3 KiB
C
142 lines
3.3 KiB
C
/*
|
|
* wall.c - Broadcast a message to all users.
|
|
*
|
|
* This program is not related to David Wall, whose Stanford Ph.D. thesis
|
|
* is entitled "Mechanisms for Broadcast and Selective Broadcast".
|
|
*
|
|
* Copyright (c) 1980 Regents of the University of California.
|
|
* All rights reserved. The Berkeley software License Agreement
|
|
* specifies the terms and conditions for redistribution.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <utmp.h>
|
|
#include <paths.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <sys/time.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#define IGNOREUSER "sleeper"
|
|
|
|
char hostname[32];
|
|
char mesg[3000];
|
|
int msize,sline;
|
|
struct utmp *utmp;
|
|
char who[UT_NAMESIZE + 1] = "???";
|
|
long clock;
|
|
struct tm *localclock;
|
|
|
|
extern errno;
|
|
|
|
main(argc, argv)
|
|
char *argv[];
|
|
{
|
|
register int i, c;
|
|
register struct utmp *p;
|
|
int f;
|
|
struct stat statb;
|
|
|
|
(void) gethostname(hostname, sizeof (hostname));
|
|
if ((f = open(_PATH_UTMP, O_RDONLY, 0)) < 0) {
|
|
fprintf(stderr, "Cannot open %s\n", _PATH_UTMP);
|
|
exit(1);
|
|
}
|
|
clock = time( 0 );
|
|
localclock = localtime( &clock );
|
|
sline = ttyslot(); /* 'utmp' slot no. of sender */
|
|
(void) fstat(f, &statb);
|
|
utmp = (struct utmp *)malloc((unsigned)statb.st_size);
|
|
c = read(f, (char *)utmp, (int)statb.st_size);
|
|
(void) close(f);
|
|
c /= sizeof(struct utmp);
|
|
if (sline)
|
|
strncpy(who, utmp[sline].ut_name, sizeof(utmp[sline].ut_name));
|
|
sprintf(mesg,
|
|
"\n\007\007Broadcast Message from %s@%s (%.*s) at %d:%02d ...\r\n\n"
|
|
, who
|
|
, hostname
|
|
, sizeof(utmp[sline].ut_line)
|
|
, utmp[sline].ut_line
|
|
, localclock -> tm_hour
|
|
, localclock -> tm_min
|
|
);
|
|
msize = strlen(mesg);
|
|
if (argc >= 2) {
|
|
/* take message from unix file instead of standard input */
|
|
if (freopen(argv[1], "r", stdin) == NULL) {
|
|
perror(argv[1]);
|
|
exit(1);
|
|
}
|
|
}
|
|
while ((i = getchar()) != EOF) {
|
|
if (i == '\n')
|
|
mesg[msize++] = '\r';
|
|
if (msize >= sizeof mesg) {
|
|
fprintf(stderr, "Message too long\n");
|
|
exit(1);
|
|
}
|
|
mesg[msize++] = i;
|
|
}
|
|
fclose(stdin);
|
|
for (i=0; i<c; i++) {
|
|
p = &utmp[i];
|
|
if (p->ut_name[0] == 0 ||
|
|
strncmp(p->ut_name, IGNOREUSER, sizeof(p->ut_name)) == 0)
|
|
continue;
|
|
sendmes(p->ut_line);
|
|
}
|
|
exit(0);
|
|
}
|
|
|
|
sendmes(tty)
|
|
char *tty;
|
|
{
|
|
register f, flags;
|
|
static char t[50] = "/dev/";
|
|
int e, i;
|
|
|
|
strcpy(t + 5, tty);
|
|
|
|
if ((f = open(t, O_WRONLY|O_NDELAY)) < 0) {
|
|
if (errno != EWOULDBLOCK)
|
|
perror(t);
|
|
return;
|
|
}
|
|
if ((flags = fcntl(f, F_GETFL, 0)) == -1) {
|
|
perror(t);
|
|
return;
|
|
}
|
|
if (fcntl(f, F_SETFL, flags | FNDELAY) == -1)
|
|
goto oldway;
|
|
i = write(f, mesg, msize);
|
|
e = errno;
|
|
(void) fcntl(f, F_SETFL, flags);
|
|
if (i == msize) {
|
|
(void) close(f);
|
|
return;
|
|
}
|
|
if (e != EWOULDBLOCK) {
|
|
errno = e;
|
|
perror(t);
|
|
(void) close(f);
|
|
return;
|
|
}
|
|
oldway:
|
|
while ((i = fork()) == -1)
|
|
if (wait((int *)0) == -1) {
|
|
fprintf(stderr, "Try again\n");
|
|
return;
|
|
}
|
|
if (i) {
|
|
(void) close(f);
|
|
return;
|
|
}
|
|
|
|
(void) write(f, mesg, msize);
|
|
exit(0);
|
|
}
|