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