hb/main.c

242 lines
5.5 KiB
C
Raw Normal View History

2019-04-18 01:06:55 +00:00
#define _GNU_SOURCE
#include <string.h>
2019-02-23 18:08:32 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
2019-02-24 00:41:47 +00:00
#include <sys/wait.h>
2019-02-23 18:08:32 +00:00
#include "linkedlist.h"
// Macro for status checks.
#define ONFAILED(status, fn) if(status > fn)
/**
2019-12-13 14:29:27 +00:00
* TODO: Add config file reading for daemonization.
* TODO: Allow daemonized process to call file reading/editing routines at will.
* TODO: Generalized routine for reading through a file and replacing a line.
* TODO: Generalized routine for reading a file.
*/
2019-12-13 14:29:27 +00:00
2019-12-16 14:14:41 +00:00
/** GLOBALS **/
2019-12-13 14:29:27 +00:00
// Our rule we use to blackhole domains
2019-02-23 18:08:32 +00:00
const char *blockString = "0.0.0.0 ";
LinkedList *hosts = NULL;
2019-12-13 14:29:27 +00:00
// The current hardcoded location of the hosts file.
static char *HOSTFILE = "/etc/hosts";
static char *CONFIG;
2019-12-16 14:14:41 +00:00
// Our configuration
2019-02-23 18:08:32 +00:00
2019-12-13 14:29:27 +00:00
/**
* SIGINT handler, cleans up resources on Ctrl-C
* @param signal
*/
void int_handler(int signal) {
// Clean up any resources.
fprintf(stderr, "SIGINT received, cleaning up...\n");
2019-12-16 17:39:38 +00:00
// This should be the final decrement to the config object.
2019-12-13 14:29:27 +00:00
}
void replacehost(char *oldhost, char *newhost);
2019-12-12 21:08:27 +00:00
/**
* Return an open handle to the hosts file.
*
* @param mode whichever mode host file you want to open
* @return FILE *
*/
FILE *fopenHostsFile(char *mode)
2019-02-23 18:08:32 +00:00
{
return fopen(HOSTFILE, mode);
2019-02-23 18:08:32 +00:00
}
/**
* Block a hosts using the hostsFile in FILE
*/
void blockHost(char *host)
2019-02-23 18:08:32 +00:00
{
FILE *hostsFile = fopenHostsFile("a");
2019-02-23 18:08:32 +00:00
char blockRule[256];
sprintf(blockRule, "%s %s\n", blockString, host);
blockRule[strlen(blockRule)] = 0;
2019-02-23 18:08:32 +00:00
ONFAILED(EOF, (fputs(blockRule, hostsFile))) {
fprintf(stderr, "Failed to write block rule to file\n");
}
2019-02-23 18:08:32 +00:00
fclose(hostsFile);
2019-02-23 18:08:32 +00:00
}
2019-02-24 00:33:54 +00:00
void usage()
{
fprintf(stdout, "Usage: ");
fprintf(stdout, "hb [add] <sitename>\n");
fprintf(stdout, "hb [edit] <oldsite> <newsite>\n");
fprintf(stdout, "hb [show]\n");
fprintf(stdout, "hb [delete] <sitename>\n");
2019-02-24 00:33:54 +00:00
}
2019-02-24 00:41:47 +00:00
void showHosts()
{
pid_t child = fork();
int rc = 0;
char *const parmList[] = {"/bin/cat", HOSTFILE, NULL};
2019-02-24 00:41:47 +00:00
if (child == 0)
{
execv("/bin/cat", parmList);
2019-02-24 00:41:47 +00:00
}
else
{
rc = wait(NULL);
}
}
2019-12-14 17:26:09 +00:00
/**
* Read the configuration file and give a return code to indicate any changes.
* @return 1 if successful, 0 if otherwise.
*/
int read_config_file() {
2019-12-16 17:39:38 +00:00
// increment the refcount for tmp.
2020-01-09 14:37:24 +00:00
linkedlist_add(&hosts, "hello.com");
2019-12-14 17:26:09 +00:00
}
/**
* Daemonize the process, to be run like this ONLY if there were no arguments
* provided.
*
* TODO:
* read the config file.
*/
void daemonize() {
pid_t mypid = fork();
if (mypid != 0) {
// I am the parent, kill myself
fprintf(stderr, "Parent exiting");
exit(1);
}
else {
// DO THE THING.
2019-12-14 17:26:09 +00:00
while(1) {
// read config
read_config_file();
2019-12-16 17:39:38 +00:00
break;
2019-12-14 17:26:09 +00:00
// make adjustments
// profit??
// JK, sleep.
}
}
}
2019-02-23 18:08:32 +00:00
/**
* Entrypoint.
*/
int main(int argc, char **argv)
{
2019-12-13 14:29:27 +00:00
// Install a sigint handler to help us clean up.
2020-01-09 14:37:24 +00:00
linkedlist_add(&hosts, "hello.com");
linkedlist_add(&hosts, "heloworld.com");
linkedlist_print(hosts);
2019-12-13 14:29:27 +00:00
signal(SIGINT, int_handler);
if (getuid() != 0)
2019-02-23 18:08:32 +00:00
{
fprintf(stderr, "hb: Must run as root using sudo!\n");
}
2019-12-13 14:29:27 +00:00
// Process our command line arguments.
for (int i = 0; i < argc; i++)
2019-02-23 18:08:32 +00:00
{
2019-12-13 14:29:27 +00:00
// Opens a hosts file in append mode, adding a host.
2019-02-23 18:08:32 +00:00
if (strcmp(argv[i], "add") == 0)
{
2019-12-12 21:08:27 +00:00
if (argc < 3) {
printf("Please provide a host!\n");
2019-12-12 21:08:27 +00:00
exit(1);
}
2019-12-16 17:39:38 +00:00
blockHost(argv[++i]);
2019-02-23 18:08:32 +00:00
}
2019-12-13 14:29:27 +00:00
// Replaces a host
// TODO: this currently duplicates the whole file and appends it to the end.
else if (strcmp(argv[i], "edit") == 0)
{
2019-12-16 17:39:38 +00:00
replacehost(argv[++i], argv[++i]);
}
2019-12-13 14:29:27 +00:00
// Deletes a host.
2019-02-23 18:08:32 +00:00
else if (strcmp(argv[i], "delete") == 0)
{
fprintf(stdout, "Soon to be implemented!\n");
}
2019-12-13 14:29:27 +00:00
// Shows usage.
2019-02-24 00:33:54 +00:00
else if (strcmp(argv[i], "-h") == 0)
{
usage();
exit(0);
}
2019-12-13 14:29:27 +00:00
// Show the entire hosts file.
else if (strcmp(argv[i], "show") == 0)
2019-02-24 00:41:47 +00:00
{
showHosts();
}
2019-12-16 17:39:38 +00:00
else if (strcmp(argv[i], "-config") == 0) {
CONFIG = argv[++i];
2019-12-16 17:39:38 +00:00
}
2019-12-13 14:29:27 +00:00
// Daemonize this process, allowing for hosts file to be automagically managed.
else {
2019-12-13 14:29:27 +00:00
// daemonize();
}
2019-02-23 18:08:32 +00:00
}
free_list(&hosts);
}
2019-12-12 21:08:27 +00:00
/**
* Replace a host in the hosts file with the NEW host.
*
* @param oldhost
* @param newhost
* @param hostsFile
*/
void replacehost(char *oldhost, char *newhost) {
FILE *hostsFile = fopenHostsFile("w+");
2019-12-12 21:08:27 +00:00
char buf[256];
char *ptr, *f;
char newHostsFile[4096];
memset(newHostsFile, 0, 4096);
2019-12-12 21:08:27 +00:00
printf("Starting to read!\n");
printf("Looking for host:%s\n", oldhost);
fseek(hostsFile, 0, SEEK_SET);
2019-12-12 21:08:27 +00:00
while (fgets(buf, 256, hostsFile) != NULL)
{
f = strcasestr(buf, oldhost);
if (f != NULL) {
memset(buf, 0, sizeof(buf));
sprintf(buf, "%s %s\n", blockString, newhost);
}
strcat(newHostsFile, buf);
memset(buf, 0, sizeof(buf));
}
// Ensure we have an EOF at the end of the file.
newHostsFile[strlen(newHostsFile)] = EOF;
// Seek to 0
fseek(hostsFile, 0, SEEK_SET);
// If this failed, write an error message to stderr
ONFAILED(0, (fwrite(newHostsFile, sizeof(char), sizeof(newHostsFile), hostsFile))) {
2019-12-12 21:08:27 +00:00
fprintf(stderr, "Did not write anything!\n");
}
fclose(hostsFile);
2019-12-12 21:08:27 +00:00
}