diff options
Diffstat (limited to 'initd')
| -rw-r--r-- | initd/init.h | 2 | ||||
| -rw-r--r-- | initd/main.c | 3 | ||||
| -rw-r--r-- | initd/signal_linux.c | 1 | ||||
| -rw-r--r-- | initd/supervisor.c | 79 | 
4 files changed, 85 insertions, 0 deletions
diff --git a/initd/init.h b/initd/init.h index b98da98..ffc7181 100644 --- a/initd/init.h +++ b/initd/init.h @@ -68,6 +68,8 @@ void supervisor_init(void);  bool supervisor_process_queues(void); +void supervisor_reload_config(void); +  void supervisor_answer_status_request(int fd, const void *dest_addr,  				      size_t addrlen, E_SERVICE_STATE filter); diff --git a/initd/main.c b/initd/main.c index 2b1a1cc..9cccdc5 100644 --- a/initd/main.c +++ b/initd/main.c @@ -30,6 +30,9 @@ static void handle_signal(void)  	case SIGINT:  		supervisor_set_target(TGT_REBOOT);  		break; +	case SIGHUP: +		supervisor_reload_config(); +		break;  	case SIGUSR1:  		if (sockfd >= 0) {  			close(sockfd); diff --git a/initd/signal_linux.c b/initd/signal_linux.c index bb9d339..b19d715 100644 --- a/initd/signal_linux.c +++ b/initd/signal_linux.c @@ -19,6 +19,7 @@ int sigsetup(void)  	sigaddset(&mask, SIGINT);  	sigaddset(&mask, SIGTERM);  	sigaddset(&mask, SIGUSR1); +	sigaddset(&mask, SIGHUP);  	sfd = signalfd(-1, &mask, SFD_CLOEXEC);  	if (sfd == -1) { diff --git a/initd/supervisor.c b/initd/supervisor.c index 53a2aec..3f157bf 100644 --- a/initd/supervisor.c +++ b/initd/supervisor.c @@ -13,6 +13,46 @@ static service_t *failed = NULL;  static int singleshot = 0;  static bool waiting = false; +static bool find_service(service_t *list, service_t *svc) +{ +	while (list != NULL) { +		if (strcmp(list->fname, svc->fname) == 0) +			return true; + +		list = list->next; +	} +	return false; +} + +static void remove_not_in_list(service_t **current, service_t *list, int tgt) +{ +	service_t *it = *current, *prev = NULL; + +	while (it != NULL) { +		if (it->target == tgt && !find_service(list, it)) { +			if (prev == NULL) { +				delsvc(it); +				*current = (*current)->next; +				it = *current; +			} else { +				prev->next = it->next; +				delsvc(it); +				it = prev->next; +			} +		} else { +			prev = it; +			it = it->next; +		} +	} +} + +static bool have_service(service_t *svc) +{ +	return find_service(running, svc) || find_service(terminated, svc) || +		find_service(queue, svc) || find_service(completed, svc) || +		find_service(failed, svc); +} +  static int start_service(service_t *svc)  {  	if (svc->id < 1) @@ -145,6 +185,45 @@ void supervisor_init(void)  	print_status("reading configuration from " SVCDIR, status, false);  } +void supervisor_reload_config(void) +{ +	service_list_t newcfg; +	service_t *svc; +	int i; + +	if (svcscan(SVCDIR, &newcfg, RDSVC_NO_EXEC | RDSVC_NO_CTTY)) +		return; + +	for (i = 0; i < TGT_MAX; ++i) { +		if (cfg.targets[i] == NULL) { +			remove_not_in_list(&queue, newcfg.targets[i], i); +			remove_not_in_list(&terminated, newcfg.targets[i], i); +			remove_not_in_list(&completed, newcfg.targets[i], i); +			remove_not_in_list(&failed, newcfg.targets[i], i); + +			while (newcfg.targets[i] != NULL) { +				svc = newcfg.targets[i]; +				newcfg.targets[i] = svc->next; + +				if (have_service(svc)) { +					delsvc(svc); +				} else { +					svc->id = service_id++; +					svc->status = EXIT_SUCCESS; +					svc->next = completed; +					completed = svc; +				} +			} +		} else { +			svc = cfg.targets[i]; +			cfg.targets[i] = newcfg.targets[i]; +			newcfg.targets[i] = svc; +		} +	} + +	del_svc_list(&newcfg); +} +  bool supervisor_process_queues(void)  {  	service_t *svc;  | 
