pdp11v/usr/src/cmd/wall.c
/* @(#)wall.c 1.6 */
#define FAILURE (-1)
#define TRUE 1
#define FALSE 0
#include <signal.h>
char mesg[3000];
#include <sys/types.h>
#include <utmp.h>
#include <grp.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include <pwd.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
unsigned int usize;
int entries;
struct utmp *utmp;
char *line = "???";
char who[9] = "???";
char *infile;
int group;
struct group *pgrp;
extern struct group *getgrname();
extern char *ttyname();
char *grpname;
char *timstr;
long tloc, time();
extern int errno;
#define equal(a,b) (!strcmp( (a), (b) ))
main(argc, argv)
int argc;
char *argv[];
{
int i, fd;
register struct utmp *p,*pmax;
FILE *f;
struct utmp *getutent();
struct stat statbuf;
struct direct direntry;
int devfd;
register char *ptr;
struct passwd *pwd;
extern struct passwd *getpwuid();
char *malloc();
if(stat(UTMP_FILE, &statbuf) < 0) {
fprintf(stderr, "stat failed on %s\n", UTMP_FILE);
exit(1);
}
/* get usize (an unsigned int) for malloc call
* and check that there is no truncation (for those 16 bit CPUs)
*/
usize = statbuf.st_size;
if(usize != statbuf.st_size) {
fprintf(stderr, "'%s' too big.\n", UTMP_FILE);
exit(1);
}
entries = usize / sizeof(struct utmp);
if((utmp=(struct utmp *)malloc(usize)) == NULL) {
fprintf(stderr, "cannot allocate memory for '%s'.\n", UTMP_FILE);
exit(1);
}
if((fd=open(UTMP_FILE, O_RDONLY)) < 0) {
fprintf(stderr,"cannot open '%s'\n", UTMP_FILE);
exit(1);
}
if(read(fd, utmp, usize) != usize) {
fprintf(stderr, "cannot read '%s'\n", UTMP_FILE);
exit(1);
}
close(fd);
readargs(argc, argv);
/* Get the name of the terminal wall is running from. */
if (isatty(fileno(stderr)) && fstat(fileno(stderr),&statbuf) !=
FAILURE && (devfd = open("/dev",0)) != FAILURE) {
while (who[0] == '?') {
/* Read in directory entries for /dev and look for ones with */
/* an inode number equal to the inode number of our standard */
/* error output. */
for (direntry.d_ino=0; direntry.d_ino !=
statbuf.st_ino;) {
direntry.d_ino = 0;
if (read(devfd,&direntry,sizeof(direntry))
!= sizeof(direntry)) {
direntry.d_ino = 0;
break;
}
}
/* If we've reached the end of the dev directory and can't find */
/* another name for this terminal, finally give up. */
if (direntry.d_ino != statbuf.st_ino) break;
else line = &direntry.d_name[0];
/* Search for self so that we can identify ourselves when we send. */
for(i=0;i<entries;i++) {
p = &utmp[i];
if(p->ut_type != USER_PROCESS) continue;
if (strncmp(line,&p->ut_line[0],
sizeof(p->ut_line)) == 0) {
strncpy(&who[0],&p->ut_user[0],
sizeof(p->ut_user));
who[sizeof(p->ut_user)] = '\0';
break;
}
}
/* If we didn't find the utmp entry, reset line to "???" and */
/* continue looking. */
if (p == pmax) {
strcpy(&who[0],"???");
line = "???";
}
}
} else {
if (pwd = getpwuid(getuid()))
strncpy(&who[0],pwd->pw_name,sizeof(who));
}
if (devfd != FAILURE) close(devfd);
f = stdin;
if(infile) {
f = fopen(infile, "r");
if(f == NULL) {
printf("%s??\n", infile);
exit(1);
}
}
for(ptr= &mesg[0]; fgets(ptr,&mesg[sizeof(mesg)]-ptr, f) != NULL
; ptr += strlen(ptr));
fclose(f);
time(&tloc);
timstr = ctime(&tloc);
for(i=0;i<entries;i++) {
if((p=(&utmp[i]))->ut_type != USER_PROCESS) continue;
sendmes(p);
}
alarm(60);
do {
i = wait((int *)0);
} while(i != -1 || errno != ECHILD);
exit(0);
}
sendmes(p)
struct utmp *p;
{
register i;
register char *s;
static char device[] = "/dev/123456789012";
FILE *f;
if(group)
if(!chkgrp(p->ut_user))
return;
while((i=fork()) == -1) {
alarm(60);
wait((int *)0);
alarm(0);
}
if(i)
return;
signal(SIGHUP, SIG_IGN);
alarm(60);
s = &device[0];
sprintf(s,"/dev/%s",&p->ut_line[0]);
#ifdef DEBUG
f = fopen("wall.debug", "a");
#else
f = fopen(s, "w");
#endif
if(f == NULL) {
printf("Cannot send to %.-8s\n", &p->ut_user[0]);
perror("open");
exit(1);
}
fprintf(f, "\07\07\07Broadcast Message from %s (%s) %19.19s",
who, line, timstr);
if(group)
fprintf(f, " to group %s", grpname);
fprintf(f, "...\n");
#ifdef DEBUG
fprintf(f,"DEBUG: To %.8s on %s\n", p->ut_user, s);
#endif
fprintf(f, "%s\n", mesg);
fclose(f);
exit(0);
}
readargs(ac, av)
int ac;
char **av;
{
register int i, j;
for(i = 1; i < ac; i++) {
if(equal(av[i], "-g")) {
if(group) {
fprintf(stderr, "Only one group allowed\n");
exit(1);
}
i++;
if((pgrp=getgrname(grpname= av[i])) == NULL) {
fprintf(stderr, "Unknown group %s\n", grpname);
exit(1);
}
endgrent();
group++;
}
else
infile = av[i];
}
}
#define BLANK ' '
chkgrp(name)
register char *name;
{
register int i;
register char *p;
for(i = 0; pgrp->gr_mem[i] && pgrp->gr_mem[i][0]; i++) {
for(p=name; *p && *p != BLANK; p++);
*p = 0;
if(equal(name, pgrp->gr_mem[i]))
return(1);
}
return(0);
}