summaryrefslogtreecommitdiff
path: root/src/main.c
blob: 016a2e99e021c5885d9f950480ec3e42ac03ca86 (plain)
    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 #include <math.h>
   22 
   23 
   24 /**
   25  * Converts the given day count to seconds (multiplies by the number of seconds
   26  * in a day, 86400).
   27  *
   28  * @param days Day count to convert to seconds
   29  *
   30  * @return long Number of total seconds in the given day duration
   31  */
   32 long days_to_seconds(int days) {
   33   return days * 86400;
   34 }
   35 
   36 
   37 /**
   38  * Converts the given "string integer" to a long datatype. This is useful for
   39  * programs that take command line arguments from the user and they need to
   40  * treats those arguments like actual numbers.
   41  * 
   42  * @param intstr Integer string
   43  * 
   44  * @return long The integer represented by the given string
   45  */
   46 long ctoi(char* intstr) {
   47   // TODO: This doesn't work yet
   48   int i = 0;
   49   long out = 0;
   50 
   51   while(intstr[i] != '\0') {
   52     //printf("%d\n", intstr[i] - 48);
   53     if(intstr[i] == '0') {
   54       out += pow(10,i);
   55     } else {
   56       out += (intstr[i] - 48) + pow(10,i);
   57     }
   58     i++;
   59   }
   60   return out;
   61 }
   62 
   63 
   64 /**
   65  * TODO
   66  */
   67 int get_user_home(char* out) {
   68   if(getenv("HOME") != NULL) {
   69     strcpy(out, getenv("HOME"));
   70     return 0;
   71   } else {
   72     return 1;
   73   }
   74 }
   75 
   76 
   77 /**
   78  * Writes the current timestamp to the specified lastlogin file
   79  * 
   80  * @param path Path to the lastlogin file
   81  * 
   82  * @return int Status of the write operation
   83  */
   84 int write_lastlogin(char* path) {
   85   FILE* f = fopen(path, "w+");
   86 
   87   // Exit if file cannot be opened for writing
   88   if(f == NULL) { return 1; }
   89 
   90   // Write the current time
   91   fprintf(f, "%d", time(NULL));
   92 
   93   fclose(f);
   94   return 0;
   95 }
   96 
   97 
   98 /**
   99  * Gets the time_t value contained in the specified lastlogin file.
  100  *
  101  * @param lastlogin_path Path to the lastlogin file to be read
  102  * @param lastlogin Output time_t variable
  103  *
  104  * @return int Status of reading the lastlogin file
  105  */
  106 int get_lastlogin(char* lastlogin_path, time_t* lastlogin) {
  107   // File pointer to lastlogin file (used for reading and writing)
  108   FILE* lastlogin_file;
  109   // String contents of the lastlogin file
  110   char lastlogin_str[32];
  111 
  112   // Attempt read lastlogin file contents
  113   lastlogin_file = fopen(lastlogin_path, "r");
  114   
  115   if(lastlogin_file == NULL) {
  116     return 1;
  117   } else {
  118     // Read the lastlogin file and set its value to lastlogin
  119     fgets(lastlogin_str, 32, lastlogin_file);
  120     *lastlogin = atoi(lastlogin_str);
  121     fclose(lastlogin_file);
  122   }
  123   return 0;
  124 }
  125 
  126 
  127 /**
  128  * Executes the specified command, printing the output.
  129  * Note that this does read the calling shell's environmental variables, and so
  130  * absolute paths are not necessary if the command targets an executable in
  131  * PATH.
  132  * 
  133  * @param cmd Command to be executed and output to be printed
  134  * 
  135  * @return int Execution status of the command
  136  *             Note that if the command fails execution at start, -1 is
  137  *             returned.
  138  */
  139 int exec_cmd(char* cmd) {
  140   FILE* p = popen(cmd, "r");
  141   if(p == NULL) { return -1; }
  142 
  143   // Buffer for each line
  144   char line[256];
  145   // For each line, print the output
  146   while (fgets(line, sizeof(line)-1, p) != NULL) {
  147     printf("%s", line);
  148   }
  149 
  150   return pclose(p);
  151 }
  152 
  153 
  154 /**
  155  * Ye olde main function
  156  */
  157 int main(int argc, char* argv[]) {
  158   char home[128];
  159   int days;
  160   char* cmd;
  161   // Expected path to lastlogin file
  162   char lastlogin_path[256];
  163   // Time-related variables
  164   time_t now;
  165   time_t threshold;
  166   time_t lastlogin;
  167 
  168   if(argc < 3) {
  169     printf(
  170       "Please specify a timeout threshold (in days) as well as a command\n"
  171       "or commands to be run if the threshold is exceeded.\n\n"
  172       "Example:\n"
  173       "  terminus 5 '<command to execute>'\n\n"
  174       "This example will execute the given command if the user has not\n"
  175       "logged in in the last 5 days.\n\n"
  176     );
  177     return 1;
  178   }
  179 
  180   // Get program arguments
  181   days = atoi(argv[1]);
  182   cmd = argv[2];
  183 
  184   // Compose path to lastlogin file
  185   get_user_home(home);
  186   strcpy(lastlogin_path, home);
  187   strcat(lastlogin_path, "/.lastlogin");
  188 
  189   // Set time-related values
  190   now = time(NULL);
  191   threshold = days_to_seconds(days);
  192   if(get_lastlogin(lastlogin_path, &lastlogin) == 1) {
  193     // Create lastlogin file since it doesn't exist
  194     printf("Lastlogin file could not be read. Writing\n");
  195     if(write_lastlogin(lastlogin_path) == 1) {
  196       printf("Failure writing lastlogin\n");
  197       return 1;
  198     }
  199     // Go ahead and set lastlogin time, since writing it means we're using
  200     // "now".
  201     lastlogin = time(NULL);
  202   }
  203 
  204   // Determine if I'm dead
  205   if((now - lastlogin) > threshold) {
  206     printf("You're dead!\n");
  207     exec_cmd(cmd);
  208   } else {
  209     if(write_lastlogin(lastlogin_path) == 1) {
  210       printf("Failure writing lastlogin\n");
  211       return 1;
  212     }
  213     printf("You're not dead!\n");
  214   }
  215   
  216   return 0;
  217 }

Generated by cgit