diff options
Diffstat (limited to 'term-utils/wall.c')
| -rw-r--r-- | term-utils/wall.c | 147 |
1 files changed, 88 insertions, 59 deletions
diff --git a/term-utils/wall.c b/term-utils/wall.c index 4865ac7a1..20a2891f2 100644 --- a/term-utils/wall.c +++ b/term-utils/wall.c @@ -69,39 +69,41 @@ #include "fileutils.h" #include "closestream.h" -#define IGNOREUSER "sleeper" #define WRITE_TIME_OUT 300 /* in seconds */ /* Function prototypes */ -char *makemsg(char *fname, size_t *mbufsize, int print_banner); -static void usage(FILE *out); +static char *makemsg(char *fname, char **mvec, int mvecsz, + size_t *mbufsize, int print_banner); static void __attribute__((__noreturn__)) usage(FILE *out) { - fputs(_("\nUsage:\n"), out); + fputs(USAGE_HEADER, out); fprintf(out, - _(" %s [options] [<file>]\n"),program_invocation_short_name); - - fputs(_("\nOptions:\n"), out); - fputs(_(" -n, --nobanner do not print banner, works only for root\n" - " -t, --timeout <timeout> write timeout in seconds\n" - " -V, --version output version information and exit\n" - " -h, --help display this help and exit\n\n"), out); + _(" %s [options] [<file> | <message>]\n"), program_invocation_short_name); + fputs(USAGE_OPTIONS, out); + fputs(_(" -n, --nobanner do not print banner, works only for root\n"), out); + fputs(_(" -t, --timeout <timeout> write timeout in seconds\n"), out); + fputs(USAGE_SEPARATOR, out); + fputs(USAGE_HELP, out); + fputs(USAGE_VERSION, out); + fprintf(out, USAGE_MAN_TAIL("wall(1)")); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } -int -main(int argc, char **argv) { +int main(int argc, char **argv) +{ int ch; struct iovec iov; struct utmp *utmpptr; char *p; char line[sizeof(utmpptr->ut_line) + 1]; int print_banner = TRUE; - char *mbuf; + char *mbuf, *fname = NULL; size_t mbufsize; unsigned timeout = WRITE_TIME_OUT; + char **mvec = NULL; + int mvecsz = 0; static const struct option longopts[] = { { "nobanner", no_argument, 0, 'n' }, @@ -130,8 +132,7 @@ main(int argc, char **argv) { errx(EXIT_FAILURE, _("invalid timeout argument: %s"), optarg); break; case 'V': - printf(_("%s from %s\n"), program_invocation_short_name, - PACKAGE_STRING); + printf(UTIL_LINUX_VERSION); exit(EXIT_SUCCESS); case 'h': usage(stdout); @@ -141,23 +142,25 @@ main(int argc, char **argv) { } argc -= optind; argv += optind; - if (argc > 1) - usage(stderr); - mbuf = makemsg(*argv, &mbufsize, print_banner); + if (argc == 1 && access(argv[0], F_OK) == 0) + fname = argv[0]; + else if (argc >= 1) { + mvec = argv; + mvecsz = argc; + } + + mbuf = makemsg(fname, mvec, mvecsz, &mbufsize, print_banner); iov.iov_base = mbuf; iov.iov_len = mbufsize; while((utmpptr = getutent())) { - if (!utmpptr->ut_name[0] || - !strncmp(utmpptr->ut_name, IGNOREUSER, - sizeof(utmpptr->ut_name))) + if (!utmpptr->ut_user[0]) continue; #ifdef USER_PROCESS if (utmpptr->ut_type != USER_PROCESS) continue; #endif - /* Joey Hess reports that use-sessreg in /etc/X11/wdm/ produces ut_line entries like :0, and a write to /dev/:0 fails. */ @@ -173,16 +176,13 @@ main(int argc, char **argv) { exit(EXIT_SUCCESS); } -char * -makemsg(char *fname, size_t *mbufsize, int print_banner) +static char *makemsg(char *fname, char **mvec, int mvecsz, + size_t *mbufsize, int print_banner) { register int ch, cnt; - struct tm *lt; - struct passwd *pw; struct stat sbuf; - time_t now; FILE *fp; - char *p, *whom, *where, *lbuf, *tmpname, *mbuf; + char *p, *lbuf, *tmpname, *mbuf; long line_max; line_max = sysconf(_SC_LINE_MAX); @@ -195,6 +195,10 @@ makemsg(char *fname, size_t *mbufsize, int print_banner) if (print_banner == TRUE) { char *hostname = xgethostname(); + char *whom, *where, *date; + struct passwd *pw; + time_t now; + if (!(whom = getlogin()) || !*whom) whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; if (!whom) { @@ -205,9 +209,12 @@ makemsg(char *fname, size_t *mbufsize, int print_banner) if (!where) { where = "somewhere"; warn(_("cannot get tty name")); - } + } else if (strncmp(where, "/dev/", 5) == 0) + where += 5; + time(&now); - lt = localtime(&now); + date = xstrdup(ctime(&now)); + date[strlen(date) - 1] = '\0'; /* * all this stuff is to blank out a square for the message; @@ -219,44 +226,66 @@ makemsg(char *fname, size_t *mbufsize, int print_banner) /* snprintf is not always available, but the sprintf's here will not overflow as long as %d takes at most 100 chars */ fprintf(fp, "\r%79s\r\n", " "); - sprintf(lbuf, _("Broadcast Message from %s@%s"), - whom, hostname); - free(hostname); + sprintf(lbuf, _("Broadcast message from %s@%s (%s) (%s):"), + whom, hostname, where, date); fprintf(fp, "%-79.79s\007\007\r\n", lbuf); - sprintf(lbuf, " (%s) at %d:%02d ...", - where, lt->tm_hour, lt->tm_min); - fprintf(fp, "%-79.79s\r\n", lbuf); + free(hostname); + free(date); } fprintf(fp, "%79s\r\n", " "); + if (mvec) { + /* + * Read message from argv[] + */ + int i; - if (fname) { + for (i = 0; i < mvecsz; i++) { + fputs(mvec[i], fp); + if (i < mvecsz - 1) + fputc(' ', fp); + } + fputc('\r', fp); + fputc('\n', fp); + + } else { /* - * When we are not root, but suid or sgid, refuse to read files - * (e.g. device files) that the user may not have access to. - * After all, our invoker can easily do "wall < file" - * instead of "wall file". + * read message from <file> */ - uid_t uid = getuid(); - if (uid && (uid != geteuid() || getgid() != getegid())) - errx(EXIT_FAILURE, _("will not read %s - use stdin."), - fname); + if (fname) { + /* + * When we are not root, but suid or sgid, refuse to read files + * (e.g. device files) that the user may not have access to. + * After all, our invoker can easily do "wall < file" + * instead of "wall file". + */ + uid_t uid = getuid(); + if (uid && (uid != geteuid() || getgid() != getegid())) + errx(EXIT_FAILURE, _("will not read %s - use stdin."), + fname); - if (!freopen(fname, "r", stdin)) - err(EXIT_FAILURE, _("cannot open %s"), fname); - } + if (!freopen(fname, "r", stdin)) + err(EXIT_FAILURE, _("cannot open %s"), fname); - while (fgets(lbuf, line_max, stdin)) { - for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) { - if (cnt == 79 || ch == '\n') { - for (; cnt < 79; ++cnt) - putc(' ', fp); - putc('\r', fp); - putc('\n', fp); - cnt = 0; + } + + /* + * Read message from stdin. + */ + while (fgets(lbuf, line_max, stdin)) { + for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) { + if (cnt == 79 || ch == '\n') { + for (; cnt < 79; ++cnt) + putc(' ', fp); + putc('\r', fp); + putc('\n', fp); + cnt = 0; + } + if (ch == '\t') + cnt += (7 - (cnt % 8)); + if (ch != '\n') + carefulputc(ch, fp, '^'); } - if (ch != '\n') - carefulputc(ch, fp); } } fprintf(fp, "%79s\r\n", " "); |
