Almost initial commit
This commit is contained in:
parent
350d52d68f
commit
a971a0e647
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
/build/
|
||||
*.sock
|
||||
19
CMakeLists.txt
Normal file
19
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
cmake_minimum_required(VERSION 3.20)
|
||||
project(amduat_api LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
|
||||
add_subdirectory(vendor/amduat)
|
||||
|
||||
add_executable(amduatd src/amduatd.c)
|
||||
|
||||
target_include_directories(amduatd
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/vendor/amduat/src/internal
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/vendor/amduat/include
|
||||
)
|
||||
|
||||
target_link_libraries(amduatd
|
||||
PRIVATE amduat_asl_store_fs amduat_asl amduat_enc amduat_hash_asl1 amduat_util
|
||||
)
|
||||
690
src/amduatd.c
Normal file
690
src/amduatd.c
Normal file
|
|
@ -0,0 +1,690 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include "amduat/asl/artifact_io.h"
|
||||
#include "amduat/asl/asl_store_fs.h"
|
||||
#include "amduat/asl/asl_store_fs_meta.h"
|
||||
#include "amduat/asl/ref_text.h"
|
||||
#include "amduat/asl/store.h"
|
||||
#include "amduat/enc/asl1_core_codec.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char *const AMDUATD_DEFAULT_ROOT = ".amduat-asl";
|
||||
static const char *const AMDUATD_DEFAULT_SOCK = "amduatd.sock";
|
||||
|
||||
static volatile sig_atomic_t amduatd_should_exit = 0;
|
||||
|
||||
static void amduatd_on_signal(int signo) {
|
||||
(void)signo;
|
||||
amduatd_should_exit = 1;
|
||||
}
|
||||
|
||||
static bool amduatd_write_all(int fd, const uint8_t *buf, size_t len) {
|
||||
size_t off = 0;
|
||||
while (off < len) {
|
||||
ssize_t n = write(fd, buf + off, len - off);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (n == 0) {
|
||||
return false;
|
||||
}
|
||||
off += (size_t)n;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool amduatd_read_exact(int fd, uint8_t *buf, size_t len) {
|
||||
size_t off = 0;
|
||||
while (off < len) {
|
||||
ssize_t n = read(fd, buf + off, len - off);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (n == 0) {
|
||||
return false;
|
||||
}
|
||||
off += (size_t)n;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool amduatd_read_line(int fd, char *buf, size_t cap, size_t *out_len) {
|
||||
size_t len = 0;
|
||||
while (len + 1 < cap) {
|
||||
char c = 0;
|
||||
ssize_t n = read(fd, &c, 1);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (n == 0) {
|
||||
return false;
|
||||
}
|
||||
if (c == '\n') {
|
||||
break;
|
||||
}
|
||||
buf[len++] = c;
|
||||
}
|
||||
if (len == 0) {
|
||||
return false;
|
||||
}
|
||||
if (len > 0 && buf[len - 1] == '\r') {
|
||||
len--;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
if (out_len != NULL) {
|
||||
*out_len = len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char method[8];
|
||||
char path[1024];
|
||||
char content_type[128];
|
||||
char accept[128];
|
||||
char x_type_tag[64];
|
||||
size_t content_length;
|
||||
} amduatd_http_req_t;
|
||||
|
||||
static void amduatd_http_req_init(amduatd_http_req_t *req) {
|
||||
memset(req, 0, sizeof(*req));
|
||||
}
|
||||
|
||||
static bool amduatd_http_parse_request(int fd, amduatd_http_req_t *out_req) {
|
||||
char line[2048];
|
||||
size_t line_len = 0;
|
||||
char *sp1 = NULL;
|
||||
char *sp2 = NULL;
|
||||
|
||||
if (out_req == NULL) {
|
||||
return false;
|
||||
}
|
||||
amduatd_http_req_init(out_req);
|
||||
|
||||
if (!amduatd_read_line(fd, line, sizeof(line), &line_len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sp1 = strchr(line, ' ');
|
||||
if (sp1 == NULL) {
|
||||
return false;
|
||||
}
|
||||
*sp1++ = '\0';
|
||||
sp2 = strchr(sp1, ' ');
|
||||
if (sp2 == NULL) {
|
||||
return false;
|
||||
}
|
||||
*sp2++ = '\0';
|
||||
|
||||
if (strlen(line) >= sizeof(out_req->method)) {
|
||||
return false;
|
||||
}
|
||||
strncpy(out_req->method, line, sizeof(out_req->method) - 1);
|
||||
|
||||
if (strlen(sp1) >= sizeof(out_req->path)) {
|
||||
return false;
|
||||
}
|
||||
strncpy(out_req->path, sp1, sizeof(out_req->path) - 1);
|
||||
|
||||
for (;;) {
|
||||
if (!amduatd_read_line(fd, line, sizeof(line), &line_len)) {
|
||||
return false;
|
||||
}
|
||||
if (line_len == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (strncasecmp(line, "Content-Length:", 15) == 0) {
|
||||
const char *v = line + 15;
|
||||
while (*v == ' ' || *v == '\t') {
|
||||
v++;
|
||||
}
|
||||
out_req->content_length = (size_t)strtoull(v, NULL, 10);
|
||||
} else if (strncasecmp(line, "Content-Type:", 13) == 0) {
|
||||
const char *v = line + 13;
|
||||
while (*v == ' ' || *v == '\t') {
|
||||
v++;
|
||||
}
|
||||
strncpy(out_req->content_type, v, sizeof(out_req->content_type) - 1);
|
||||
} else if (strncasecmp(line, "Accept:", 7) == 0) {
|
||||
const char *v = line + 7;
|
||||
while (*v == ' ' || *v == '\t') {
|
||||
v++;
|
||||
}
|
||||
strncpy(out_req->accept, v, sizeof(out_req->accept) - 1);
|
||||
} else if (strncasecmp(line, "X-Amduat-Type-Tag:", 18) == 0) {
|
||||
const char *v = line + 18;
|
||||
while (*v == ' ' || *v == '\t') {
|
||||
v++;
|
||||
}
|
||||
strncpy(out_req->x_type_tag, v, sizeof(out_req->x_type_tag) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool amduatd_http_send_status(int fd,
|
||||
int code,
|
||||
const char *reason,
|
||||
const char *content_type,
|
||||
const uint8_t *body,
|
||||
size_t body_len,
|
||||
bool head_only) {
|
||||
char hdr[512];
|
||||
int n = snprintf(hdr,
|
||||
sizeof(hdr),
|
||||
"HTTP/1.1 %d %s\r\n"
|
||||
"Content-Length: %zu\r\n"
|
||||
"Content-Type: %s\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n",
|
||||
code,
|
||||
reason != NULL ? reason : "",
|
||||
body_len,
|
||||
content_type != NULL ? content_type : "text/plain");
|
||||
if (n <= 0 || (size_t)n >= sizeof(hdr)) {
|
||||
return false;
|
||||
}
|
||||
if (!amduatd_write_all(fd, (const uint8_t *)hdr, (size_t)n)) {
|
||||
return false;
|
||||
}
|
||||
if (!head_only && body != NULL && body_len != 0) {
|
||||
return amduatd_write_all(fd, body, body_len);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool amduatd_http_send_text(int fd,
|
||||
int code,
|
||||
const char *reason,
|
||||
const char *text,
|
||||
bool head_only) {
|
||||
const uint8_t *body = (const uint8_t *)(text != NULL ? text : "");
|
||||
size_t len = text != NULL ? strlen(text) : 0;
|
||||
return amduatd_http_send_status(
|
||||
fd, code, reason, "text/plain; charset=utf-8", body, len, head_only);
|
||||
}
|
||||
|
||||
static bool amduatd_http_send_json(int fd,
|
||||
int code,
|
||||
const char *reason,
|
||||
const char *json,
|
||||
bool head_only) {
|
||||
const uint8_t *body = (const uint8_t *)(json != NULL ? json : "{}");
|
||||
size_t len = json != NULL ? strlen(json) : 2;
|
||||
return amduatd_http_send_status(
|
||||
fd, code, reason, "application/json", body, len, head_only);
|
||||
}
|
||||
|
||||
static const char *amduatd_query_param(const char *path,
|
||||
const char *key,
|
||||
char *out_value,
|
||||
size_t out_cap) {
|
||||
const char *q = strchr(path, '?');
|
||||
size_t key_len = 0;
|
||||
if (out_value != NULL && out_cap != 0) {
|
||||
out_value[0] = '\0';
|
||||
}
|
||||
if (q == NULL || key == NULL || out_value == NULL || out_cap == 0) {
|
||||
return NULL;
|
||||
}
|
||||
q++;
|
||||
key_len = strlen(key);
|
||||
|
||||
while (*q != '\0') {
|
||||
const char *k = q;
|
||||
const char *eq = strchr(k, '=');
|
||||
const char *amp = strchr(k, '&');
|
||||
size_t klen = 0;
|
||||
const char *v = NULL;
|
||||
size_t vlen = 0;
|
||||
|
||||
if (amp == NULL) {
|
||||
amp = q + strlen(q);
|
||||
}
|
||||
if (eq == NULL || eq > amp) {
|
||||
q = (*amp == '&') ? (amp + 1) : amp;
|
||||
continue;
|
||||
}
|
||||
klen = (size_t)(eq - k);
|
||||
if (klen == key_len && strncmp(k, key, key_len) == 0) {
|
||||
v = eq + 1;
|
||||
vlen = (size_t)(amp - v);
|
||||
if (vlen >= out_cap) {
|
||||
vlen = out_cap - 1;
|
||||
}
|
||||
memcpy(out_value, v, vlen);
|
||||
out_value[vlen] = '\0';
|
||||
return out_value;
|
||||
}
|
||||
q = (*amp == '&') ? (amp + 1) : amp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void amduatd_path_without_query(const char *path,
|
||||
char *out,
|
||||
size_t cap) {
|
||||
const char *q = NULL;
|
||||
size_t n = 0;
|
||||
if (out == NULL || cap == 0) {
|
||||
return;
|
||||
}
|
||||
out[0] = '\0';
|
||||
if (path == NULL) {
|
||||
return;
|
||||
}
|
||||
q = strchr(path, '?');
|
||||
n = q != NULL ? (size_t)(q - path) : strlen(path);
|
||||
if (n >= cap) {
|
||||
n = cap - 1;
|
||||
}
|
||||
memcpy(out, path, n);
|
||||
out[n] = '\0';
|
||||
}
|
||||
|
||||
static bool amduatd_parse_type_tag_hex(const char *text,
|
||||
bool *out_has_type_tag,
|
||||
amduat_type_tag_t *out_type_tag) {
|
||||
char *end = NULL;
|
||||
unsigned long v = 0;
|
||||
if (out_has_type_tag != NULL) {
|
||||
*out_has_type_tag = false;
|
||||
}
|
||||
if (text == NULL || text[0] == '\0' || out_type_tag == NULL ||
|
||||
out_has_type_tag == NULL) {
|
||||
return true;
|
||||
}
|
||||
errno = 0;
|
||||
v = strtoul(text, &end, 0);
|
||||
if (errno != 0 || end == text || *end != '\0' || v > 0xffffffffUL) {
|
||||
return false;
|
||||
}
|
||||
*out_has_type_tag = true;
|
||||
out_type_tag->tag_id = (uint32_t)v;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool amduatd_handle_meta(int fd,
|
||||
const amduat_asl_store_fs_config_t *cfg,
|
||||
bool head_only) {
|
||||
char json[512];
|
||||
int n = snprintf(json,
|
||||
sizeof(json),
|
||||
"{"
|
||||
"\"store_id\":\"%s\","
|
||||
"\"encoding_profile_id\":\"0x%04x\","
|
||||
"\"hash_id\":\"0x%04x\""
|
||||
"}\n",
|
||||
cfg != NULL ? cfg->store_id : "",
|
||||
cfg != NULL ? (unsigned int)cfg->config.encoding_profile_id
|
||||
: 0u,
|
||||
cfg != NULL ? (unsigned int)cfg->config.hash_id : 0u);
|
||||
if (n <= 0 || (size_t)n >= sizeof(json)) {
|
||||
return amduatd_http_send_text(fd, 500, "Internal Server Error", "error\n",
|
||||
head_only);
|
||||
}
|
||||
return amduatd_http_send_json(fd, 200, "OK", json, head_only);
|
||||
}
|
||||
|
||||
static bool amduatd_handle_get_artifact(int fd,
|
||||
amduat_asl_store_t *store,
|
||||
const char *path,
|
||||
bool head_only) {
|
||||
char no_query[1024];
|
||||
char format[32];
|
||||
const char *ref_text = NULL;
|
||||
amduat_reference_t ref;
|
||||
amduat_artifact_t artifact;
|
||||
amduat_asl_store_error_t err;
|
||||
bool want_artifact = false;
|
||||
|
||||
memset(&ref, 0, sizeof(ref));
|
||||
memset(&artifact, 0, sizeof(artifact));
|
||||
amduatd_path_without_query(path, no_query, sizeof(no_query));
|
||||
|
||||
if (strncmp(no_query, "/v1/artifacts/", 14) != 0) {
|
||||
return amduatd_http_send_text(fd, 404, "Not Found", "not found\n",
|
||||
head_only);
|
||||
}
|
||||
ref_text = no_query + 14;
|
||||
if (ref_text[0] == '\0') {
|
||||
return amduatd_http_send_text(fd, 400, "Bad Request", "missing ref\n",
|
||||
head_only);
|
||||
}
|
||||
|
||||
if (!amduat_asl_ref_decode_hex(ref_text, &ref)) {
|
||||
return amduatd_http_send_text(fd, 400, "Bad Request", "invalid ref\n",
|
||||
head_only);
|
||||
}
|
||||
|
||||
memset(format, 0, sizeof(format));
|
||||
if (amduatd_query_param(path, "format", format, sizeof(format)) != NULL) {
|
||||
if (strcmp(format, "artifact") == 0) {
|
||||
want_artifact = true;
|
||||
} else if (strcmp(format, "raw") == 0 || format[0] == '\0') {
|
||||
want_artifact = false;
|
||||
} else {
|
||||
free((void *)ref.digest.data);
|
||||
return amduatd_http_send_text(fd, 400, "Bad Request",
|
||||
"invalid format\n", head_only);
|
||||
}
|
||||
}
|
||||
|
||||
err = amduat_asl_store_get(store, ref, &artifact);
|
||||
free((void *)ref.digest.data);
|
||||
if (err == AMDUAT_ASL_STORE_ERR_NOT_FOUND) {
|
||||
return amduatd_http_send_text(fd, 404, "Not Found", "not found\n",
|
||||
head_only);
|
||||
}
|
||||
if (err != AMDUAT_ASL_STORE_OK) {
|
||||
amduat_asl_artifact_free(&artifact);
|
||||
return amduatd_http_send_text(fd, 500, "Internal Server Error",
|
||||
"store error\n", head_only);
|
||||
}
|
||||
|
||||
if (!want_artifact) {
|
||||
bool ok = amduatd_http_send_status(
|
||||
fd,
|
||||
200,
|
||||
"OK",
|
||||
"application/octet-stream",
|
||||
artifact.bytes.data,
|
||||
artifact.bytes.len,
|
||||
head_only);
|
||||
amduat_asl_artifact_free(&artifact);
|
||||
return ok;
|
||||
}
|
||||
|
||||
{
|
||||
amduat_octets_t out = amduat_octets(NULL, 0);
|
||||
bool ok = amduat_enc_asl1_core_encode_artifact_v1(artifact, &out);
|
||||
amduat_asl_artifact_free(&artifact);
|
||||
if (!ok) {
|
||||
return amduatd_http_send_text(fd, 500, "Internal Server Error",
|
||||
"encode error\n", head_only);
|
||||
}
|
||||
ok = amduatd_http_send_status(fd,
|
||||
200,
|
||||
"OK",
|
||||
"application/vnd.amduat.asl.artifact+v1",
|
||||
out.data,
|
||||
out.len,
|
||||
head_only);
|
||||
free((void *)out.data);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
static bool amduatd_handle_head_artifact(int fd,
|
||||
amduat_asl_store_t *store,
|
||||
const char *path) {
|
||||
return amduatd_handle_get_artifact(fd, store, path, true);
|
||||
}
|
||||
|
||||
static bool amduatd_handle_post_artifacts(int fd,
|
||||
amduat_asl_store_t *store,
|
||||
const amduatd_http_req_t *req) {
|
||||
uint8_t *body = NULL;
|
||||
bool has_type_tag = false;
|
||||
amduat_type_tag_t type_tag;
|
||||
amduat_asl_io_format_t input_format = AMDUAT_ASL_IO_RAW;
|
||||
amduat_artifact_t artifact;
|
||||
amduat_reference_t ref;
|
||||
amduat_asl_store_error_t err;
|
||||
char *ref_hex = NULL;
|
||||
char json[2048];
|
||||
|
||||
memset(&artifact, 0, sizeof(artifact));
|
||||
memset(&ref, 0, sizeof(ref));
|
||||
memset(&type_tag, 0, sizeof(type_tag));
|
||||
|
||||
if (req == NULL) {
|
||||
return amduatd_http_send_text(fd, 400, "Bad Request", "bad request\n",
|
||||
false);
|
||||
}
|
||||
|
||||
if (req->content_length > (64u * 1024u * 1024u)) {
|
||||
return amduatd_http_send_text(fd, 413, "Payload Too Large",
|
||||
"payload too large\n", false);
|
||||
}
|
||||
|
||||
if (req->content_length != 0) {
|
||||
body = (uint8_t *)malloc(req->content_length);
|
||||
if (body == NULL) {
|
||||
return amduatd_http_send_text(fd, 500, "Internal Server Error",
|
||||
"oom\n", false);
|
||||
}
|
||||
if (!amduatd_read_exact(fd, body, req->content_length)) {
|
||||
free(body);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
body = NULL;
|
||||
}
|
||||
|
||||
if (req->content_type[0] != '\0' &&
|
||||
strstr(req->content_type, "application/vnd.amduat.asl.artifact+v1") !=
|
||||
NULL) {
|
||||
input_format = AMDUAT_ASL_IO_ARTIFACT;
|
||||
}
|
||||
|
||||
if (input_format == AMDUAT_ASL_IO_RAW) {
|
||||
if (!amduatd_parse_type_tag_hex(req->x_type_tag,
|
||||
&has_type_tag,
|
||||
&type_tag)) {
|
||||
free(body);
|
||||
return amduatd_http_send_text(fd, 400, "Bad Request",
|
||||
"invalid X-Amduat-Type-Tag\n", false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!amduat_asl_artifact_from_bytes(amduat_octets(body, req->content_length),
|
||||
input_format,
|
||||
has_type_tag,
|
||||
type_tag,
|
||||
&artifact)) {
|
||||
free(body);
|
||||
return amduatd_http_send_text(fd, 400, "Bad Request",
|
||||
"invalid artifact\n", false);
|
||||
}
|
||||
|
||||
err = amduat_asl_store_put(store, artifact, &ref);
|
||||
amduat_asl_artifact_free(&artifact);
|
||||
if (err != AMDUAT_ASL_STORE_OK) {
|
||||
free((void *)ref.digest.data);
|
||||
return amduatd_http_send_text(fd, 500, "Internal Server Error",
|
||||
"store error\n", false);
|
||||
}
|
||||
|
||||
if (!amduat_asl_ref_encode_hex(ref, &ref_hex)) {
|
||||
free((void *)ref.digest.data);
|
||||
return amduatd_http_send_text(fd, 500, "Internal Server Error",
|
||||
"encode ref error\n", false);
|
||||
}
|
||||
free((void *)ref.digest.data);
|
||||
|
||||
{
|
||||
int n = snprintf(json, sizeof(json), "{\"ref\":\"%s\"}\n", ref_hex);
|
||||
free(ref_hex);
|
||||
if (n <= 0 || (size_t)n >= sizeof(json)) {
|
||||
return amduatd_http_send_text(fd, 500, "Internal Server Error",
|
||||
"error\n", false);
|
||||
}
|
||||
return amduatd_http_send_json(fd, 200, "OK", json, false);
|
||||
}
|
||||
}
|
||||
|
||||
static bool amduatd_handle_conn(int fd,
|
||||
amduat_asl_store_t *store,
|
||||
const amduat_asl_store_fs_config_t *cfg) {
|
||||
amduatd_http_req_t req;
|
||||
char no_query[1024];
|
||||
|
||||
if (!amduatd_http_parse_request(fd, &req)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
amduatd_path_without_query(req.path, no_query, sizeof(no_query));
|
||||
|
||||
if (strcmp(req.method, "GET") == 0 && strcmp(no_query, "/v1/meta") == 0) {
|
||||
return amduatd_handle_meta(fd, cfg, false);
|
||||
}
|
||||
if (strcmp(req.method, "HEAD") == 0 && strcmp(no_query, "/v1/meta") == 0) {
|
||||
return amduatd_handle_meta(fd, cfg, true);
|
||||
}
|
||||
|
||||
if (strcmp(req.method, "POST") == 0 && strcmp(no_query, "/v1/artifacts") == 0) {
|
||||
return amduatd_handle_post_artifacts(fd, store, &req);
|
||||
}
|
||||
if (strcmp(req.method, "GET") == 0 &&
|
||||
strncmp(no_query, "/v1/artifacts/", 14) == 0) {
|
||||
return amduatd_handle_get_artifact(fd, store, req.path, false);
|
||||
}
|
||||
if (strcmp(req.method, "HEAD") == 0 &&
|
||||
strncmp(no_query, "/v1/artifacts/", 14) == 0) {
|
||||
return amduatd_handle_head_artifact(fd, store, req.path);
|
||||
}
|
||||
|
||||
return amduatd_http_send_text(fd, 404, "Not Found", "not found\n", false);
|
||||
}
|
||||
|
||||
static void amduatd_print_usage(FILE *stream) {
|
||||
fprintf(stream,
|
||||
"usage:\n"
|
||||
" amduatd [--root PATH] [--sock PATH]\n"
|
||||
"\n"
|
||||
"defaults:\n"
|
||||
" --root %s\n"
|
||||
" --sock %s\n",
|
||||
AMDUATD_DEFAULT_ROOT,
|
||||
AMDUATD_DEFAULT_SOCK);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const char *root = AMDUATD_DEFAULT_ROOT;
|
||||
const char *sock_path = AMDUATD_DEFAULT_SOCK;
|
||||
amduat_asl_store_fs_config_t cfg;
|
||||
amduat_asl_store_fs_t fs;
|
||||
amduat_asl_store_t store;
|
||||
int i;
|
||||
int sfd = -1;
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "--root") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
fprintf(stderr, "error: --root requires a path\n");
|
||||
return 2;
|
||||
}
|
||||
root = argv[++i];
|
||||
} else if (strcmp(argv[i], "--sock") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
fprintf(stderr, "error: --sock requires a path\n");
|
||||
return 2;
|
||||
}
|
||||
sock_path = argv[++i];
|
||||
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
|
||||
amduatd_print_usage(stdout);
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
if (!amduat_asl_store_fs_load_config(root, &cfg)) {
|
||||
fprintf(stderr, "error: failed to load store config: %s\n", root);
|
||||
return 8;
|
||||
}
|
||||
|
||||
memset(&fs, 0, sizeof(fs));
|
||||
if (!amduat_asl_store_fs_init(&fs, cfg.config, root)) {
|
||||
fprintf(stderr, "error: failed to initialize store: %s\n", root);
|
||||
return 8;
|
||||
}
|
||||
amduat_asl_store_init(&store, cfg.config, amduat_asl_store_fs_ops(), &fs);
|
||||
|
||||
signal(SIGINT, amduatd_on_signal);
|
||||
signal(SIGTERM, amduatd_on_signal);
|
||||
|
||||
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sfd < 0) {
|
||||
perror("socket");
|
||||
return 8;
|
||||
}
|
||||
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (strlen(sock_path) >= sizeof(addr.sun_path)) {
|
||||
fprintf(stderr, "error: socket path too long\n");
|
||||
close(sfd);
|
||||
return 2;
|
||||
}
|
||||
strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);
|
||||
|
||||
(void)unlink(sock_path);
|
||||
|
||||
if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
close(sfd);
|
||||
return 8;
|
||||
}
|
||||
(void)chmod(sock_path, 0660);
|
||||
|
||||
if (listen(sfd, 16) < 0) {
|
||||
perror("listen");
|
||||
(void)unlink(sock_path);
|
||||
close(sfd);
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "amduatd: root=%s sock=%s\n", root, sock_path);
|
||||
|
||||
while (!amduatd_should_exit) {
|
||||
int cfd = accept(sfd, NULL, NULL);
|
||||
if (cfd < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
perror("accept");
|
||||
break;
|
||||
}
|
||||
|
||||
(void)amduatd_handle_conn(cfd, &store, &cfg);
|
||||
(void)close(cfd);
|
||||
}
|
||||
|
||||
(void)unlink(sock_path);
|
||||
(void)close(sfd);
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue