/* * Wall function. */ void wall(const char *text, int remote) { FILE *tp; struct sigaction sa; struct utmp *utmp; time_t t; char term[UT_LINESIZE+ strlen(_PATH_DEV) + 1]; char line[81]; char hostname[HOST_NAME_MAX+1]; char *date, *p; char *user, *tty; int fd, flags; /* * Make sure tp and fd aren't in a register. Some versions * of gcc clobber those after longjmp (or so I understand). */ (void) &tp; (void) &fd; getuidtty(&user, &tty); /* Get and report current hostname, to make it easier to find out which machine is being shut down. */ if (0 != gethostname(hostname, sizeof(hostname))) { strncpy(hostname, "[unknown]", sizeof(hostname)-1); } /* If hostname is truncated, it is unspecified if the string is null terminated or not. Make sure we know it is null terminated. */ hostname[sizeof(hostname)-1] = 0; /* Get the time */ time(&t); date = ctime(&t); for(p = date; *p && *p != '\n'; p++) ; *p = 0; if (remote) { snprintf(line, sizeof(line), "\007\r\nRemote broadcast message (%s):\r\n\r\n", date); } else { snprintf(line, sizeof(line), "\007\r\nBroadcast message from %s@%s %s(%s):\r\n\r\n", user, hostname, tty, date); } /* * Fork to avoid us hanging in a write() */ if (fork() != 0) return; memset(&sa, 0, sizeof(sa)); sa.sa_handler = handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGALRM, &sa, NULL); setutent(); while ((utmp = getutent()) != NULL) { if(utmp->ut_type != USER_PROCESS || utmp->ut_user[0] == 0) continue; if (strncmp(utmp->ut_line, _PATH_DEV, strlen(_PATH_DEV)) == 0) { term[0] = 0; strncat(term, utmp->ut_line, sizeof(term)-1); } else snprintf(term, sizeof(term), _PATH_DEV "%.*s", UT_LINESIZE, utmp->ut_line); if (strstr(term, "/../")) continue; fd = -1; tp = NULL; /* * Open it non-delay */ if (sigsetjmp(jbuf, 1) == 0) { alarm(2); flags = O_WRONLY|O_NDELAY|O_NOCTTY; if (file_isatty(term) && (fd = open(term, flags)) >= 0) { if (isatty(fd) && (tp = fdopen(fd, "w")) != NULL) { fputs(line, tp); feputs(text, tp); fflush(tp); } } } alarm(0); if (fd >= 0) close(fd); if (tp != NULL) fclose(tp); } endutent(); exit(0); }
/* * Wall function. */ void wall(char *text, int fromshutdown, int remote) { FILE *tp; struct sigaction sa; struct utmp *utmp; time_t t; char term[UT_LINESIZE+6]; char line[81]; char *date, *p; char *user, *tty; int fd, flags; /* * Make sure tp and fd aren't in a register. Some versions * of gcc clobber those after longjmp (or so I understand). */ (void) &tp; (void) &fd; getuidtty(&user, &tty); /* Get the time */ time(&t); date = ctime(&t); for(p = date; *p && *p != '\n'; p++) ; *p = 0; if (remote) { snprintf(line, sizeof(line), "\007\r\nRemote broadcast message (%s):\r\n\r\n", date); } else { snprintf(line, sizeof(line), "\007\r\nBroadcast message from %s %s(%s):\r\n\r\n", user, tty, date); } /* * Fork to avoid us hanging in a write() */ if (fork() != 0) return; memset(&sa, 0, sizeof(sa)); sa.sa_handler = handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGALRM, &sa, NULL); setutent(); while ((utmp = getutent()) != NULL) { if(utmp->ut_type != USER_PROCESS || utmp->ut_user[0] == 0) continue; if (strncmp(utmp->ut_line, "/dev/", 5) == 0) { term[0] = 0; strncat(term, utmp->ut_line, UT_LINESIZE); } else snprintf(term, sizeof(term), "/dev/%.*s", UT_LINESIZE, utmp->ut_line); if (strstr(term, "/../")) continue; fd = -1; tp = NULL; /* * Open it non-delay */ if (sigsetjmp(jbuf, 1) == 0) { alarm(2); flags = O_WRONLY|O_NDELAY|O_NOCTTY; if (file_isatty(term) && (fd = open(term, flags)) >= 0) { if (isatty(fd) && (tp = fdopen(fd, "w")) != NULL) { fputs(line, tp); feputs(text, tp); fflush(tp); } } } alarm(0); if (fd >= 0) close(fd); if (tp != NULL) fclose(tp); } endutent(); exit(0); }