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"
56 /* local function prototypes */
58 static int check_login (const struct utmpx *ut);
59 #else /* !USE_UTMPX */
60 static int check_login (const struct utmp *ut);
61 #endif /* !USE_UTMPX */
62 static void send_mesg_to_tty (int tty_fd);
65 * check_login - check if user (struct utmpx/utmp) allowed to stay logged in
68 static int check_login (const struct utmpx *ut)
69 #else /* !USE_UTMPX */
70 static int check_login (const struct utmp *ut)
71 #endif /* !USE_UTMPX */
73 char user[sizeof (ut->ut_user) + 1];
77 * ut_user may not have the terminating NUL.
79 strncpy (user, ut->ut_user, sizeof (ut->ut_user));
80 user[sizeof (ut->ut_user)] = '\0';
85 * Check if they are allowed to be logged in right now.
87 if (!isttytime (user, ut->ut_line, now)) {
94 static void send_mesg_to_tty (int tty_fd)
97 FILE *mesg_file, *tty_file;
100 tty_file = fdopen (tty_fd, "w");
101 if (NULL == tty_file) {
105 is_tty = (GTTY (tty_fd, &oldt) == 0);
107 /* Suggested by Ivan Nejgebauar <ian@unsux.ns.ac.yu>:
108 set OPOST before writing the message. */
110 newt.c_oflag |= OPOST;
111 STTY (tty_fd, &newt);
114 mesg_file = fopen (HUP_MESG_FILE, "r");
115 if (NULL != mesg_file) {
117 while ((c = getc (mesg_file)) != EOF) {
119 putc ('\r', tty_file);
125 fputs (DEFAULT_HUP_MESG, tty_file);
131 STTY (tty_fd, &oldt);
137 * logoutd - logout daemon to enforce /etc/porttime file policy
139 * logoutd is started at system boot time and enforces the login
140 * time and port restrictions specified in /etc/porttime. The
141 * utmpx/utmp file is periodically scanned and offending users are logged
142 * off from the system.
144 int main (int argc, char **argv)
152 #else /* !USE_UTMPX */
154 #endif /* !USE_UTMPX */
155 char user[sizeof (ut->ut_user) + 1]; /* terminating NUL */
156 char tty_name[sizeof (ut->ut_line) + 6]; /* /dev/ + NUL */
160 (void) fputs (_("Usage: logoutd\n"), stderr);
163 (void) setlocale (LC_ALL, "");
164 (void) bindtextdomain (PACKAGE, LOCALEDIR);
165 (void) textdomain (PACKAGE);
168 for (i = 0; close (i) == 0; i++);
173 * Put this process in the background.
179 } else if (pid < 0) {
187 * Start syslogging everything
189 Prog = Basename (argv[0]);
194 * Scan the utmpx/utmp file once per minute looking for users that
195 * are not supposed to still be logged in.
200 * Attempt to re-open the utmpx/utmp file. The file is only
201 * open while it is being used.
205 #else /* !USE_UTMPX */
207 #endif /* !USE_UTMPX */
210 * Read all of the entries in the utmpx/utmp file. The entries
211 * for login sessions will be checked to see if the user
212 * is permitted to be signed on at this time.
215 while ((ut = getutxent ()) != NULL)
216 #else /* !USE_UTMPX */
217 while ((ut = getutent ()) != NULL)
218 #endif /* !USE_UTMPX */
220 if (ut->ut_type != USER_PROCESS) {
223 if (ut->ut_user[0] == '\0') {
226 if (check_login (ut)) {
231 * Put the rest of this in a child process. This
232 * keeps the scan from waiting on other ports to die.
239 } else if (pid < 0) {
240 /* failed - give up until the next scan */
245 if (strncmp (ut->ut_line, "/dev/", 5) != 0) {
246 strcpy (tty_name, "/dev/");
251 strcat (tty_name, ut->ut_line);
256 open (tty_name, O_WRONLY | O_NDELAY | O_NOCTTY);
258 send_mesg_to_tty (tty_fd);
263 if (ut->ut_pid > 1) {
264 kill (-ut->ut_pid, SIGHUP);
266 kill (-ut->ut_pid, SIGKILL);
269 strncpy (user, ut->ut_user, sizeof (user) - 1);
270 user[sizeof (user) - 1] = '\0';
273 "logged off user '%s' on '%s'", user,
277 * This child has done all it can, drop dead.
284 #else /* !USE_UTMPX */
286 #endif /* !USE_UTMPX */
292 * Reap any dead babies ...
294 while (wait (&status) != -1);