2 * Copyright (c) 1991 - 1993, Julianne Frances Haugh
3 * Copyright (c) 1996 - 2000, Marek Michałkiewicz
4 * Copyright (c) 2001 - 2006, Tomasz Kłoczko
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the copyright holders or contributors may not be used to
16 * endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include <sys/types.h>
42 #include "prototypes.h"
48 #ifndef DEFAULT_HUP_MESG
49 #define DEFAULT_HUP_MESG _("login time exceeded\n\n")
53 #define HUP_MESG_FILE "/etc/logoutd.mesg"
57 static int check_login (const struct utmpx *);
59 static int check_login (const struct utmp *);
63 * check_login - check if user (struct utmpx/utmp) allowed to stay logged in
66 static int check_login (const struct utmpx *ut)
68 static int check_login (const struct utmp *ut)
71 char user[sizeof (ut->ut_user) + 1];
75 * ut_user may not have the terminating NUL.
77 strncpy (user, ut->ut_user, sizeof (ut->ut_user));
78 user[sizeof (ut->ut_user)] = '\0';
83 * Check if they are allowed to be logged in right now.
85 if (!isttytime (user, ut->ut_line, now)) {
92 static void send_mesg_to_tty (int tty_fd)
95 FILE *mesg_file, *tty_file;
99 tty_file = fdopen (tty_fd, "w");
100 if (NULL == tty_file) {
104 is_tty = (GTTY (tty_fd, &oldt) == 0);
106 /* Suggested by Ivan Nejgebauar <ian@unsux.ns.ac.yu>:
107 set OPOST before writing the message. */
109 newt.c_oflag |= OPOST;
110 STTY (tty_fd, &newt);
113 mesg_file = fopen (HUP_MESG_FILE, "r");
114 if (NULL != mesg_file) {
115 while ((c = getc (mesg_file)) != EOF) {
117 putc ('\r', tty_file);
123 fputs (DEFAULT_HUP_MESG, tty_file);
129 STTY (tty_fd, &oldt);
135 * logoutd - logout daemon to enforce /etc/porttime file policy
137 * logoutd is started at system boot time and enforces the login
138 * time and port restrictions specified in /etc/porttime. The
139 * utmpx/utmp file is periodically scanned and offending users are logged
140 * off from the system.
142 int main (int argc, char **argv)
153 char user[sizeof (ut->ut_user) + 1]; /* terminating NUL */
154 char tty_name[sizeof (ut->ut_line) + 6]; /* /dev/ + NUL */
157 (void) setlocale (LC_ALL, "");
158 (void) bindtextdomain (PACKAGE, LOCALEDIR);
159 (void) textdomain (PACKAGE);
162 for (i = 0; close (i) == 0; i++);
167 * Put this process in the background.
173 } else if (pid < 0) {
181 * Start syslogging everything
183 Prog = Basename (argv[0]);
188 * Scan the utmpx/utmp file once per minute looking for users that
189 * are not supposed to still be logged in.
194 * Attempt to re-open the utmpx/utmp file. The file is only
195 * open while it is being used.
204 * Read all of the entries in the utmpx/utmp file. The entries
205 * for login sessions will be checked to see if the user
206 * is permitted to be signed on at this time.
209 while ((ut = getutxent ()) != NULL) {
211 while ((ut = getutent ()) != NULL) {
213 if (ut->ut_type != USER_PROCESS) {
216 if (ut->ut_user[0] == '\0') {
219 if (check_login (ut)) {
224 * Put the rest of this in a child process. This
225 * keeps the scan from waiting on other ports to die.
232 } else if (pid < 0) {
233 /* failed - give up until the next scan */
238 if (strncmp (ut->ut_line, "/dev/", 5) != 0) {
239 strcpy (tty_name, "/dev/");
244 strcat (tty_name, ut->ut_line);
249 open (tty_name, O_WRONLY | O_NDELAY | O_NOCTTY);
251 send_mesg_to_tty (tty_fd);
256 if (ut->ut_pid > 1) {
257 kill (-ut->ut_pid, SIGHUP);
259 kill (-ut->ut_pid, SIGKILL);
262 strncpy (user, ut->ut_user, sizeof (user) - 1);
263 user[sizeof (user) - 1] = '\0';
266 "logged off user `%s' on `%s'", user,
270 * This child has done all it can, drop dead.
285 * Reap any dead babies ...
287 while (wait (&status) != -1);