From 82e4ad2efd34cffaed26e620fcde2ca6090a648a Mon Sep 17 00:00:00 2001 From: Aaron Ball Date: Sat, 27 Jun 2015 00:29:14 -0600 Subject: Initial commit of terminus source code This version is fully working, though it is still lacking in some functionality. --- Makefile | 7 +++ src/main.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 Makefile create mode 100644 src/main.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cdae433 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +out = terminus + +all: + cc src/main.c -lm -o $(out) + +debug: + make all dbg="-g" diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c36ac6e --- /dev/null +++ b/src/main.c @@ -0,0 +1,200 @@ +#include +#include +#include +#include +#include + +// +// Converts the given day count to seconds (multiplies by the number of seconds +// in a day, 86400). +// +// @param days Day count to convert to seconds +// +// @return long Number of total seconds in the given day duration +// +long days_to_seconds(int days) { + return days * 86400; +} + + +// +// Converts the given "string integer" to a long datatype. This is useful for +// programs that take command line arguments from the user and they need to +// treats those arguments like actual numbers. +// +// @param intstr Integer string +// +// @return long The integer represented by the given string +// +long ctoi(char* intstr) { + // TODO: This doesn't work yet + int i = 0; + long out = 0; + + while(intstr[i] != '\0') { + //printf("%d\n", intstr[i] - 48); + if(intstr[i] == '0') { + out += pow(10,i); + } else { + out += (intstr[i] - 48) + pow(10,i); + } + i++; + } + return out; +} + + +// +// +// +int get_user_home(char* out) { + if(getenv("HOME") != NULL) { + strcpy(out, getenv("HOME")); + return 0; + } else { + return 1; + } +} + + +// +// Writes the current timestamp to the specified lastlogin file +// +// @param path Path to the lastlogin file +// +// @return int Status of the write operation +// +int write_lastlogin(char* path) { + FILE* f = fopen(path, "w+"); + + // Exit if file cannot be opened for writing + if(f == NULL) { return 1; } + + // Write the current time + fprintf(f, "%d", time(NULL)); + + fclose(f); + return 0; +} + + +// +// Gets the time_t value contained in the specified lastlogin file. +// +// @param lastlogin_path Path to the lastlogin file to be read +// @param lastlogin Output time_t variable +// +// @return int Status of reading the lastlogin file +// +int get_lastlogin(char* lastlogin_path, time_t* lastlogin) { + // File pointer to lastlogin file (used for reading and writing) + FILE* lastlogin_file; + // String contents of the lastlogin file + char lastlogin_str[32]; + + // Attempt read lastlogin file contents + lastlogin_file = fopen(lastlogin_path, "r"); + + if(lastlogin_file == NULL) { + return 1; + } else { + // Read the lastlogin file and set its value to lastlogin + fgets(lastlogin_str, 32, lastlogin_file); + *lastlogin = atoi(lastlogin_str); + fclose(lastlogin_file); + } + return 0; +} + + +// +// Executes the specified command, printing the output. +// Note that this does read the calling shell's environmental variables, and so +// absolute paths are not necessary if the command targets an executable in +// PATH. +// +// @param cmd Command to be executed and output to be printed +// +// @return int Execution status of the command +// Note that if the command fails execution at start, -1 is +// returned. +// +int exec_cmd(char* cmd) { + FILE* p = popen(cmd, "r"); + if(p == NULL) { return -1; } + + // Buffer for each line + char line[256]; + // For each line, print the output + while (fgets(line, sizeof(line)-1, p) != NULL) { + printf("%s", line); + } + + return pclose(p); +} + + +// +// Ye olde main function +// +int main(int argc, char* argv[]) { + char home[128]; + int days; + char* cmd; + // Expected path to lastlogin file + char lastlogin_path[256]; + // Time-related variables + time_t now; + time_t threshold; + time_t lastlogin; + + if(argc < 3) { + printf( + "Please specify a timeout threshold (in days) as well as a command\n" + "or commands to be run if the threshold is exceeded.\n\n" + "Example:\n" + " terminus 5 ''\n\n" + "This example will execute the given command if the user has not\n" + "logged in in the last 5 days.\n\n" + ); + return 1; + } + + // Get program arguments + days = atoi(argv[1]); + cmd = argv[2]; + + // Compose path to lastlogin file + get_user_home(home); + strcpy(lastlogin_path, home); + strcat(lastlogin_path, "/.lastlogin"); + + // Set time-related values + now = time(NULL); + threshold = days_to_seconds(days); + if(get_lastlogin(lastlogin_path, &lastlogin) == 1) { + // Create lastlogin file since it doesn't exist + printf("Lastlogin file could not be read. Writing\n"); + if(write_lastlogin(lastlogin_path) == 1) { + printf("Failure writing lastlogin\n"); + return 1; + } + // Go ahead and set lastlogin time, since writing it means we're using + // "now". + lastlogin = time(NULL); + } + + // Determine if I'm dead + if((now - lastlogin) > threshold) { + printf("You're dead!\n"); + exec_cmd(cmd); + } else { + if(write_lastlogin(lastlogin_path) == 1) { + printf("Failure writing lastlogin\n"); + return 1; + } + printf("You're not dead!\n"); + } + + return 0; +} -- cgit v1.2.3