]>
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>
42 # define _PATH_DEV "/dev/"
45 # define HOST_NAME_MAX 255
48 static sigjmp_buf jbuf
;
55 static void handler(int arg
__attribute__((unused
)))
57 static void handler(int arg
)
65 * Print a text, escape all characters not in Latin-1.
67 static void feputs(const char *line
, FILE *fp
)
71 for (p
= (unsigned char *)line
; *p
; p
++) {
72 if (strchr("\t\r\n", *p
) ||
73 (*p
>= 32 && *p
<= 127) || (*p
>= 160)) {
76 fprintf(fp
, "^%c", (*p
& 0x1f) + 'A' - 1);
83 static void getuidtty(char **userp
, char **ttyp
)
88 static char uidbuf
[32];
89 static char ttynm
[UT_LINESIZE
+ 4];
95 if ((pwd
= getpwuid(uid
)) != NULL
) {
97 strncat(uidbuf
, pwd
->pw_name
, sizeof(uidbuf
) - 1);
99 sprintf(uidbuf
, uid
? "uid %d" : "root", (int)uid
);
102 if ((tty
= ttyname(0)) != NULL
) {
103 const size_t plen
= strlen(_PATH_DEV
);
104 if (strncmp(tty
, _PATH_DEV
, plen
) == 0) {
109 snprintf(ttynm
, sizeof(ttynm
), "(%.*s) ",
121 * Check whether given filename looks like tty device.
123 static int file_isatty(const char *fname
)
128 if (stat(fname
, &st
) < 0)
131 if (st
.st_nlink
!= 1 || !S_ISCHR(st
.st_mode
))
135 * It would be an impossible task to list all major/minors
136 * of tty devices here, so we just exclude the obvious
137 * majors of which just opening has side-effects:
138 * printers and tapes.
140 major
= major(st
.st_dev
);
141 if (major
== 1 || major
== 2 || major
== 6 || major
== 9 ||
142 major
== 12 || major
== 16 || major
== 21 || major
== 27 ||
143 major
== 37 || major
== 96 || major
== 97 || major
== 206 ||
144 major
== 230) return 0;
152 void wall(const char *text
, int remote
)
158 char term
[UT_LINESIZE
+ strlen(_PATH_DEV
) + 1];
160 char hostname
[HOST_NAME_MAX
+1];
166 * Make sure tp and fd aren't in a register. Some versions
167 * of gcc clobber those after longjmp (or so I understand).
172 getuidtty(&user
, &tty
);
174 /* Get and report current hostname, to make it easier to find
175 out which machine is being shut down. */
176 if (0 != gethostname(hostname
, sizeof(hostname
))) {
177 strncpy(hostname
, "[unknown]", sizeof(hostname
)-1);
179 /* If hostname is truncated, it is unspecified if the string
180 is null terminated or not. Make sure we know it is null
182 hostname
[sizeof(hostname
)-1] = 0;
187 for(p
= date
; *p
&& *p
!= '\n'; p
++)
192 snprintf(line
, sizeof(line
),
193 "\007\r\nRemote broadcast message (%s):\r\n\r\n",
196 snprintf(line
, sizeof(line
),
197 "\007\r\nBroadcast message from %s@%s %s(%s):\r\n\r\n",
198 user
, hostname
, tty
, date
);
202 * Fork to avoid us hanging in a write()
207 memset(&sa
, 0, sizeof(sa
));
208 sa
.sa_handler
= handler
;
210 sigemptyset(&sa
.sa_mask
);
211 sigaction(SIGALRM
, &sa
, NULL
);
215 while ((utmp
= getutent()) != NULL
) {
216 if(utmp
->ut_type
!= USER_PROCESS
||
217 utmp
->ut_user
[0] == 0) continue;
218 if (strncmp(utmp
->ut_line
, _PATH_DEV
, strlen(_PATH_DEV
)) == 0) {
220 strncat(term
, utmp
->ut_line
, sizeof(term
)-1);
222 snprintf(term
, sizeof(term
), _PATH_DEV
"%.*s",
223 UT_LINESIZE
, utmp
->ut_line
);
224 if (strstr(term
, "/../")) continue;
232 if (sigsetjmp(jbuf
, 1) == 0) {
234 flags
= O_WRONLY
|O_NDELAY
|O_NOCTTY
;
235 if (file_isatty(term
) &&
236 (fd
= open(term
, flags
)) >= 0) {
238 (tp
= fdopen(fd
, "w")) != NULL
) {
246 if (fd
>= 0) close(fd
);
247 if (tp
!= NULL
) fclose(tp
);