Skip to content

Commit

Permalink
initial source checkin
Browse files Browse the repository at this point in the history
  • Loading branch information
Gottox committed Nov 10, 2021
1 parent 8819464 commit 3f03e7d
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
AlignAfterOpenBracket: AlwaysBreak
AlignEscapedNewlines: DontAlign
AlignOperands: DontAlign
AlwaysBreakAfterReturnType: AllDefinitions
ContinuationIndentWidth: 8
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: false
TabWidth: 4
UseTab: ForContinuationAndIndentation
AlignTrailingComments: false
...
8 changes: 8 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
root = true

[*]
end_of_line = lf
insert_final_newline = true
indent_style = tab
tab_width = 4
indent_size = 4
27 changes: 27 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Check
on:
- push
jobs:
build:
runs-on: ubuntu-latest
container: alpine:3.14
steps:
- uses: actions/checkout@v2
- name: install deps
run: |
apk add make gcc musl-dev
- name: make
run: make DEBUG=0 STATIC=1 STRIP=1
- name: irc notice
uses: Gottox/irc-message-action@v2
if: failure()
with:
channel: "Gottox"
nickname: gh-gottox
message: "https://github.com/${{ github.repository }} failed on push ${{ github.event.compare }}"
- name: release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/v') && success()
with:
files: |
autohup
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,8 @@ modules.order
Module.symvers
Mkfile.old
dkms.conf

compile_commands.json
.cache
autohup
.gdb_history
34 changes: 34 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
######################################################################
# @author : Enno Boland ([email protected])
# @file : Makefile
# @created : Tuesday Nov 09, 2021 18:51:02 CET
######################################################################

CFLAGS ?= -Wall -Wpedantic -Werror
VERSION ?= 0.1

ifeq ($(STATIC),1)
LDFLAGS += -static
endif

ifeq ($(DEBUG),1)
LDFLAGS += -g
endif

ifeq ($(STRIP),1)
LDFLAGS += -s
endif

autohup: main.c
$(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) -DVERSION='"$(VERSION)"'

.PHONY: clean release
clean:
rm -f autohup

release: clean
test -z "`git status -s`"
test "`git branch --show-current`" = main
test "`git rev-parse HEAD`" = "`git rev-parse origin/main`"
git tag v$(VERSION)
git push --tags
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,37 @@
# autohup
automaticly sends SIGHUP to a process when a file changes.

## usage

```
usage: autohup [-s signal] [-v] [path ...] -- command [argument ...]
autohup -l
```

## exit code

`autohup` always returns 255 if an error occurs internally. If the program
defined with `command` exits, its error code is used.

## example

This example watches for changes in `/etc/daemon.d` and sends `SIGHUP` when inotify
registers a change in that directory.
```
$ autohup /etc/daemon.d -- daemon
```

The second example watches multiple directories and sends `SIGTERM` instead
```
$ autohup -s term /etc/daemon.d /var/lib/daemon -- daemon
```

To list all signals autohup can send use this command:
```
$ autohup -l
```

Signals can also be defined as numbers
```
$ autohup /etc/daemon.d -s 10 -- daemon # 10 = SIGUSR2
```
183 changes: 183 additions & 0 deletions main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/**
* @author : Enno Boland ([email protected])
* @file : main
* @created : Tuesday Nov 09, 2021 18:54:40 CET
*/

#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#define EXIT_ERROR_CODE 255
#define MAX_EVENTS 1
#define EVENT_SIZE (sizeof(struct inotify_event))
#define BUF_LEN (MAX_EVENTS * (EVENT_SIZE + NAME_MAX))

#define SIG(x) \
{ .number = SIG##x, .name = #x }
const struct {
int number;
char name[7];
} signals[] = {SIG(ALRM), SIG(HUP), SIG(INT), SIG(QUIT), SIG(TERM),
SIG(URG), SIG(USR1), SIG(USR2), SIG(WINCH), {0}};
#undef SIG

pid_t child = 0;
int trigger_signal = SIGHUP;
int verbose = 0;

static const char *
get_sig_name(const int signal) {
int i;

for (i = 0; signals[i].number != 0; i++) {
if (signal == signals[i].number) {
return signals[i].name;
}
}

return NULL;
}

static int
get_sig_number(const char *signal) {
int i;
if (strncasecmp("SIG", signal, 3) == 0) {
signal += 3;
}

for (i = 0; signals[i].number != 0; i++) {
if (strcasecmp(signals[i].name, signal) == 0) {
return signals[i].number;
}
}

return -1;
}

void
sig_handler_forward(int sig) {
if (child == 0) {
return;
}

kill(child, sig);
}

static void
sig_handler_child(int sig) {
int status;

while (waitpid(-1, &status, WNOHANG) > 0) {
}

exit(status);
}

int
list_signals() {
int i;
for (i = 0; signals[i].number != 0; i++) {
fputs("SIG", stdout);
puts(signals[i].name);
}

return EXIT_SUCCESS;
}

int
usage(char *arg0) {
fprintf(stderr,
"usage: %s [-s signal] [-v] [path ...] -- command [argument ...]\n",
arg0);
fprintf(stderr, " %s -l\n", arg0);
return EXIT_ERROR_CODE;
}

int
main(int argc, char **argv) {
int rv;
int inotify_fd;
char buffer[BUF_LEN];
const char *observed = argv[1];
int opt;

inotify_fd = inotify_init();

while ((opt = getopt(argc, argv, "-s:lvV")) != -1) {
switch (opt) {
case 'l':
return list_signals();
case 's':
rv = atoi(optarg);
if (rv == 0) {
rv = get_sig_number(optarg);
}
if (rv < 0) {
fprintf(stderr, "%s: Signal cannot be found\n", optarg);
return usage(argv[0]);
}
trigger_signal = rv;
break;
case 'V':
fputs("autohup-" VERSION "\n", stderr);
return EXIT_ERROR_CODE;
case 'v':
verbose++;
break;
case 1:
rv = inotify_add_watch(inotify_fd, optarg, IN_ALL_EVENTS);
if (rv < 0) {
perror(observed);
return EXIT_ERROR_CODE;
}
break;
default:
return EXIT_ERROR_CODE;
}
}
if (optind == argc) {
return usage(argv[0]);
}

signal(SIGCHLD, sig_handler_child);

child = fork();
if (child < 0) {
perror(argv[2]);
} else if (child == 0) {
argv += optind;
execvp(argv[0], argv);
perror(argv[0]);

return EXIT_ERROR_CODE;
} else {
signal(SIGHUP, sig_handler_forward);
signal(SIGINT, sig_handler_forward);
signal(SIGQUIT, sig_handler_forward);
signal(SIGUSR1, sig_handler_forward);
signal(SIGUSR2, sig_handler_forward);
signal(SIGTERM, sig_handler_forward);
signal(SIGCONT, sig_handler_forward);
for (;;) {
rv = read(inotify_fd, buffer, BUF_LEN);
if (rv < 0) {
perror("inotify");
return EXIT_ERROR_CODE;
}

if (verbose) {
fprintf(stderr, "DEBUG: sending signal %s to child process\n",
get_sig_name(trigger_signal));
}
sig_handler_forward(trigger_signal);
}
return EXIT_ERROR_CODE;
}
}

0 comments on commit 3f03e7d

Please sign in to comment.