|
root / base / usr / src / zyginit / services / console-login / write_login_utmpx.c
write_login_utmpx.c C 57 lines 1.6 KB
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
 * write_login_utmpx — write a LOGIN_PROCESS utmpx entry for a target PID.
 *
 * Usage: write_login_utmpx <ut_id> <ut_line> <ut_pid>
 *
 * Background: illumos `login(1)` walks utmpx and requires an entry whose
 * ut_pid matches login's own PID. ttymon updates an existing entry via
 * pututxline() — it does NOT create one. Standard illumos init writes
 * INIT_PROCESS entries when spawning getty/ttymon from inittab; zyginit
 * doesn't, so ttymon has nothing to update and login eventually errors
 * out with "No utmpx entry. You must exec login from the lowest level
 * shell."
 *
 * This helper writes a LOGIN_PROCESS entry for a target PID and exits.
 * Called from console-login/start.sh just before `exec ttymon`, with
 * $$ (the wrapper script's PID, which becomes ttymon's PID after exec)
 * as the third argument.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <utmpx.h>

int
main(int argc, char **argv)
{
	struct utmpx ux;
	pid_t target_pid;

	if (argc < 4) {
		(void) fprintf(stderr,
		    "Usage: %s <ut_id> <ut_line> <ut_pid>\n", argv[0]);
		return (1);
	}

	target_pid = (pid_t)atoi(argv[3]);

	(void) memset(&ux, 0, sizeof (ux));
	(void) strncpy(ux.ut_id, argv[1], sizeof (ux.ut_id));
	(void) strncpy(ux.ut_line, argv[2], sizeof (ux.ut_line));
	(void) strncpy(ux.ut_user, "LOGIN", sizeof (ux.ut_user));
	ux.ut_pid = target_pid;
	ux.ut_type = LOGIN_PROCESS;
	(void) time(&ux.ut_tv.tv_sec);

	setutxent();
	if (pututxline(&ux) == NULL) {
		(void) fprintf(stderr, "%s: pututxline failed\n", argv[0]);
		endutxent();
		return (1);
	}
	endutxent();

	return (0);
}