Commit | Line | Data |
---|---|---|
02072412 DF |
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 | |
4689f60b | 14 | static char sccsid[] = "@(#)wall.c 5.3 (Berkeley) %G%"; |
02072412 DF |
15 | #endif not lint |
16 | ||
1addde1c BJ |
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> | |
3071a7ff | 26 | #include <errno.h> |
df3e00cc | 27 | #include <signal.h> |
3071a7ff RC |
28 | #include <sys/time.h> |
29 | #include <fcntl.h> | |
734f8abe JB |
30 | #include <sys/types.h> |
31 | #include <sys/stat.h> | |
3071a7ff | 32 | |
ec74d621 | 33 | #define IGNOREUSER "sleeper" |
1addde1c | 34 | |
cf288731 | 35 | char hostname[32]; |
1addde1c BJ |
36 | char mesg[3000]; |
37 | int msize,sline; | |
734f8abe | 38 | struct utmp *utmp; |
1addde1c BJ |
39 | char *strcpy(); |
40 | char *strcat(); | |
734f8abe | 41 | char *malloc(); |
3071a7ff | 42 | char who[9] = "???"; |
1eca479f | 43 | long clock, time(); |
1addde1c BJ |
44 | struct tm *localtime(); |
45 | struct tm *localclock; | |
46 | ||
3071a7ff RC |
47 | extern errno; |
48 | ||
1addde1c BJ |
49 | main(argc, argv) |
50 | char *argv[]; | |
51 | { | |
3071a7ff | 52 | register int i, c; |
1addde1c | 53 | register struct utmp *p; |
734f8abe JB |
54 | int f; |
55 | struct stat statb; | |
1addde1c | 56 | |
734f8abe JB |
57 | (void) gethostname(hostname, sizeof (hostname)); |
58 | if ((f = open("/etc/utmp", O_RDONLY, 0)) < 0) { | |
1addde1c BJ |
59 | fprintf(stderr, "Cannot open /etc/utmp\n"); |
60 | exit(1); | |
61 | } | |
62 | clock = time( 0 ); | |
63 | localclock = localtime( &clock ); | |
3071a7ff | 64 | sline = ttyslot(); /* 'utmp' slot no. of sender */ |
734f8abe JB |
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); | |
3071a7ff RC |
70 | if (sline) |
71 | strncpy(who, utmp[sline].ut_name, sizeof(utmp[sline].ut_name)); | |
72 | sprintf(mesg, | |
4689f60b | 73 | "\n\007\007Broadcast Message from %s@%s (%.*s) at %d:%02d ...\r\n\n" |
3071a7ff RC |
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) { | |
1addde1c | 83 | /* take message from unix file instead of standard input */ |
3071a7ff RC |
84 | if (freopen(argv[1], "r", stdin) == NULL) { |
85 | perror(argv[1]); | |
1addde1c BJ |
86 | exit(1); |
87 | } | |
88 | } | |
3071a7ff RC |
89 | while ((i = getchar()) != EOF) { |
90 | if (i == '\n') | |
91 | mesg[msize++] = '\r'; | |
df3e00cc BJ |
92 | if (msize >= sizeof mesg) { |
93 | fprintf(stderr, "Message too long\n"); | |
94 | exit(1); | |
1addde1c | 95 | } |
df3e00cc BJ |
96 | mesg[msize++] = i; |
97 | } | |
3071a7ff RC |
98 | fclose(stdin); |
99 | for (i=0; i<c; i++) { | |
1addde1c | 100 | p = &utmp[i]; |
3071a7ff RC |
101 | if (p->ut_name[0] == 0 || |
102 | strncmp(p->ut_name, IGNOREUSER, sizeof(p->ut_name)) == 0) | |
1addde1c | 103 | continue; |
1addde1c BJ |
104 | sendmes(p->ut_line); |
105 | } | |
106 | exit(0); | |
107 | } | |
108 | ||
109 | sendmes(tty) | |
110 | char *tty; | |
111 | { | |
3071a7ff RC |
112 | register f, flags; |
113 | static char t[50] = "/dev/"; | |
114 | int e, i; | |
1addde1c | 115 | |
3071a7ff RC |
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: | |
df3e00cc BJ |
143 | while ((i = fork()) == -1) |
144 | if (wait((int *)0) == -1) { | |
145 | fprintf(stderr, "Try again\n"); | |
146 | return; | |
147 | } | |
3071a7ff RC |
148 | if (i) { |
149 | (void) close(f); | |
1addde1c | 150 | return; |
1addde1c | 151 | } |
1addde1c | 152 | |
3071a7ff | 153 | (void) write(f, mesg, msize); |
1addde1c BJ |
154 | exit(0); |
155 | } |