fixup! Add service(8).

This commit is contained in:
Jonas 'Sortie' Termansen 2024-05-07 14:29:49 +02:00
parent b676a5f2da
commit f551b4afa8
2 changed files with 124 additions and 1 deletions

2
init/.gitignore vendored
View File

@ -1,2 +1,2 @@
init
*.o
service

123
init/service.c Normal file
View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2024 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* service.c
* Start and stop services.
*/
#include <sys/socket.h>
#include <sys/un.h>
#include <err.h>
#include <getopt.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
static int open_local_client_socket(const char* path, int flags)
{
size_t path_length = strlen(path);
size_t addr_size = offsetof(struct sockaddr_un, sun_path) + path_length + 1;
struct sockaddr_un* sockaddr = malloc(addr_size);
if ( !sockaddr )
return -1;
sockaddr->sun_family = AF_LOCAL;
strcpy(sockaddr->sun_path, path);
int fd = socket(AF_LOCAL, SOCK_STREAM | flags, 0);
if ( fd < 0 )
return free(sockaddr), -1;
if ( connect(fd, (const struct sockaddr*) sockaddr, addr_size) < 0 )
return close(fd), free(sockaddr), -1;
free(sockaddr);
return fd;
}
int main(int argc, char* argv[])
{
const char* init_socket = getenv("INIT_SOCKET");
if ( !init_socket )
init_socket = "/var/run/init";
bool raw = false;
const char* source = "local";
const struct option longopts[] =
{
{"source", required_argument, NULL, 't'},
{"raw", no_argument, NULL, 'r'},
{0, 0, 0, 0}
};
const char* opts = "rs:";
int opt;
while ( (opt = getopt_long(argc, argv, opts, longopts, NULL)) != -1 )
{
switch ( opt )
{
case 'r': raw = true; break;
case 's': source = optarg; break;
default: return 2;
}
}
int fd = open_local_client_socket(init_socket, 0);
if ( fd < 0 )
err(1, "%s", init_socket);
if ( raw )
{
for ( int i = optind; i < argc; i++ )
{
if ( dprintf(fd, "%s%c", argv[i], i + 1 == argc ? '\n' : ' ') < 0 )
err(1, "%s", init_socket);
}
return 0;
}
if ( argc - optind < 2 )
errx(1, "usage: <daemon> <command>");
const char* daemon = argv[optind++];
const char* command = argv[optind++];
if ( !strcmp(command, "enable") )
{
// TODO: Option for not writing out a new config.
if ( dprintf(fd, "require %s %s start\n", source, daemon) < 0 )
err(1, "%s", init_socket);
}
else if ( !strcmp(command, "disable") )
{
// TODO: Option for not writing out a new config.
if ( dprintf(fd, "unrequire %s %s\n", source, daemon) < 0 )
err(1, "%s", init_socket);
}
else if ( !strcmp(command, "start") )
{
if ( dprintf(fd, "require %s %s start\n", source, daemon) < 0 )
err(1, "%s", init_socket);
}
else if ( !strcmp(command, "stop") )
{
if ( dprintf(fd, "unrequire %s %s stop\n", source, daemon) < 0 )
err(1, "%s", init_socket);
}
else
errx(1, "unknown command: %s", command);
return 0;
}