1 /**
2 * Copyright (C) 2015 Aaron Ball <nullspoon@iohq.net>
3 *
4 * Terminus is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Terminus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with terminus. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21
22
23 /**
24 * Converts the given day count to seconds (multiplies by the number of seconds
25 * in a day, 86400).
26 *
27 * @param days Day count to convert to seconds
28 *
29 * @return long Number of total seconds in the given day duration
30 */
31 long days_to_seconds(int days) {
32 return days * 86400;
33 }
34
35
36 /**
37 * TODO
38 */
39 int get_user_home(char* out) {
40 if(getenv("HOME") != NULL) {
41 strcpy(out, getenv("HOME"));
42 return 0;
43 } else {
44 return 1;
45 }
46 }
47
48
49 /**
50 * Writes the current timestamp to the specified lastlogin file
51 *
52 * @param path Path to the lastlogin file
53 *
54 * @return int Status of the write operation
55 */
56 int write_lastlogin(char* path) {
57 FILE* f = fopen(path, "w+");
58
59 // Exit if file cannot be opened for writing
60 if(f == NULL) { return 1; }
61
62 // Write the current time
63 fprintf(f, "%d", time(NULL));
64
65 fclose(f);
66 return 0;
67 }
68
69
70 /**
71 * Gets the time_t value contained in the specified lastlogin file.
72 *
73 * @param lastlogin_path Path to the lastlogin file to be read
74 * @param lastlogin Output time_t variable
75 *
76 * @return int Status of reading the lastlogin file
77 */
78 int get_lastlogin(char* lastlogin_path, time_t* lastlogin) {
79 // File pointer to lastlogin file (used for reading and writing)
80 FILE* lastlogin_file;
81 // String contents of the lastlogin file
82 char lastlogin_str[32];
83
84 // Attempt read lastlogin file contents
85 lastlogin_file = fopen(lastlogin_path, "r");
86
87 if(lastlogin_file == NULL) {
88 return 1;
89 } else {
90 // Read the lastlogin file and set its value to lastlogin
91 fgets(lastlogin_str, 32, lastlogin_file);
92 *lastlogin = atoi(lastlogin_str);
93 fclose(lastlogin_file);
94 }
95 return 0;
96 }
97
98
99 /**
100 * Executes the specified command, printing the output.
101 * Note that this does read the calling shell's environmental variables, and so
102 * absolute paths are not necessary if the command targets an executable in
103 * PATH.
104 *
105 * @param cmd Command to be executed and output to be printed
106 *
107 * @return int Execution status of the command
108 * Note that if the command fails execution at start, -1 is
109 * returned.
110 */
111 int exec_cmd(char* cmd) {
112 FILE* p = popen(cmd, "r");
113 if(p == NULL) { return -1; }
114
115 // Buffer for each line
116 char line[256];
117 // For each line, print the output
118 while (fgets(line, sizeof(line)-1, p) != NULL) {
119 printf("%s", line);
120 }
121
122 return pclose(p);
123 }
124
125
126 /**
127 * Ye olde main function
128 */
129 int main(int argc, char* argv[]) {
130 char home[128];
131 int days;
132 char* cmd;
133 // Expected path to lastlogin file
134 char lastlogin_path[256];
135 // Time-related variables
136 time_t now;
137 time_t threshold;
138 time_t lastlogin;
139
140 if(argc < 3) {
141 printf(
142 "Please specify a timeout threshold (in days) as well as a command\n"
143 "or commands to be run if the threshold is exceeded.\n\n"
144 "[1mExample:[0m\n"
145 " terminus 5 '<command to execute>'\n\n"
146 "This example will execute the given command if the user has not\n"
147 "logged in in the last 5 days.\n\n"
148 );
149 return 1;
150 }
151
152 // Get program arguments
153 days = atoi(argv[1]);
154 cmd = argv[2];
155
156 // Compose path to lastlogin file
157 get_user_home(home);
158 strcpy(lastlogin_path, home);
159 strcat(lastlogin_path, "/.lastlogin");
160
161 // Set time-related values
162 now = time(NULL);
163 threshold = days_to_seconds(days);
164 if(get_lastlogin(lastlogin_path, &lastlogin) == 1) {
165 // Create lastlogin file since it doesn't exist
166 printf("Lastlogin file could not be read. Writing\n");
167 if(write_lastlogin(lastlogin_path) == 1) {
168 printf("Failure writing lastlogin\n");
169 return 1;
170 }
171 // Go ahead and set lastlogin time, since writing it means we're using
172 // "now".
173 lastlogin = time(NULL);
174 }
175
176 // Determine if I'm dead
177 if((now - lastlogin) > threshold) {
178 printf("You're dead!\n");
179 exec_cmd(cmd);
180 } else {
181 if(write_lastlogin(lastlogin_path) == 1) {
182 printf("Failure writing lastlogin\n");
183 return 1;
184 }
185 printf("You're not dead!\n");
186 }
187
188 return 0;
189 }
|