Skip to content

Commit

Permalink
docs: add doc comments for posterity pt 1
Browse files Browse the repository at this point in the history
  • Loading branch information
exbotanical committed Nov 12, 2023
1 parent fc8b41d commit 3cbff2b
Show file tree
Hide file tree
Showing 19 changed files with 397 additions and 123 deletions.
2 changes: 2 additions & 0 deletions scripts/proc-count.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
ps aux | grep 'defunct' | grep -v 'grep' | awk '{print $2}' | wc -l
6 changes: 6 additions & 0 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
#include "commander/commander.h"
#include "constants.h"

/**
* Sets the log file CLI option.
*
* Optionally specify a path to which logs will be written.
* Otherwise, syslog or a comparable facility will be utilized.
*/
static void setopt_logfile(command_t* self) {
opts.log_file = (char*)self->arg;
}
Expand Down
6 changes: 6 additions & 0 deletions src/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@

#include <stdbool.h>

/**
* CLI configuration options.
*/
typedef struct {
bool use_syslog;
char* log_file;
} CliOptions;

extern CliOptions opts;

/**
* Initializes the CLI configuration.
*/
void cli_init(int argc, char** argv);

#endif /* CLI_H */
1 change: 1 addition & 0 deletions src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ extern pid_t daemon_pid;
extern char hostname[SMALL_BUFFER];

extern array_t *job_queue;
extern array_t *mail_queue;

extern const char *job_state_names[];

Expand Down
2 changes: 1 addition & 1 deletion src/cronentry.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ CronEntry* new_cron_entry(char* raw, time_t curr, Crontab* ct) {

// TODO: Lift out
if (parse_entry(entry, raw) != OK) {
printlogf("Failed to parse entry line %s\n", raw);
printlogf("[ERROR] Failed to parse entry line %s\n", raw);
return NULL;
}

Expand Down
38 changes: 38 additions & 0 deletions src/cronentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,55 @@
#include "ccronexpr/ccronexpr.h"
#include "crontab.h"

/**
* Represents a single line (entry) in a crontab.
*/
typedef struct {
/**
* The pre-parsed cron expression.
*/
cron_expr *expr;
/**
* The original cron schedule specification in the entry.
*/
char *schedule;
/**
* The command specified by the entry.
*/
char *cmd;
/**
* The next execution time, relative to the current crond iteration.
*/
time_t next;
/**
* A unique identifier for the entry. Used for logging and non-critical
* functions.
*/
unsigned int id;
/**
* A pointer to the entry's parent crontab.
*/
Crontab *parent;
} CronEntry;

/**
* Parses the raw line from the crontab file as an entry for the provided
* crontab object.
*
* @param raw The raw line/entry.
* @param curr The current crond iteration time.
* @param ct The crontab object to which this entry belongs. We pass in the
* crontab because we want the entry to have a pointer to its parent.
*/
CronEntry *new_cron_entry(char *raw, time_t curr, Crontab *ct);

/**
* Renews the `next` field on the given cron entry based on the current crond
* iteration time.
*
* @param entry The cron entry to renew.
* @param curr The current crond iteration time.
*/
void renew_cron_entry(CronEntry *entry, time_t curr);

#endif /* CRONENTRY_H */
54 changes: 35 additions & 19 deletions src/crontab.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,42 @@
#include "parser.h"
#include "util.h"

/*
* Because crontab/at files may be owned by their respective users we
* take extreme care in opening them. If the OS lacks the O_NOFOLLOW
* we will just have to live without it. In order for this to be an
* issue an attacker would have to subvert group CRON_GROUP.
* TODO: comment
*/
// Some systems won't have this option and we'll just have to live without it.
#ifndef O_NOFOLLOW
#define O_NOFOLLOW 0
#endif

#define MAXENTRIES 256
#define RW_BUFFER 1024

/**
* Returns true if the file represented by the stat entity is not owned by the
* user (represented by the pw entity).
*
* @param statbuf The stat struct for the file we're evaluating.
* @param pw The user's passwd entry.
* @param uname The username.
* @return true The file is NOT owned by the given user.
* @return false The file IS owned by the given user - yay!
*/
static bool file_not_owned_by(struct stat* statbuf, struct passwd* pw,
char* uname) {
return statbuf->st_uid != ROOT_UID &&
(pw == NULL || statbuf->st_uid != pw->pw_uid ||
strcmp(uname, pw->pw_name) != 0);
}

/**
* Modifies and finalizes the given crontab's environment data by adding any
* missing env vars. For example, we check for the user's home directory, shell,
* etc and set those.
*
* @param ct The crontab whose environment we're finalizing.
*/
static void complete_env(Crontab* ct) {
hash_table* vars = ct->vars;

// We don't want to have to create users for unit tests.
#ifndef UNIT_TEST
struct passwd* pw = getpwnam(ct->uname);
if (pw) {
Expand All @@ -60,16 +72,19 @@ static void complete_env(Crontab* ct) {
}
} else {
printlogf(
"Something went really awry and uname=%s wasn't found in the system "
"user db\n",
"[ERROR] Something went really awry and uname=%s wasn't found in the "
"system user db\n",
ct->uname);
}
#endif

// TODO: We could totally hoist this logic - the var matching function
// actually returns the full key=value string in the first element of the
// matches array I was just lazy and really wanted to get the crond up and
// running
// matches array. I was just lazy and really wanted to get the crond up and
// running.

// Fill out the envp using the vars map. We're going to need this later and
// forevermore, so we might as well get it out of the way upfront.
if (vars->count > 0) {
ct->envp = malloc(sizeof(char*) * vars->count + 1);

Expand All @@ -82,15 +97,16 @@ static void complete_env(Crontab* ct) {
idx++;
}

// `execle` requires it to be NULL-terminated
ct->envp[idx] = NULL;
}
}

array_t* get_filenames(char* dpath) {
array_t* get_filenames(char* dirpath) {
DIR* dir;

if ((dir = opendir(dpath)) != NULL) {
printlogf("scanning dir %s\n", dpath);
if ((dir = opendir(dirpath)) != NULL) {
printlogf("scanning dir %s\n", dirpath);
struct dirent* den;

array_t* file_names = array_init();
Expand All @@ -101,15 +117,15 @@ array_t* get_filenames(char* dpath) {
continue;
}

printlogf("found file %s/%s\n", dpath, den->d_name);
printlogf("found file %s/%s\n", dirpath, den->d_name);
array_push(file_names, s_copy(den->d_name));
}

closedir(dir);
return file_names;
} else {
perror("opendir");
printlogf("unable to scan dir %s\n", dpath);
printlogf("unable to scan dir %s\n", dirpath);
}

return NULL;
Expand Down Expand Up @@ -252,15 +268,15 @@ Crontab* new_crontab(int crontab_fd, bool is_root, time_t curr_time,

void scan_crontabs(hash_table* old_db, hash_table* new_db, DirConfig dir_conf,
time_t curr) {
array_t* fnames = get_filenames(dir_conf.name);
array_t* fnames = get_filenames(dir_conf.path);
// If no files, fall through to db replacement
// This will handle removal of any files that were deleted during runtime
if (has_elements(fnames)) {
foreach (fnames, i) {
char* fname = array_get(fnames, i);
char* fpath;
if (!(fpath = fmt_str("%s/%s", dir_conf.name, fname))) {
printlogf("failed to concatenate as %s/%s\n", dir_conf.name, fname);
if (!(fpath = fmt_str("%s/%s", dir_conf.path, fname))) {
printlogf("failed to concatenate as %s/%s\n", dir_conf.path, fname);
continue;
}
Crontab* ct = (Crontab*)ht_get(old_db, fpath);
Expand Down
73 changes: 70 additions & 3 deletions src/crontab.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,95 @@
#include "libhash/libhash.h"
#include "libutil/libutil.h"

// TODO: check dir mtime as well?
/**
* Holds metadata and configuration for one of the crontab directories being
* tracked.
*
* TODO: check dir mtime as well?
*/
typedef struct {
/**
* Does this directory house system i.e. root crontabs?
*/
bool is_root;
char *name;
/**
* The absolute path of the directory.
*/
char *path;
} DirConfig;

/**
* Represents a single crontab (file). We assume (and we enforce this in the
* crontab program) each file will be named after its user, except for root/sys
* crontabs.
*/
typedef struct {
/**
* The last time this crontab file was modified.
*/
time_t mtime;
/**
* The owning user's username (and name of the crontab file).
*/
char *uname;
/**
* An array of this crontab's entries.
*/
array_t *entries;
/**
* A mapping of variables (key/value pairs) set in the crontab.
*/
hash_table *vars;
/**
* A char* array of vars, concatenated such that each string is represented as
* "key=value" literals.
*/
char **envp;
} Crontab;

array_t *get_filenames(char *dpath);
/**
* Given a directory path, returns an array of all of the valid filenames
* therein.
*
* @param dirpath
*/
array_t *get_filenames(char *dirpath);

/**
* Parses a file into new crontab.
*
* @param crontab_fd The file descriptor for the crontab file.
* @param is_root A flag indicating whether this is a system (root-owned)
* crontab.
* @param curr_time The current time.
* @param mtime The last modified time of the file represented by `crontab_fd`.
* @param uname The username (and filename).
* @return Crontab*
*/
Crontab *new_crontab(int crontab_fd, bool is_root, time_t curr_time,
time_t mtime, char *uname);

/**
* Scans all crontabs in the given directory and updates them if needed.
*
* @param old_db A pointer to the current database.
* @param new_db A pointer to the new database; all updates will be placed here.
* @param dir_conf The dir config for the directory to be scanned.
* @param curr The current time.
*
* TODO: static
*/
void scan_crontabs(hash_table *old_db, hash_table *new_db, DirConfig dir_conf,
time_t curr);

/**
* Updates the crontab database by scanning all files that have been modified.
*
* @param db A pointer to the crontab database.
* @param curr The current time.
* @param dir_conf A variadic list of directories to be scanned.
* @param ...
*/
void update_db(hash_table *db, time_t curr, DirConfig *dir_conf, ...);

#endif /* FS_H */
5 changes: 5 additions & 0 deletions src/daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

#include "util.h"

/**
* Daemonizes the current running process and detaches it from the TTY.
*
* @return Retval
*/
Retval daemonize();

#endif /* DAEMON_H */
Loading

0 comments on commit 3cbff2b

Please sign in to comment.