1 --- dowall.c 2001-09-26 12:59:46.000000000 +0200
2 +++ ../../sysvinit-2.86.ds1/src/dowall.c 2004-06-09 14:47:45.000000000 +0200
5 * Author: Miquel van Smoorenburg, miquels@cistron.nl
7 - * Version: @(#)dowall.c 2.79 11-Sep-2000 miquels@cistron.nl
8 + * Version: @(#)dowall.c 2.85-5 02-Jul-2003 miquels@cistron.nl
10 * This file is part of the sysvinit suite,
11 - * Copyright 1991-2000 Miquel van Smoorenburg.
12 + * Copyright 1991-2003 Miquel van Smoorenburg.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
18 #include <sys/types.h>
20 +#include <sys/sysmacros.h>
31 -/* display pid of rpc.rwalld if wall() is called with 'remote' non-zero */
33 +static sigjmp_buf jbuf;
39 -static void handler(arg)
41 +static void handler(int arg)
43 - signal(SIGALRM, handler);
45 + siglongjmp(jbuf, 1);
50 * Print a text, escape all characters not in Latin-1.
52 -void feputs(char *line, FILE *fp)
53 +static void feputs(char *line, FILE *fp)
58 for (p = (unsigned char *)line; *p; p++) {
59 if (strchr("\t\r\n", *p) ||
67 -void wall(char *text, int fromshutdown, int remote)
68 +static void getuidtty(char **userp, char **ttyp)
72 - char term[UT_LINESIZE+6];
73 - static char *user, ttynm[32], *date;
75 - static int fd, init = 0;
84 + static char uidbuf[32];
85 + static char ttynm[32];
86 + static int init = 0;
93 - pwd = getpwuid(uid);
94 - sprintf (uidbuf, "uid %d", (int)uid);
96 - * display uid if no corresponding username found in
97 - * password file. superuser (uid 0) is always "root",
100 - user = pwd ? pwd->pw_name : (uid == 0 ? "root" : uidbuf);
101 + if ((pwd = getpwuid(uid)) != NULL) {
103 + strncat(uidbuf, pwd->pw_name, sizeof(uidbuf) - 1);
105 + sprintf(uidbuf, uid ? "uid %d" : "root", (int)uid);
108 if ((tty = ttyname(0)) != NULL) {
109 if (strncmp(tty, "/dev/", 5) == 0)
115 - signal(SIGALRM, handler);
124 + * Check whether given filename looks like tty device.
126 +static int file_isatty(const char *fname)
131 + if (stat(fname, &st) < 0)
134 + if (st.st_nlink != 1 || !S_ISCHR(st.st_mode))
138 + * It would be an impossible task to list all major/minors
139 + * of tty devices here, so we just exclude the obvious
140 + * majors of which just opening has side-effects:
141 + * printers and tapes.
143 + major = major(st.st_dev);
144 + if (major == 1 || major == 2 || major == 6 || major == 9 ||
145 + major == 12 || major == 16 || major == 21 || major == 27 ||
146 + major == 37 || major == 96 || major == 97 || major == 206 ||
147 + major == 230) return 0;
155 +void wall(char *text, int fromshutdown, int remote)
158 + struct sigaction sa;
161 + char term[UT_LINESIZE+6];
168 + * Make sure tp and fd aren't in a register. Some versions
169 + * of gcc clobber those after longjmp (or so I understand).
174 + getuidtty(&user, &tty);
181 snprintf(line, sizeof(line),
182 "\007\r\nBroadcast message from %s %s(%s):\r\n\r\n",
183 - user, ttynm, date);
188 @@ -124,50 +167,50 @@
192 - siginterrupt (SIGALRM, 1);
193 + memset(&sa, 0, sizeof(sa));
194 + sa.sa_handler = handler;
196 + sigemptyset(&sa.sa_mask);
197 + sigaction(SIGALRM, &sa, NULL);
201 while ((utmp = getutent()) != NULL) {
202 if(utmp->ut_type != USER_PROCESS ||
203 utmp->ut_user[0] == 0) continue;
204 - term[sizeof(term) - 1] = 0;
205 - if (strncmp(utmp->ut_line, "/dev/", 5) == 0)
206 - strncpy(term, utmp->ut_line, sizeof(term)-1);
208 - snprintf(term, sizeof(term), "/dev/%s",
212 - * Sometimes the open/write hangs in spite of the O_NDELAY
216 + if (strncmp(utmp->ut_line, "/dev/", 5) == 0) {
218 + strncat(term, utmp->ut_line, UT_LINESIZE);
220 + snprintf(term, sizeof(term), "/dev/%.*s",
221 + UT_LINESIZE, utmp->ut_line);
222 + if (strstr(term, "/../")) continue;
230 - if (setjmp(jbuf) == 0 &&
231 - (fd = open(term, O_WRONLY | O_NDELAY )) > 0) {
232 - if ((tp = fdopen(fd, "w")) != NULL) {
240 + if (sigsetjmp(jbuf, 1) == 0) {
242 + flags = O_WRONLY|O_NDELAY|O_NOCTTY;
243 + if (file_isatty(term) &&
244 + (fd = open(term, flags)) >= 0) {
246 + (tp = fdopen(fd, "w")) != NULL) {
254 if (fd >= 0) close(fd);
256 - if (setjmp(jbuf) == 0 && (tp = fopen(term, "w")) != NULL) {
263 if (tp != NULL) fclose(tp);