init
This commit is contained in:
31
Makefile
Normal file
31
Makefile
Normal file
@@ -0,0 +1,31 @@
|
||||
include config.mk
|
||||
|
||||
all: prepare log log_test rt make_conf
|
||||
@echo "libglacier-ng has finished building"
|
||||
|
||||
prepare:
|
||||
mkdir -p build
|
||||
mkdir -p build/lib
|
||||
mkdir -p build/include
|
||||
mkdir -p build/lib/tmp
|
||||
mkdir -p build/lib/shared
|
||||
mkdir -p build/include/glacier
|
||||
|
||||
log:
|
||||
$(CC) $(CFLAGS) src/log.c -c -o build/lib/tmp/log.o
|
||||
cp src/log.h build/include/glacier/log.h
|
||||
|
||||
log_test:
|
||||
$(CC) $(CFLAGS) -shared -fPIC src/log.c -o build/lib/shared/lg_log.so
|
||||
|
||||
rt:
|
||||
$(CC) $(CFLAGS) src/runtime.c -c -o build/lib/tmp/runtime.o
|
||||
|
||||
make_conf:
|
||||
$(CC) $(CFLAGS) src/make_conf.c -c -o build/lib/tmp/make_conf.o
|
||||
|
||||
install_test_dir:
|
||||
install build/lib/shared/lg_log.so $(TEST_DIR)
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
40
build/include/glacier/log.h
Normal file
40
build/include/glacier/log.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef LOG_H_
|
||||
#define LOG_H_
|
||||
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "color.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LG_INFO,
|
||||
LG_WARN,
|
||||
LG_ERR,
|
||||
LG_SUCCESS
|
||||
}
|
||||
loglevel_t;
|
||||
|
||||
int supports_utf8(void);
|
||||
const char *p2s(int priority);
|
||||
|
||||
void lg_printf(loglevel_t loglevel, const char *fmt, ...);
|
||||
void lg_syslog(int priority, const char *fmt, ...);
|
||||
void lg_log(bool use_syslog, FILE *logfile, int priority, const char *fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LOG_H_ */
|
||||
BIN
build/lib/shared/lg_log.so
Executable file
BIN
build/lib/shared/lg_log.so
Executable file
Binary file not shown.
BIN
build/lib/shared/log.so
Executable file
BIN
build/lib/shared/log.so
Executable file
Binary file not shown.
BIN
build/lib/tmp/log.o
Normal file
BIN
build/lib/tmp/log.o
Normal file
Binary file not shown.
BIN
build/lib/tmp/make_conf.o
Normal file
BIN
build/lib/tmp/make_conf.o
Normal file
Binary file not shown.
BIN
build/lib/tmp/runtime.o
Normal file
BIN
build/lib/tmp/runtime.o
Normal file
Binary file not shown.
7
config.mk
Normal file
7
config.mk
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# config.mk
|
||||
#
|
||||
|
||||
CFLAGS = -std=c11 -pedantic -O2 -flto -Wall -Wextra -Wshadow -Wformat=2 -Wconversion -Wpedantic -Werror
|
||||
|
||||
TEST_DIR = /home/lw/Projects/glacier-ng/lib
|
||||
25
src/color.h
Normal file
25
src/color.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* libcolor.h - header file to define colors */
|
||||
|
||||
#ifndef LIBCOLOR_H_
|
||||
#define LIBCOLOR_H_
|
||||
|
||||
/* Standard colors */
|
||||
#define COL_RED "\x1b[31m\x1b[1m"
|
||||
#define COL_GREEN "\x1b[32m\x1b[1m"
|
||||
#define COL_YELLOW "\x1b[33m\x1b[1m"
|
||||
#define COL_BLUE "\x1b[34m\x1b[1m"
|
||||
#define COL_MAGENTA "\x1b[35m\x1b[1m"
|
||||
#define COL_CYAN "\x1b[36m\x1b[1m"
|
||||
|
||||
/* Standard colors excluding bolded text */
|
||||
#define COL_RED_NB "\x1b[31m"
|
||||
#define COL_GREEN_NB "\x1b[32m"
|
||||
#define COL_YELLOW_NB "\x1b[33m"
|
||||
#define COL_BLUE_NB "\x1b[34m"
|
||||
#define COL_MAGENTA_NB "\x1b[35m"
|
||||
#define COL_CYAN_NB "\x1b[36m"
|
||||
|
||||
/* Reset colors */
|
||||
#define COL_RESET "\x1b[0m\x1b[m"
|
||||
|
||||
#endif
|
||||
22
src/deb.c
Normal file
22
src/deb.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
|
||||
#include "color.h"
|
||||
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int
|
||||
extract_tar(const char *tarfile, const char *dest)
|
||||
{
|
||||
struct archive *a = archive_read_new();
|
||||
struct archive *ext = archive_write_disk_new();
|
||||
}
|
||||
23
src/glacier.log
Normal file
23
src/glacier.log
Normal file
@@ -0,0 +1,23 @@
|
||||
[2025-09-16 17:54:10] [INFO] Glacier started with PID 12345
|
||||
[2025-09-16 20:09:54] [6] Glacier started with PID 12345
|
||||
[2025-09-16 20:13:34] [-173481940] Glacier started with PID 12345
|
||||
[2025-09-16 20:13:36] [-1935986644] Glacier started with PID 12345
|
||||
[2025-09-16 20:15:21] [INFO] Glacier started with PID 12345
|
||||
[2025-09-16 20:17:18] [INFO] Glacier started with PID 12345
|
||||
[2025-09-16 20:17:18] [ERR] Failed to install package glibc
|
||||
[2025-09-16 20:19:42] [INFO] Glacier started with PID 12345
|
||||
[2025-09-16 20:19:42] [ERR] Failed to install package glibc
|
||||
[2025-09-17 08:39:22] [INFO] Glacier started with PID 12345
|
||||
[2025-09-17 08:39:22] [ERR] Failed to install package glibc
|
||||
[2025-09-17 11:33:39] [INFO] Glacier started with PID 12345
|
||||
[2025-09-17 11:33:39] [ERR] Failed to install package glibc
|
||||
[2025-09-17 11:33:40] [INFO] Glacier started with PID 12345
|
||||
[2025-09-17 11:33:40] [ERR] Failed to install package glibc
|
||||
[2025-09-18 14:21:45] [INFO] Glacier started with PID 12345
|
||||
[2025-09-18 14:21:45] [ERR] Failed to install package glibc
|
||||
[2025-09-18 20:37:44] [INFO] Glacier started with PID 12345
|
||||
[2025-09-18 20:37:44] [ERR] Failed to install package glibc
|
||||
[2025-09-22 23:24:51] [INFO] Glacier started with PID 12345
|
||||
[2025-09-22 23:24:51] [ERR] Failed to install package glibc
|
||||
[2025-09-22 23:24:51] [INFO] Glacier started with PID 12345
|
||||
[2025-09-22 23:24:51] [ERR] Failed to install package glibc
|
||||
93
src/gpkg.c
Normal file
93
src/gpkg.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
|
||||
#include "color.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *PKG_NAME;
|
||||
char *PKG_DESC;
|
||||
int PKG_MAJOR;
|
||||
int PKG_MINOR;
|
||||
int PKG_PATCH;
|
||||
char *PKG_MAINT;
|
||||
char *PKG_LICENSE;
|
||||
char *PKG_ARCH;
|
||||
char **PKG_DEPS;
|
||||
char **PKG_CONFLICTS;
|
||||
}
|
||||
lg_gpkg_t;
|
||||
|
||||
static char
|
||||
*strdup_s(const char *s)
|
||||
{
|
||||
if (!s) { return NULL; }
|
||||
char *r = strdup(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
free_str_array(char **arr)
|
||||
{
|
||||
if (!arr) { return; }
|
||||
for (size_t i = 0; arr[i]; i++) { free(arr[i])); }
|
||||
free(arr);
|
||||
}
|
||||
|
||||
static char
|
||||
**split_csv_to_array(const char *s)
|
||||
{
|
||||
if (!s) { return NULL; }
|
||||
|
||||
char *cpy = strdup_s(s);
|
||||
if (!cpy) { return NULL; }
|
||||
|
||||
size_t count = 0;
|
||||
for (char *p = cpy; *p; p++) {
|
||||
if (*p == ',') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
size_t max = count + 1;
|
||||
char **arr = calloc(max + 1, sizeof(char*));
|
||||
if (!arr) { free(cpy); return NULL; }
|
||||
size_t idx = 0;
|
||||
char *saveptr = NULL;
|
||||
char *tok = strtok_r(cpt, ",", &saveptr);
|
||||
while (tok) {
|
||||
while (isspace((unsigned char)*tok))) { tok++; }
|
||||
char *end =p tok + strlen(tok) - 1;
|
||||
while (end > tok && isspace((unsigned char)*end)) { *end-- = '\0'; }
|
||||
arr[idx++ = strdup_s(tok);
|
||||
tok = strtok_r(NULL, ",", &saveptr);
|
||||
}
|
||||
|
||||
arr[idx] = NULL;
|
||||
free(cpy);
|
||||
return arr;
|
||||
}
|
||||
|
||||
lg_gpkg_t
|
||||
*gpkg_new(void)
|
||||
{
|
||||
lg_gpkg_t *g = calloc(1, sizeof(lg_gpkg_t));
|
||||
return g;
|
||||
}
|
||||
|
||||
void
|
||||
gpkg_free(lg_gpkg_t *g)
|
||||
{
|
||||
if (!g) { return; }
|
||||
free(g->PKG_NAME);
|
||||
free(g->PKG_DESC);
|
||||
free(g->PKG_MAINT);
|
||||
free(g->PKG_LICENSE);
|
||||
free(g->PKG_ARCH);
|
||||
|
||||
free_str_array(g->PKG_DEPS);
|
||||
free_str_array(g->PKG_CONFLICTS);
|
||||
|
||||
free(g);
|
||||
}
|
||||
70
src/gpkg.lua
Normal file
70
src/gpkg.lua
Normal file
@@ -0,0 +1,70 @@
|
||||
local gpkg = {}
|
||||
|
||||
function gpkg.parse_manifest(buffer)
|
||||
local pkg = {
|
||||
PKG_NAME = nil,
|
||||
PKG_DESC = nil,
|
||||
PKG_MAJOR = 0,
|
||||
PKG_MINOR = 0,
|
||||
PKG_PAATCH = 0,
|
||||
PKG_MAINT = nil,
|
||||
PKG_LICENSE = nil,
|
||||
PKG_ARCH = nil,
|
||||
PKG_DEPS = {},
|
||||
PKG_CONFLICTS = {},
|
||||
}
|
||||
|
||||
for line in buffer:gmatch("[^\r\n]+") do
|
||||
line = line:match("^%s*(.-)%s*$+");
|
||||
if line -= "" and not line:match("^#") then
|
||||
local key, val = line:match("([^=]+)=(.*)");
|
||||
if key and val then
|
||||
key = key:match("^%s*(.-)%s*$");
|
||||
val = val:match("^%s*(.-)%s*$");
|
||||
|
||||
if key == "PKG_NAME" then pkg.PKG_NAME = val
|
||||
elseif key == "PKG_DESC" then pkg.PKG_DESC = val
|
||||
elseif key == "PKG_MAJOR" then pkg.PKG_MAJOR = tonumber(val) or 0
|
||||
elseif key == "PKG_MINOR" then pkg.PKG_MINOR = tonumber(val) or 0
|
||||
elseif key == "PKG_PATCH" then pkg.PKG_PATCH = tonumber(val) or 0
|
||||
elseif key == "PKG_MAINT" then pkg.PKG_MAINT = val
|
||||
elseif key == "PKG_LICENSE" then pkg.PKG_LICENSE = val
|
||||
elseif key == "PKG_ARCH" then pkg.PKG_ARCH = val
|
||||
elseif key == "PKG_DEPS" then
|
||||
pkg.PKG_DEPS = {}
|
||||
for dep in val:gmatch("[^,%s]+") do
|
||||
table.insert(pkg.PKG_DEPS, dep)
|
||||
end
|
||||
elseif key == "PKG_CONFLICTS" then
|
||||
pkg.PKG_CONFLICTS = {}
|
||||
for c in val:gmatch("[^,%s]+") do
|
||||
table.insert(pkg.PKG_CONFLICTS, c)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return pkg
|
||||
end
|
||||
|
||||
function gpkg.serialize(pkg)
|
||||
local out = {}
|
||||
local function line(k, v) table.insert(out, string.format("%s=%s", k, v or "")) end
|
||||
|
||||
line("PKG_NAME", pkg.PKG_NAME or "")
|
||||
line("PKG_DESC", pkg.PKG_DESC or "")
|
||||
line("PKG_MAJOR", pkg.PKG_MAJOR or 0)
|
||||
line("PKG_MINOR", pkg.PKG_MINOR or 0)
|
||||
line("PKG_PATCH", pkg.PKG_PATCH or 0)
|
||||
line("PKG_MAINT", pkg.PKG_MAINT or "")
|
||||
line("PKG_LICENSE", pkg.PKG_LICENSE or "")
|
||||
line("PKG_ARCH", pkg.PKG_ARCH or "")
|
||||
|
||||
line("PKG_DEPS", table.concat(pkg.PKG_DEPS or {}, ","))
|
||||
line("PKG_CONFLICTS", table.concat(pkg.PKG_CONFLICTS or {}, ","))
|
||||
|
||||
return table.concat(out, "\n") .. "\n"
|
||||
end
|
||||
|
||||
return gpkg
|
||||
174
src/log.c
Normal file
174
src/log.c
Normal file
@@ -0,0 +1,174 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "color.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LG_INFO,
|
||||
LG_WARN,
|
||||
LG_ERR,
|
||||
LG_SUCCESS
|
||||
}
|
||||
loglevel_t;
|
||||
|
||||
static int
|
||||
supports_utf8(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return GetConsoleOutputCP() == 65001;
|
||||
#else
|
||||
setlocale(LC_CTYPE, "");
|
||||
const char *codeset = nl_langinfo(CODESET);
|
||||
return (codeset && strcmp(codeset, "UTF-8") == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Converts priority integer to string */
|
||||
const char
|
||||
*p2s(int priority)
|
||||
{
|
||||
switch (priority)
|
||||
{
|
||||
case LOG_EMERG: return "EMERG"; break;
|
||||
case LOG_ALERT: return "ALERT"; break;
|
||||
case LOG_CRIT: return "CRIT"; break;
|
||||
case LOG_ERR: return "ERR"; break;
|
||||
case LOG_WARNING: return "WARN"; break;
|
||||
case LOG_NOTICE: return "NOTICE"; break;
|
||||
case LOG_INFO: return "INFO"; break;
|
||||
case LOG_DEBUG: return "DEBUG"; break;
|
||||
default: return "UNKNOWN"; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lg_printf(loglevel_t loglevel, const char *fmt, ...)
|
||||
{
|
||||
const char *prefix;
|
||||
|
||||
int utf8_ok = supports_utf8();
|
||||
|
||||
switch (loglevel) {
|
||||
case LG_INFO:
|
||||
prefix = COL_BLUE "[i]" COL_RESET " ";
|
||||
break;
|
||||
case LG_WARN:
|
||||
prefix = COL_YELLOW "[!]" COL_RESET " ";
|
||||
break;
|
||||
case LG_ERR:
|
||||
prefix = COL_RED "[x]" COL_RESET " ";
|
||||
break;
|
||||
case LG_SUCCESS:
|
||||
if (utf8_ok) {
|
||||
prefix = COL_GREEN "[" "\xE2\x9C\x93" "]" COL_RESET " ";
|
||||
} else {
|
||||
prefix = COL_GREEN "[*]" COL_RESET " ";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
prefix = "[?] ";
|
||||
}
|
||||
|
||||
fputs(prefix, stdout);
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
lg_syslog(int priority, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsyslog(priority, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
lg_log(bool use_syslog, const char *logfile, int priority, const char *fmt, ...)
|
||||
{
|
||||
FILE *log = fopen(logfile, "a");
|
||||
if (!log) {
|
||||
perror("fopen");
|
||||
return;
|
||||
}
|
||||
|
||||
time_t now = time(NULL);
|
||||
struct tm *t = localtime(&now);
|
||||
|
||||
char timestamp[20];
|
||||
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", t);
|
||||
|
||||
fprintf(log, "[%s] [%s] ", timestamp, p2s(priority));
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vfprintf(log, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
fputc('\n', log);
|
||||
fflush(log);
|
||||
|
||||
if (use_syslog) {
|
||||
va_list args2;
|
||||
va_start(args2, fmt);
|
||||
vsyslog(priority, fmt, args2);
|
||||
va_end(args2);
|
||||
fclose(log);
|
||||
}
|
||||
else {
|
||||
fclose(log);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lg_gpkg_help(int argc, char *argv[])
|
||||
{
|
||||
(void)argc;
|
||||
|
||||
printf("%s: Manage the user package index\n", argv[0]);
|
||||
printf("usage: %s [OPTIONS] PKG...\n", argv[0]);
|
||||
printf("\n");
|
||||
printf("Options:\n"
|
||||
"\t{-h}\tShow this message\n"
|
||||
"\t{-v}\tShow the current version\n"
|
||||
"\t{-f} PKG...\tMerge a package into the user index\n"
|
||||
"\t{-u} PKG...\tUpgrade a merged package\n"
|
||||
"\t{-x} PKG...\tRemove a merged package\n"
|
||||
"\n"
|
||||
"This program is free software.\n"
|
||||
"See the GNU GPL version 3 for details.\n"
|
||||
);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
lg_printf(LG_INFO, "info");
|
||||
lg_printf(LG_WARN, "warning");
|
||||
lg_printf(LG_ERR, "error");
|
||||
lg_printf(LG_SUCCESS, "success");
|
||||
|
||||
lg_log(true, "./glacier.log", LOG_INFO, "Glacier started with PID %d", 12345);
|
||||
lg_log(true, "./glacier.log", LOG_ERR, "Failed to install package %s", "glibc");
|
||||
|
||||
return 0;
|
||||
}
|
||||
40
src/log.h
Normal file
40
src/log.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef LOG_H_
|
||||
#define LOG_H_
|
||||
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "color.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LG_INFO,
|
||||
LG_WARN,
|
||||
LG_ERR,
|
||||
LG_SUCCESS
|
||||
}
|
||||
loglevel_t;
|
||||
|
||||
int supports_utf8(void);
|
||||
const char *p2s(int priority);
|
||||
|
||||
void lg_printf(loglevel_t loglevel, const char *fmt, ...);
|
||||
void lg_syslog(int priority, const char *fmt, ...);
|
||||
void lg_log(bool use_syslog, FILE *logfile, int priority, const char *fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LOG_H_ */
|
||||
95
src/make_conf.c
Normal file
95
src/make_conf.c
Normal file
@@ -0,0 +1,95 @@
|
||||
#define _POSIX_C_SOURcE 200809L
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_LINE 1024
|
||||
|
||||
static char
|
||||
*trim(char *s) {
|
||||
char *end;
|
||||
while (isspace((unsigned char)*s)) { s++; }
|
||||
if (*s == 0) { return s; }
|
||||
end = s + strlen(s) - 1;
|
||||
while (end > s && isspace((unsigned char)*end)) { *end-- = 0; }
|
||||
return s;
|
||||
}
|
||||
|
||||
static char
|
||||
*expand(char *value)
|
||||
{
|
||||
size_t cap = strlen(value) + 1;
|
||||
char *buffer = malloc(cap);
|
||||
if (!buffer) { return NULL; }
|
||||
char *out = buffer;
|
||||
|
||||
char *p = value;
|
||||
|
||||
while (*p) {
|
||||
if (*p == '$') {
|
||||
p++;
|
||||
char var[128], *vp = var;
|
||||
while (*p && (isalnum((unsigned char)*p) || *p == '_')) {
|
||||
*vp++ = *p++;
|
||||
}
|
||||
|
||||
*vp = '\0';
|
||||
char *val = getenv(var);
|
||||
if (val) {
|
||||
size_t len = strlen(val);
|
||||
size_t used = (size_t)(out - buffer);
|
||||
if (used + len + 1 > cap) {
|
||||
cap = used + len + 1;
|
||||
buffer = realloc(buffer, cap);
|
||||
if (!buffer) { return NULL; }
|
||||
out = buffer + used;
|
||||
}
|
||||
|
||||
memcpy(out, val, len);
|
||||
out += len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*out++ = *p++;
|
||||
}
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int
|
||||
parse_makeconf(const char *filename)
|
||||
{
|
||||
FILE *make_conf = fopen(filename, "r");
|
||||
if (!make_conf) {
|
||||
perror("fopen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char line[MAX_LINE];
|
||||
while (fgets(line, sizeof(line), make_conf)) {
|
||||
char *p = trim(line);
|
||||
if (*p == '\0' || *p == '#') { continue; }
|
||||
|
||||
char *eq = strchr(p, '=');
|
||||
if (!eq) { continue; }
|
||||
|
||||
*eq = '\0';
|
||||
char *key = trim(p);
|
||||
char *val = trim(eq + 1);
|
||||
|
||||
char *expanded = expand(val);
|
||||
if (expanded) {
|
||||
setenv(key, expanded, 1);
|
||||
free(expanded);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(make_conf);
|
||||
return 0;
|
||||
}
|
||||
4
src/report.c
Normal file
4
src/report.c
Normal file
@@ -0,0 +1,4 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
|
||||
45
src/runtime.c
Normal file
45
src/runtime.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "color.h"
|
||||
|
||||
bool
|
||||
lg_is_root(void)
|
||||
{
|
||||
if (getuid() != 0) {
|
||||
return false;
|
||||
}
|
||||
else if (getuid() == 0) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
lg_runtime_exists(void)
|
||||
{
|
||||
const char *rt_files[] = {
|
||||
"/etc/glacier/glacier.conf",
|
||||
"/etc/glacier/make.conf"
|
||||
};
|
||||
|
||||
size_t num_of_files = sizeof(rt_files) / sizeof(rt_files[0]);
|
||||
|
||||
for (size_t f_index = 0; f_index < num_of_files; f_index++) {
|
||||
if (access(rt_files[f_index], F_OK) == 0) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
201
src/templ.c
Normal file
201
src/templ.c
Normal file
@@ -0,0 +1,201 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct html_report
|
||||
{
|
||||
FILE *f;
|
||||
int error;
|
||||
};
|
||||
|
||||
#include "html_report.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Internal struct */
|
||||
struct html_report {
|
||||
FILE *f;
|
||||
int error;
|
||||
};
|
||||
|
||||
/* Escape special HTML characters safely */
|
||||
static char *
|
||||
html_escape(const char *s)
|
||||
{
|
||||
if (!s) {
|
||||
return strdup("");
|
||||
}
|
||||
|
||||
size_t extra = 0;
|
||||
for (const unsigned char *p = (const unsigned char*)s; *p; ++p) {
|
||||
switch (*p) {
|
||||
case '&': extra += 4; break;
|
||||
case '<': extra += 3; break;
|
||||
case '>': extra += 3; break;
|
||||
case '"': extra += 5; break;
|
||||
case '\'': extra += 4; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t len = strlen(s);
|
||||
char *out = malloc(len + extra + 1);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *q = out;
|
||||
for (const unsigned char *p = (const unsigned char*)s; *p; ++p) {
|
||||
switch (*p) {
|
||||
case '&': memcpy(q, "&", 5); q += 5; break;
|
||||
case '<': memcpy(q, "<", 4); q += 4; break;
|
||||
case '>': memcpy(q, ">", 4); q += 4; break;
|
||||
case '"': memcpy(q, """, 6); q += 6; break;
|
||||
case '\'': memcpy(q, "'", 5); q += 5; break;
|
||||
default: *q++ = *p; break;
|
||||
}
|
||||
}
|
||||
*q = '\0';
|
||||
return out;
|
||||
}
|
||||
|
||||
html_report *
|
||||
html_begin(const char *filename, const char *title)
|
||||
{
|
||||
if (!filename || !title) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE *f = fopen(filename, "w");
|
||||
if (!f) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
html_report *r = malloc(sizeof *r);
|
||||
if (!r) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
r->f = f;
|
||||
r->error = 0;
|
||||
|
||||
if (fprintf(f,
|
||||
"<!doctype html>\n"
|
||||
"<html lang=\"en\">\n"
|
||||
"<head>\n"
|
||||
" <meta charset=\"utf-8\">\n"
|
||||
" <title>%s</title>\n"
|
||||
" <style>\n"
|
||||
" body { font-family: sans-serif; margin: 2em; }\n"
|
||||
" table { border-collapse: collapse; margin-top: 1em; }\n"
|
||||
" th, td { border: 1px solid #aaa; padding: 0.5em 1em; }\n"
|
||||
" th { background: #eee; }\n"
|
||||
" </style>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
" <h1>%s</h1>\n",
|
||||
title, title) < 0) {
|
||||
fclose(f);
|
||||
free(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
html_add_summary(html_report *r, const char *text)
|
||||
{
|
||||
if (!r || !r->f || r->error) {
|
||||
return -1;
|
||||
}
|
||||
char *esc = html_escape(text);
|
||||
if (!esc) {
|
||||
r->error = 1;
|
||||
return -1;
|
||||
}
|
||||
int ret = fprintf(r->f, " <p>%s</p>\n", esc);
|
||||
free(esc);
|
||||
if (ret < 0) {
|
||||
r->error = 1;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
html_begin_table(html_report *r)
|
||||
{
|
||||
if (!r || !r->f || r->error) {
|
||||
return -1;
|
||||
}
|
||||
if (fprintf(r->f, " <table>\n") < 0) {
|
||||
r->error = 1;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
html_add_row(html_report *r, const char *cell1, const char *cell2)
|
||||
{
|
||||
if (!r || !r->f || r->error) {
|
||||
return -1;
|
||||
}
|
||||
char *a = html_escape(cell1);
|
||||
char *b = html_escape(cell2);
|
||||
if (!a || !b) {
|
||||
free(a);
|
||||
free(b);
|
||||
r->error = 1;
|
||||
return -1;
|
||||
}
|
||||
int ret = fprintf(r->f, " <tr><td>%s</td><td>%s</td></tr>\n",
|
||||
a, b);
|
||||
free(a);
|
||||
free(b);
|
||||
if (ret < 0) {
|
||||
r->error = 1;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
html_end_table(html_report *r)
|
||||
{
|
||||
if (!r || !r->f || r->error) {
|
||||
return -1;
|
||||
}
|
||||
if (fprintf(r->f, " </table>\n") < 0) {
|
||||
r->error = 1;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
html_end(html_report *r)
|
||||
{
|
||||
if (!r) {
|
||||
return -1;
|
||||
}
|
||||
int ok = 0;
|
||||
if (r->f) {
|
||||
if (!r->error) {
|
||||
if (fprintf(r->f, "</body>\n</html>\n") < 0) {
|
||||
ok = -1;
|
||||
}
|
||||
}
|
||||
if (fclose(r->f) == EOF) {
|
||||
ok = -1;
|
||||
}
|
||||
}
|
||||
free(r);
|
||||
return ok;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user