[9] | 1 | /* wall - write to all logged in users Author: V. Archer */
|
---|
| 2 | /*
|
---|
| 3 | Edvard Tuinder v892231@si.hhs.NL
|
---|
| 4 | Modified some things to include this with my shutdown/halt
|
---|
| 5 | package
|
---|
| 6 | */
|
---|
| 7 |
|
---|
| 8 | #define _POSIX_SOURCE 1
|
---|
| 9 | #include <sys/types.h>
|
---|
| 10 | #include <fcntl.h>
|
---|
| 11 | #include <pwd.h>
|
---|
| 12 | #include <string.h>
|
---|
| 13 | #include <stdio.h>
|
---|
| 14 | #include <time.h>
|
---|
| 15 | #include <utmp.h>
|
---|
| 16 | #include <unistd.h>
|
---|
| 17 | #include <sys/utsname.h>
|
---|
| 18 | #include <sys/stat.h>
|
---|
| 19 | #undef UTMP
|
---|
| 20 |
|
---|
| 21 | static char UTMP[] = "/etc/utmp"; /* Currently logged in users. */
|
---|
| 22 |
|
---|
| 23 | void wall _ARGS(( char *when, char *extra ));
|
---|
| 24 | void crnlcat _ARGS(( char *message, char *more ));
|
---|
| 25 |
|
---|
| 26 | void
|
---|
| 27 | wall(when, extra)
|
---|
| 28 | char *when; /* When is shutdown */
|
---|
| 29 | char *extra; /* If non-nil, why is the shutdown */
|
---|
| 30 | {
|
---|
| 31 | struct utmp utmp;
|
---|
| 32 | char utmptty[5 + sizeof(utmp.ut_line) + 1];
|
---|
| 33 | char message[1024];
|
---|
| 34 | struct passwd *pw;
|
---|
| 35 | int utmpfd, ttyfd;
|
---|
| 36 | char *ourtty, *ourname;
|
---|
| 37 | time_t now;
|
---|
| 38 | struct utsname utsname;
|
---|
| 39 | struct stat con_st, tty_st;
|
---|
| 40 |
|
---|
| 41 | if (ourtty = ttyname(1)) {
|
---|
| 42 | if (ourname = strrchr(ourtty, '/')) ourtty = ourname+1;
|
---|
| 43 | } else ourtty = "system task";
|
---|
| 44 | if (pw = getpwuid(getuid())) ourname = pw->pw_name;
|
---|
| 45 | else ourname = "unknown";
|
---|
| 46 |
|
---|
| 47 | time(&now);
|
---|
| 48 | if (uname(&utsname) != 0) strcpy(utsname.nodename, "?");
|
---|
| 49 | sprintf(message, "\r\nBroadcast message from %s@%s (%s)\r\n%.24s...\r\n",
|
---|
| 50 | ourname, utsname.nodename, ourtty, ctime(&now));
|
---|
| 51 |
|
---|
| 52 | crnlcat(message, when);
|
---|
| 53 | crnlcat(message, extra);
|
---|
| 54 |
|
---|
| 55 | /* Search the UTMP database for all logged-in users. */
|
---|
| 56 |
|
---|
| 57 | if ((utmpfd = open(UTMP, O_RDONLY)) < 0) {
|
---|
| 58 | fprintf(stderr, "Cannot open utmp file\r\n");
|
---|
| 59 | return;
|
---|
| 60 | }
|
---|
| 61 |
|
---|
| 62 | /* first the console */
|
---|
| 63 | strcpy(utmptty, "/dev/console");
|
---|
| 64 | if ((ttyfd = open(utmptty, O_WRONLY | O_NONBLOCK)) < 0) {
|
---|
| 65 | perror(utmptty);
|
---|
| 66 | } else {
|
---|
| 67 | fstat(ttyfd, &con_st);
|
---|
| 68 | write(ttyfd, message, strlen(message));
|
---|
| 69 | close(ttyfd);
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | while (read(utmpfd, (char *) &utmp, sizeof(utmp)) == sizeof(utmp)) {
|
---|
| 73 | /* is this the user we are looking for? */
|
---|
| 74 | if (utmp.ut_type != USER_PROCESS) continue;
|
---|
| 75 |
|
---|
| 76 | strncpy(utmptty+5, utmp.ut_line, sizeof(utmp.ut_line));
|
---|
| 77 | utmptty[5 + sizeof(utmp.ut_line) + 1] = 0;
|
---|
| 78 | if ((ttyfd = open(utmptty, O_WRONLY | O_NONBLOCK)) < 0) {
|
---|
| 79 | perror(utmptty);
|
---|
| 80 | continue;
|
---|
| 81 | }
|
---|
| 82 | fstat(ttyfd, &tty_st);
|
---|
| 83 | if (tty_st.st_rdev != con_st.st_rdev)
|
---|
| 84 | write(ttyfd, message, strlen(message));
|
---|
| 85 | close(ttyfd);
|
---|
| 86 | }
|
---|
| 87 | close(utmpfd);
|
---|
| 88 | return;
|
---|
| 89 | }
|
---|
| 90 |
|
---|
| 91 | void
|
---|
| 92 | crnlcat(message, more)
|
---|
| 93 | char *message, *more;
|
---|
| 94 | {
|
---|
| 95 | char *p = message;
|
---|
| 96 | char *m = more;
|
---|
| 97 | char *end = message + 1024 - 1;
|
---|
| 98 |
|
---|
| 99 | while (p < end && *p != 0) *p++;
|
---|
| 100 |
|
---|
| 101 | while (p < end && *m != 0) {
|
---|
| 102 | if (*m == '\n' && (p == message || p[-1] != '\n')) {
|
---|
| 103 | *p++ = '\r';
|
---|
| 104 | if (p == end) p--;
|
---|
| 105 | }
|
---|
| 106 | *p++ = *m++;
|
---|
| 107 | }
|
---|
| 108 | *p = 0;
|
---|
| 109 | }
|
---|