change login detection to `true'
[tlock.git] / tlock.c
bloba1c58ad2002a52f0c1851f3bc04f5a541b6a85c9
1 /*
2 * Copyright (c) 2017, S. Gilles <sgilles@math.umd.edu>
4 * Permission to use, copy, modify, and/or distribute this software
5 * for any purpose with or without fee is hereby granted, provided
6 * that the above copyright notice and this permission notice appear
7 * in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
13 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
14 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <errno.h>
20 #include <pwd.h>
21 #include <signal.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/ioctl.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <termios.h>
29 #include <time.h>
30 #include <unistd.h>
32 #include "macros.h"
34 static void jack(int s)
36 UNUSED(s);
39 static int get_username(const char **out_username)
41 struct passwd *passwd;
43 errno = 0;
45 if (!(passwd = getpwuid(getuid()))) {
46 PERROR_MESSAGE("getpwuid");
48 return -1;
51 *out_username = passwd->pw_name;
53 return 0;
56 static void redraw_screen(int failed)
58 struct winsize ws;
59 struct timespec req = { .tv_sec = 0, .tv_nsec = 500000000 };
60 int midcol = 0;
62 ioctl(fileno(stdin), TIOCGWINSZ, &ws);
63 printf("\033[2J");
65 if (failed) {
66 printf("\033[48;2;%d;%d;%dm", 0xcc, 0x33, 0x33);
67 } else {
68 printf("\033[48;2;%d;%d;%dm", 0x88, 0x88, 0x88);
71 for (int row = 0; row <= ws.ws_row; ++row) {
72 printf("\033[%d;0f", row);
74 for (int j = 0; j < ws.ws_col; ++j) {
75 printf(" ");
79 printf("\033[0m");
80 fflush(stdout);
81 printf("\033[%d;%df", ws.ws_row / 2 - 1, 0);
82 nanosleep(&req, 0);
83 req.tv_nsec = 500000000 / ws.ws_col;
84 midcol = ws.ws_col / 2;
86 for (int j = 0; j <= ws.ws_col / 2 + 1; ++j) {
87 nanosleep(&req, 0);
89 /* left */
90 if (midcol - j >= 0) {
91 printf("\033[%d;%df", ws.ws_row / 2 - 1, midcol - j);
92 printf("─");
93 printf("\033[%d;%df", ws.ws_row / 2, midcol - j);
94 printf(" ");
95 printf("\033[%d;%df", ws.ws_row / 2 + 1, midcol - j);
96 printf("─");
99 /* right */
100 if (midcol + j <= ws.ws_col) {
101 printf("\033[%d;%df", ws.ws_row / 2 - 1, midcol + j);
102 printf("─");
103 printf("\033[%d;%df", ws.ws_row / 2, midcol + j);
104 printf(" ");
105 printf("\033[%d;%df", ws.ws_row / 2 + 1, midcol + j);
106 printf("─");
109 fflush(stdout);
112 fflush(stdout);
113 printf("\033[%d;%df", ws.ws_row / 2, 5);
114 fflush(stdout);
117 static void get_correct_password(const char *username)
119 pid_t pid = 0;
120 int status = 0;
121 int failed_yet = 0;
123 while (1) {
124 redraw_screen(failed_yet);
125 pid = fork();
127 if (!pid) {
128 /* We are child */
129 execl("/bin/su", "su", "-", username, "-c", "true",
130 (char *) 0);
131 _exit(-1);
134 if (waitpid(pid, &status, 0) < 0) {
135 /* Waitpid failed. Too bad, user */
136 continue;
139 if (WIFEXITED(status) &&
140 WEXITSTATUS(status) == 0) {
141 break;
144 failed_yet = 1;
148 static int ignore_signals(void)
150 struct sigaction sa = { .sa_handler = jack, .sa_flags = SA_RESTART };
152 sigfillset(&sa.sa_mask);
154 if (sigaction(SIGUSR1, &sa, 0) < 0) {
155 PERROR_MESSAGE("sigaction");
157 return -1;
160 if (sigaction(SIGUSR2, &sa, 0) < 0) {
161 PERROR_MESSAGE("sigaction");
163 return -1;
166 if (sigaction(SIGINT, &sa, 0) < 0) {
167 PERROR_MESSAGE("sigaction");
169 return -1;
172 if (sigaction(SIGTSTP, &sa, 0) < 0) {
173 PERROR_MESSAGE("sigaction");
175 return -1;
178 return 0;
181 int main(void)
183 const char *username = 0;
185 if (ignore_signals() < 0) {
186 goto done;
189 printf("\033[3J");
190 printf("\033[?25l");
191 fflush(stdout);
193 if (get_username(&username) < 0) {
194 goto done;
197 get_correct_password(username);
198 printf("\033[0m");
199 printf("\033[0;0f");
200 printf("\033[2J");
201 done:
202 printf("\033[?25h");
204 return 0;