xref: /original-bsd/usr.bin/wall/wall.c (revision 7e7b101a)
1 static char *sccsid = "@(#)wall.c	4.8 (Berkeley) 84/03/30";
2 /*
3  * wall.c - Broadcast a message to all users.
4  *
5  * This program is not related to David Wall, whose Stanford Ph.D. thesis
6  * is entitled "Mechanisms for Broadcast and Selective Broadcast".
7  */
8 
9 #include <stdio.h>
10 #include <utmp.h>
11 #include <errno.h>
12 #include <signal.h>
13 #include <sys/time.h>
14 #include <fcntl.h>
15 
16 #define	USERS	128
17 #define IGNOREUSER	"sleeper"
18 
19 char	hostname[32];
20 char	mesg[3000];
21 int	msize,sline;
22 struct	utmp utmp[USERS];
23 char	*strcpy();
24 char	*strcat();
25 char	who[9] = "???";
26 long	clock, time();
27 struct tm *localtime();
28 struct tm *localclock;
29 
30 extern	errno;
31 
32 main(argc, argv)
33 char *argv[];
34 {
35 	register int i, c;
36 	register struct utmp *p;
37 	FILE *f;
38 
39 	gethostname(hostname, sizeof (hostname));
40 	if ((f = fopen("/etc/utmp", "r")) == NULL) {
41 		fprintf(stderr, "Cannot open /etc/utmp\n");
42 		exit(1);
43 	}
44 	clock = time( 0 );
45 	localclock = localtime( &clock );
46 	sline = ttyslot();	/* 'utmp' slot no. of sender */
47 	c = fread((char *)utmp, sizeof(struct utmp), USERS, f);
48 	fclose(f);
49 	if (sline)
50 		strncpy(who, utmp[sline].ut_name, sizeof(utmp[sline].ut_name));
51 	sprintf(mesg,
52 	    "\nBroadcast Message from %s@%s (%.*s) at %d:%02d ...\r\n\n"
53 		, who
54 		, hostname
55 		, sizeof(utmp[sline].ut_line)
56 		, utmp[sline].ut_line
57 		, localclock -> tm_hour
58 		, localclock -> tm_min
59 	);
60 	msize = strlen(mesg);
61 	if (argc >= 2) {
62 		/* take message from unix file instead of standard input */
63 		if (freopen(argv[1], "r", stdin) == NULL) {
64 			perror(argv[1]);
65 			exit(1);
66 		}
67 	}
68 	while ((i = getchar()) != EOF) {
69 		if (i == '\n')
70 			mesg[msize++] = '\r';
71 		if (msize >= sizeof mesg) {
72 			fprintf(stderr, "Message too long\n");
73 			exit(1);
74 		}
75 		mesg[msize++] = i;
76 	}
77 	fclose(stdin);
78 	for (i=0; i<c; i++) {
79 		p = &utmp[i];
80 		if (p->ut_name[0] == 0 ||
81 		    strncmp(p->ut_name, IGNOREUSER, sizeof(p->ut_name)) == 0)
82 			continue;
83 		sendmes(p->ut_line);
84 	}
85 	exit(0);
86 }
87 
88 sendmes(tty)
89 char *tty;
90 {
91 	register f, flags;
92 	static char t[50] = "/dev/";
93 	int e, i;
94 
95 	strcpy(t + 5, tty);
96 
97 	if ((f = open(t, O_WRONLY|O_NDELAY)) < 0) {
98 		if (errno != EWOULDBLOCK)
99 			perror(t);
100 		return;
101 	}
102 	if ((flags = fcntl(f, F_GETFL, 0)) == -1) {
103 		perror(t);
104 		return;
105 	}
106 	if (fcntl(f, F_SETFL, flags | FNDELAY) == -1)
107 		goto oldway;
108 	i = write(f, mesg, msize);
109 	e = errno;
110 	(void) fcntl(f, F_SETFL, flags);
111 	if (i == msize) {
112 		(void) close(f);
113 		return;
114 	}
115 	if (e != EWOULDBLOCK) {
116 		errno = e;
117 		perror(t);
118 		(void) close(f);
119 		return;
120 	}
121 oldway:
122 	while ((i = fork()) == -1)
123 		if (wait((int *)0) == -1) {
124 			fprintf(stderr, "Try again\n");
125 			return;
126 		}
127 	if (i) {
128 		(void) close(f);
129 		return;
130 	}
131 
132 	(void) write(f, mesg, msize);
133 	exit(0);
134 }
135