.I /etc/pam.d/remote
).
+
+.SH CONFIG FILE ITEMS
+.B login
+reads the
+.IR /etc/login.defs (5)
+configuration file. Note that the configuration file could be distributed with
+another package (e.g. shadow-utils). The following configuration items are
+relevant for
+.BR login (1):
+.PP
+\fBMOTD_FILE\fR (string)
+.RS 4
+If defined, ":" delimited list of "message of the day" files to be displayed
+upon login. The default value is "/etc/motd". If the \fBMOTD_FILE\fR item is
+empty or "quiet" login is enabled then the message of the day is not displayed.
+Note that the same functionality is also provided by
+.BR pam_motd (8)
+PAM module.
+.RE
+
.SH FILES
.nf
.I /var/run/utmp
#include <grp.h>
#include <pwd.h>
#include <utmp.h>
-#include <setjmp.h>
#include <stdlib.h>
#include <sys/syslog.h>
#include <sys/sysmacros.h>
#include <lastlog.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>
+#include <sys/sendfile.h>
#ifdef HAVE_LIBAUDIT
# include <libaudit.h>
#include "xalloc.h"
#include "writeall.h"
+#include "logindefs.h"
+
#define is_pam_failure(_rc) ((_rc) != PAM_SUCCESS)
#define LOGIN_MAX_TRIES 3
static int child_pid = 0;
static volatile int got_sig = 0;
-jmp_buf motdinterrupt;
-
/*
* Robert Ambrose writes:
* A couple of my users have a problem with login processes hanging around
kill(-child_pid, SIGHUP); /* because the shell often ignores SIGTERM */
}
-static void sigint(int sig __attribute__ ((__unused__)))
-{
- longjmp(motdinterrupt, 1);
-}
-
-
/* Should not be called from PAM code... */
static void sleepexit(int eval)
{
exit(eval);
}
+/*
+ * Output the /etc/motd file
+ *
+ * motd() determines the name of a login announcement file and outputs it to
+ * the user's terminal at login time. The MOTD_FILE configuration option is a
+ * colon-delimited list of filenames. The empty MOTD_FILE option disables motd
+ * printing at all.
+ */
static void motd(void)
{
- int fd, nchars;
- void (*oldint) (int);
- char tbuf[8192];
+ char *motdlist, *motdfile, *cp;
+ const char *mb;
- if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
+ mb = getlogindefs_str("MOTD_FILE", _PATH_MOTDFILE);
+ if (!mb || !*mb)
return;
- oldint = signal(SIGINT, sigint);
- if (setjmp(motdinterrupt) == 0)
- while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) {
- if (write(fileno(stdout), tbuf, nchars)) {
- ; /* glibc warn_unused_result */
- }
- }
- signal(SIGINT, oldint);
- close(fd);
+
+ motdlist = xstrdup(mb);
+
+ for (cp = motdlist; (motdfile = strtok(cp, ":")); cp = NULL) {
+ struct stat st;
+ int fd;
+
+ if (stat(motdfile, &st) || !st.st_size)
+ continue;
+ fd = open(motdfile, O_RDONLY, 0);
+ if (fd < 0)
+ continue;
+
+ sendfile(fileno(stdout), fd, NULL, st.st_size);
+ close(fd);
+ }
}
/*