]>
git.wh0rd.org - sysvinit.git/blob - src/dowall.c
2 * dowall.c Write to all users on the system.
4 * Author: Miquel van Smoorenburg, miquels@cistron.nl
6 * Version: @(#)dowall.c 2.85-5 02-Jul-2003 miquels@cistron.nl
8 * This file is part of the sysvinit suite,
9 * Copyright (C) 1991-2003 Miquel van Smoorenburg.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <sys/types.h>
27 #include <sys/sysmacros.h>
40 static sigjmp_buf jbuf
;
46 static void handler(int arg
)
53 * Print a text, escape all characters not in Latin-1.
55 static void feputs(const char *line
, FILE *fp
)
59 for (p
= (unsigned char *)line
; *p
; p
++) {
60 if (strchr("\t\r\n", *p
) ||
61 (*p
>= 32 && *p
<= 127) || (*p
>= 160)) {
64 fprintf(fp
, "^%c", (*p
& 0x1f) + 'A' - 1);
71 static void getuidtty(char **userp
, char **ttyp
)
76 static char uidbuf
[32];
77 static char ttynm
[UT_LINESIZE
+ 4];
83 if ((pwd
= getpwuid(uid
)) != NULL
) {
85 strncat(uidbuf
, pwd
->pw_name
, sizeof(uidbuf
) - 1);
87 sprintf(uidbuf
, uid
? "uid %d" : "root", (int)uid
);
90 if ((tty
= ttyname(0)) != NULL
) {
91 if (strncmp(tty
, "/dev/", 5) == 0)
93 sprintf(ttynm
, "(%.28s) ", tty
);
104 * Check whether given filename looks like tty device.
106 static int file_isatty(const char *fname
)
111 if (stat(fname
, &st
) < 0)
114 if (st
.st_nlink
!= 1 || !S_ISCHR(st
.st_mode
))
118 * It would be an impossible task to list all major/minors
119 * of tty devices here, so we just exclude the obvious
120 * majors of which just opening has side-effects:
121 * printers and tapes.
123 major
= major(st
.st_dev
);
124 if (major
== 1 || major
== 2 || major
== 6 || major
== 9 ||
125 major
== 12 || major
== 16 || major
== 21 || major
== 27 ||
126 major
== 37 || major
== 96 || major
== 97 || major
== 206 ||
127 major
== 230) return 0;
135 void wall(const char *text
, int remote
)
141 char term
[UT_LINESIZE
+6];
143 char hostname
[256]; /* HOST_NAME_MAX+1 */
149 * Make sure tp and fd aren't in a register. Some versions
150 * of gcc clobber those after longjmp (or so I understand).
155 getuidtty(&user
, &tty
);
157 /* Get and report current hostname, to make it easier to find
158 out which machine is being shut down. */
159 if (0 != gethostname(hostname
, sizeof(hostname
))) {
160 strncpy(hostname
, "[unknown]", sizeof(hostname
)-1);
162 /* If hostname is truncated, it is unspecified if the string
163 is null terminated or not. Make sure we know it is null
165 hostname
[sizeof(hostname
)-1] = 0;
170 for(p
= date
; *p
&& *p
!= '\n'; p
++)
175 snprintf(line
, sizeof(line
),
176 "\007\r\nRemote broadcast message (%s):\r\n\r\n",
179 snprintf(line
, sizeof(line
),
180 "\007\r\nBroadcast message from %s@%s %s(%s):\r\n\r\n",
181 user
, hostname
, tty
, date
);
185 * Fork to avoid us hanging in a write()
190 memset(&sa
, 0, sizeof(sa
));
191 sa
.sa_handler
= handler
;
193 sigemptyset(&sa
.sa_mask
);
194 sigaction(SIGALRM
, &sa
, NULL
);
198 while ((utmp
= getutent()) != NULL
) {
199 if(utmp
->ut_type
!= USER_PROCESS
||
200 utmp
->ut_user
[0] == 0) continue;
201 if (strncmp(utmp
->ut_line
, "/dev/", 5) == 0) {
203 strncat(term
, utmp
->ut_line
, sizeof(term
)-1);
205 snprintf(term
, sizeof(term
), "/dev/%.*s",
206 UT_LINESIZE
, utmp
->ut_line
);
207 if (strstr(term
, "/../")) continue;
215 if (sigsetjmp(jbuf
, 1) == 0) {
217 flags
= O_WRONLY
|O_NDELAY
|O_NOCTTY
;
218 if (file_isatty(term
) &&
219 (fd
= open(term
, flags
)) >= 0) {
221 (tp
= fdopen(fd
, "w")) != NULL
) {
229 if (fd
>= 0) close(fd
);
230 if (tp
!= NULL
) fclose(tp
);