Skip to content

Commit 3f03e7d

Browse files
committed
initial source checkin
1 parent 8819464 commit 3f03e7d

File tree

7 files changed

+304
-0
lines changed

7 files changed

+304
-0
lines changed

.clang-format

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
AlignAfterOpenBracket: AlwaysBreak
3+
AlignEscapedNewlines: DontAlign
4+
AlignOperands: DontAlign
5+
AlwaysBreakAfterReturnType: AllDefinitions
6+
ContinuationIndentWidth: 8
7+
IndentWidth: 4
8+
KeepEmptyLinesAtTheStartOfBlocks: false
9+
TabWidth: 4
10+
UseTab: ForContinuationAndIndentation
11+
AlignTrailingComments: false
12+
...

.editorconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
insert_final_newline = true
6+
indent_style = tab
7+
tab_width = 4
8+
indent_size = 4

.github/workflows/build.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Check
2+
on:
3+
- push
4+
jobs:
5+
build:
6+
runs-on: ubuntu-latest
7+
container: alpine:3.14
8+
steps:
9+
- uses: actions/checkout@v2
10+
- name: install deps
11+
run: |
12+
apk add make gcc musl-dev
13+
- name: make
14+
run: make DEBUG=0 STATIC=1 STRIP=1
15+
- name: irc notice
16+
uses: Gottox/irc-message-action@v2
17+
if: failure()
18+
with:
19+
channel: "Gottox"
20+
nickname: gh-gottox
21+
message: "https://github.com/${{ github.repository }} failed on push ${{ github.event.compare }}"
22+
- name: release
23+
uses: softprops/action-gh-release@v1
24+
if: startsWith(github.ref, 'refs/tags/v') && success()
25+
with:
26+
files: |
27+
autohup

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,8 @@ modules.order
5050
Module.symvers
5151
Mkfile.old
5252
dkms.conf
53+
54+
compile_commands.json
55+
.cache
56+
autohup
57+
.gdb_history

Makefile

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
######################################################################
2+
# @author : Enno Boland ([email protected])
3+
# @file : Makefile
4+
# @created : Tuesday Nov 09, 2021 18:51:02 CET
5+
######################################################################
6+
7+
CFLAGS ?= -Wall -Wpedantic -Werror
8+
VERSION ?= 0.1
9+
10+
ifeq ($(STATIC),1)
11+
LDFLAGS += -static
12+
endif
13+
14+
ifeq ($(DEBUG),1)
15+
LDFLAGS += -g
16+
endif
17+
18+
ifeq ($(STRIP),1)
19+
LDFLAGS += -s
20+
endif
21+
22+
autohup: main.c
23+
$(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) -DVERSION='"$(VERSION)"'
24+
25+
.PHONY: clean release
26+
clean:
27+
rm -f autohup
28+
29+
release: clean
30+
test -z "`git status -s`"
31+
test "`git branch --show-current`" = main
32+
test "`git rev-parse HEAD`" = "`git rev-parse origin/main`"
33+
git tag v$(VERSION)
34+
git push --tags

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,37 @@
11
# autohup
22
automaticly sends SIGHUP to a process when a file changes.
3+
4+
## usage
5+
6+
```
7+
usage: autohup [-s signal] [-v] [path ...] -- command [argument ...]
8+
autohup -l
9+
```
10+
11+
## exit code
12+
13+
`autohup` always returns 255 if an error occurs internally. If the program
14+
defined with `command` exits, its error code is used.
15+
16+
## example
17+
18+
This example watches for changes in `/etc/daemon.d` and sends `SIGHUP` when inotify
19+
registers a change in that directory.
20+
```
21+
$ autohup /etc/daemon.d -- daemon
22+
```
23+
24+
The second example watches multiple directories and sends `SIGTERM` instead
25+
```
26+
$ autohup -s term /etc/daemon.d /var/lib/daemon -- daemon
27+
```
28+
29+
To list all signals autohup can send use this command:
30+
```
31+
$ autohup -l
32+
```
33+
34+
Signals can also be defined as numbers
35+
```
36+
$ autohup /etc/daemon.d -s 10 -- daemon # 10 = SIGUSR2
37+
```

main.c

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/**
2+
* @author : Enno Boland ([email protected])
3+
* @file : main
4+
* @created : Tuesday Nov 09, 2021 18:54:40 CET
5+
*/
6+
7+
#include <limits.h>
8+
#include <signal.h>
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
#include <string.h>
12+
#include <sys/inotify.h>
13+
#include <sys/wait.h>
14+
#include <time.h>
15+
#include <unistd.h>
16+
17+
#define EXIT_ERROR_CODE 255
18+
#define MAX_EVENTS 1
19+
#define EVENT_SIZE (sizeof(struct inotify_event))
20+
#define BUF_LEN (MAX_EVENTS * (EVENT_SIZE + NAME_MAX))
21+
22+
#define SIG(x) \
23+
{ .number = SIG##x, .name = #x }
24+
const struct {
25+
int number;
26+
char name[7];
27+
} signals[] = {SIG(ALRM), SIG(HUP), SIG(INT), SIG(QUIT), SIG(TERM),
28+
SIG(URG), SIG(USR1), SIG(USR2), SIG(WINCH), {0}};
29+
#undef SIG
30+
31+
pid_t child = 0;
32+
int trigger_signal = SIGHUP;
33+
int verbose = 0;
34+
35+
static const char *
36+
get_sig_name(const int signal) {
37+
int i;
38+
39+
for (i = 0; signals[i].number != 0; i++) {
40+
if (signal == signals[i].number) {
41+
return signals[i].name;
42+
}
43+
}
44+
45+
return NULL;
46+
}
47+
48+
static int
49+
get_sig_number(const char *signal) {
50+
int i;
51+
if (strncasecmp("SIG", signal, 3) == 0) {
52+
signal += 3;
53+
}
54+
55+
for (i = 0; signals[i].number != 0; i++) {
56+
if (strcasecmp(signals[i].name, signal) == 0) {
57+
return signals[i].number;
58+
}
59+
}
60+
61+
return -1;
62+
}
63+
64+
void
65+
sig_handler_forward(int sig) {
66+
if (child == 0) {
67+
return;
68+
}
69+
70+
kill(child, sig);
71+
}
72+
73+
static void
74+
sig_handler_child(int sig) {
75+
int status;
76+
77+
while (waitpid(-1, &status, WNOHANG) > 0) {
78+
}
79+
80+
exit(status);
81+
}
82+
83+
int
84+
list_signals() {
85+
int i;
86+
for (i = 0; signals[i].number != 0; i++) {
87+
fputs("SIG", stdout);
88+
puts(signals[i].name);
89+
}
90+
91+
return EXIT_SUCCESS;
92+
}
93+
94+
int
95+
usage(char *arg0) {
96+
fprintf(stderr,
97+
"usage: %s [-s signal] [-v] [path ...] -- command [argument ...]\n",
98+
arg0);
99+
fprintf(stderr, " %s -l\n", arg0);
100+
return EXIT_ERROR_CODE;
101+
}
102+
103+
int
104+
main(int argc, char **argv) {
105+
int rv;
106+
int inotify_fd;
107+
char buffer[BUF_LEN];
108+
const char *observed = argv[1];
109+
int opt;
110+
111+
inotify_fd = inotify_init();
112+
113+
while ((opt = getopt(argc, argv, "-s:lvV")) != -1) {
114+
switch (opt) {
115+
case 'l':
116+
return list_signals();
117+
case 's':
118+
rv = atoi(optarg);
119+
if (rv == 0) {
120+
rv = get_sig_number(optarg);
121+
}
122+
if (rv < 0) {
123+
fprintf(stderr, "%s: Signal cannot be found\n", optarg);
124+
return usage(argv[0]);
125+
}
126+
trigger_signal = rv;
127+
break;
128+
case 'V':
129+
fputs("autohup-" VERSION "\n", stderr);
130+
return EXIT_ERROR_CODE;
131+
case 'v':
132+
verbose++;
133+
break;
134+
case 1:
135+
rv = inotify_add_watch(inotify_fd, optarg, IN_ALL_EVENTS);
136+
if (rv < 0) {
137+
perror(observed);
138+
return EXIT_ERROR_CODE;
139+
}
140+
break;
141+
default:
142+
return EXIT_ERROR_CODE;
143+
}
144+
}
145+
if (optind == argc) {
146+
return usage(argv[0]);
147+
}
148+
149+
signal(SIGCHLD, sig_handler_child);
150+
151+
child = fork();
152+
if (child < 0) {
153+
perror(argv[2]);
154+
} else if (child == 0) {
155+
argv += optind;
156+
execvp(argv[0], argv);
157+
perror(argv[0]);
158+
159+
return EXIT_ERROR_CODE;
160+
} else {
161+
signal(SIGHUP, sig_handler_forward);
162+
signal(SIGINT, sig_handler_forward);
163+
signal(SIGQUIT, sig_handler_forward);
164+
signal(SIGUSR1, sig_handler_forward);
165+
signal(SIGUSR2, sig_handler_forward);
166+
signal(SIGTERM, sig_handler_forward);
167+
signal(SIGCONT, sig_handler_forward);
168+
for (;;) {
169+
rv = read(inotify_fd, buffer, BUF_LEN);
170+
if (rv < 0) {
171+
perror("inotify");
172+
return EXIT_ERROR_CODE;
173+
}
174+
175+
if (verbose) {
176+
fprintf(stderr, "DEBUG: sending signal %s to child process\n",
177+
get_sig_name(trigger_signal));
178+
}
179+
sig_handler_forward(trigger_signal);
180+
}
181+
return EXIT_ERROR_CODE;
182+
}
183+
}

0 commit comments

Comments
 (0)