chiark / gitweb /
tree-wide: drop 'This file is part of systemd' blurb
[elogind.git] / src / shared / utmp-wtmp.c
index 7fb6fe3a6751602718039b2a8da55772cbaca2e7..1d58a5a2e0f1efb39ba1fb0e21275667b6e814b8 100644 (file)
@@ -1,34 +1,30 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
-  This file is part of systemd.
-
   Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <utmpx.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <sys/time.h>
 #include <sys/utsname.h>
-#include <fcntl.h>
 #include <unistd.h>
-#include <poll.h>
+#include <utmpx.h>
 
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "hostname-util.h"
 #include "macro.h"
 #include "path-util.h"
+#include "string-util.h"
+#include "terminal-util.h"
+#include "time-util.h"
+#include "user-util.h"
+#include "util.h"
 #include "utmp-wtmp.h"
 
 int utmp_get_runlevel(int *runlevel, int *previous) {
@@ -202,12 +198,13 @@ _pure_ static const char *sanitize_id(const char *id) {
         return id + l - sizeof(((struct utmpx*) NULL)->ut_id);
 }
 
-int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line) {
+int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user) {
         struct utmpx store = {
                 .ut_type = INIT_PROCESS,
                 .ut_pid = pid,
                 .ut_session = sid,
         };
+        int r;
 
         assert(id);
 
@@ -219,7 +216,26 @@ int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line
         if (line)
                 strncpy(store.ut_line, basename(line), sizeof(store.ut_line));
 
-        return write_entry_both(&store);
+        r = write_entry_both(&store);
+        if (r < 0)
+                return r;
+
+        if (IN_SET(ut_type, LOGIN_PROCESS, USER_PROCESS)) {
+                store.ut_type = LOGIN_PROCESS;
+                r = write_entry_both(&store);
+                if (r < 0)
+                        return r;
+        }
+
+        if (ut_type == USER_PROCESS) {
+                store.ut_type = USER_PROCESS;
+                strncpy(store.ut_user, user, sizeof(store.ut_user)-1);
+                r = write_entry_both(&store);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
 }
 
 int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
@@ -257,7 +273,6 @@ int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
         return write_utmp_wtmp(&store, &store_wtmp);
 }
 
-
 int utmp_put_runlevel(int runlevel, int previous) {
         struct utmpx store = {};
         int r;
@@ -299,7 +314,7 @@ static int write_to_terminal(const char *tty, const char *message) {
         assert(tty);
         assert(message);
 
-        fd = open(tty, O_WRONLY|O_NDELAY|O_NOCTTY|O_CLOEXEC);
+        fd = open(tty, O_WRONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC);
         if (fd < 0 || !isatty(fd))
                 return -errno;
 
@@ -346,8 +361,14 @@ static int write_to_terminal(const char *tty, const char *message) {
         return 0;
 }
 
-int utmp_wall(const char *message, const char *username, bool (*match_tty)(const char *tty)) {
-        _cleanup_free_ char *text = NULL, *hn = NULL, *un = NULL, *tty = NULL;
+int utmp_wall(
+        const char *message,
+        const char *username,
+        const char *origin_tty,
+        bool (*match_tty)(const char *tty, void *userdata),
+        void *userdata) {
+
+        _cleanup_free_ char *text = NULL, *hn = NULL, *un = NULL, *stdin_tty = NULL;
         char date[FORMAT_TIMESTAMP_MAX];
         struct utmpx *u;
         int r;
@@ -361,14 +382,17 @@ int utmp_wall(const char *message, const char *username, bool (*match_tty)(const
                         return -ENOMEM;
         }
 
-        getttyname_harder(STDIN_FILENO, &tty);
+        if (!origin_tty) {
+                getttyname_harder(STDIN_FILENO, &stdin_tty);
+                origin_tty = stdin_tty;
+        }
 
         if (asprintf(&text,
                      "\a\r\n"
                      "Broadcast message from %s@%s%s%s (%s):\r\n\r\n"
                      "%s\r\n\r\n",
                      un ?: username, hn,
-                     tty ? " on " : "", strempty(tty),
+                     origin_tty ? " on " : "", strempty(origin_tty),
                      format_timestamp(date, sizeof(date), now(CLOCK_REALTIME)),
                      message) < 0)
                 return -ENOMEM;
@@ -385,7 +409,7 @@ int utmp_wall(const char *message, const char *username, bool (*match_tty)(const
                 if (u->ut_type != USER_PROCESS || u->ut_user[0] == 0)
                         continue;
 
-                /* this access is fine, because strlen("/dev/") << 32 (UT_LINESIZE) */
+                /* this access is fine, because STRLEN("/dev/") << 32 (UT_LINESIZE) */
                 if (path_startswith(u->ut_line, "/dev/"))
                         path = u->ut_line;
                 else {
@@ -395,7 +419,7 @@ int utmp_wall(const char *message, const char *username, bool (*match_tty)(const
                         path = buf;
                 }
 
-                if (!match_tty || match_tty(path)) {
+                if (!match_tty || match_tty(path, userdata)) {
                         q = write_to_terminal(path, text);
                         if (q < 0)
                                 r = q;