Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- **hd** - makes `<h1>` headings
- **yandere** - prints a yandere-like sentence *ad infinitum*
- **iw** - a helper program to make a message like an installation wizard to stdout
- **ud** - a fake updater

## Installation

Expand Down
15 changes: 15 additions & 0 deletions ud/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Introduction

`ud` is a fake updater.

```bash
$ ud -m 마인크래프트해킹버전1.21.3 -m 메소복사버그v2 -i8
remove: 메소복사버그v2.zip
extract: 마인크래프트해킹버전1.21.3.jpeg
archive: 마인크래프트해킹버전1.21.3.txt
build: 메소복사버그v2.zip
archive: 메소복사버그v2.obj
remove: 메소복사버그v2.obj
download: 마인크래프트해킹버전1.21.3.obj
archive: 메소복사버그v2.dll
```
5 changes: 5 additions & 0 deletions ud/c/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ud
ud.exe

*.o
*.d
42 changes: 42 additions & 0 deletions ud/c/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## Variables ##
TARGET := ud

CC := gcc
CFLAGS := -O -Wall -W -pedantic
CFLAGS += -g --std=c2x
CFLAGS += -MMD -MP
CPPFLAGS = \
-I $(DIR_LIB) \
-DPROGNAME='"$(TARGET)"' \
$(if $(DIR_DATA),-DDIR_DATA='"$(DIR_DATA)"')

SOURCES = $(wildcard *.c)
LIB_SRCS = $(wildcard $(DIR_LIB)/*.c)
OBJECTS = $(SOURCES:.c=.o)
LIB_OBJS = $(notdir $(LIB_SRCS:.c=.o))

DIR_LIB := ../../lib

## Targets ##
.PHONY: all clean

## Default Goal ##
all: $(TARGET)

## Build ##
$(TARGET): $(OBJECTS) $(LIB_OBJS)
$(CC) $^ $(CFLAGS) -o $@

$(OBJECTS): %.o: %.c
$(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@

$(LIB_OBJS): %.o: $(DIR_LIB)/%.c
$(CC) $< $(CPPFLAGS) $(CFLAGS) -c -o $@

## Dependency ##
-include $(OBJECTS:.o=.d)
-include $(LIB_OBJS:.o=.d)

## Tasks ##
clean:
rm -f $(TARGET) $(TARGET).exe *.o *.d
118 changes: 118 additions & 0 deletions ud/c/argp_drivers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#include "argp_drivers.h"
#include "argp_drivers.internals.h"

static bool drive_help(argtok_t *tok, argerr_t *err) {
(void) tok, (void) err;
cfg.help = true;
return true;
}

static bool drive_msg(argtok_t *tok, argerr_t *err) {
(void) err;
/* +1 for \0 */
array_append(cfg.msgs, tok->value, strlen(tok->value) + 1);
return true;
}

static bool drive_iter(argtok_t *tok, argerr_t *err) {
char *i;
unsigned long ret;

err->errhandle = argp_errhandle_default;

if (tok->value[strspn(tok->value, " \t\n\r\v\f")] == '-') {
err->reason = "iteration must not be negative";
return false;
}

errno = 0;
ret = strtoul(tok->value, &i, 10);

if (errno == ERANGE) {
err->reason = "out of range";
return false;
}
if (i == tok->value) {
err->reason = "conversion not performed";
return false;
}
if (*i != '\0') {
err->reason = "invalid trailing characters";
return false;
}
if (ret > SIZE_MAX) {
err->reason = "iteration out of range";
return false;
}

cfg.iter = ret;
return true;
}

static bool drive_lang(argtok_t *tok, argerr_t *err) {
typedef struct {
const char *lang;
langopt_enum_t enum_val;
} mapper_t;

static const mapper_t accept_set[] = {
{ "en", LangoptEnumEn },
{ "ko", LangoptEnumKo }
};
static const size_t accept_set_len = ARRLEN(accept_set);

const mapper_t *map;

for (size_t i = 0; i < accept_set_len; i++) {
map = &accept_set[i];
if (!strcmp(tok->value, map->lang)) {
cfg.lang = map->enum_val;
return true;
}
}

/* error path */
static const errhandle_unrecognized_value_ctx_t ctx = {
.targets = (const void **) &accept_set,
.targets_len = accept_set_len,
.target_siz = ESIZ(accept_set)
};

err->errhandle = errhandle_unrecognized_value;
err->ctx = &ctx;
err->ctx_siz = sizeof ctx;
return false;
}

static void errhandle_unrecognized_value(argtok_t *tok, const char *reason, void *ctx) {
find_alikes_ret_t ret;
errhandle_unrecognized_value_ctx_t *ectx;

(void) reason;
ectx = ctx;

ret = find_alikes(
tok->value,
ectx->targets,
ectx->targets_len,
ectx->target_siz
);

safe_vprintf(
"%s: unrecognized value " Cbwhite "'%s'" Creset ".",
tok->field, tok->value
);
safe_vprintf(" Do you mean ");
if (ret.nmemb == 1) {
safe_vprintf(Cbgreen "'%s'" Creset "?\n", ret.alikes[0]);
}
else {
safe_vprintf("one of the following?\n\t" Cbgreen);
for (size_t i = 0; i < ret.nmemb; i++) {
safe_vprintf("%s ", ret.alikes[i]);
}
safe_vprintf(Creset "\n");
}

free(ret.alikes);
}
9 changes: 9 additions & 0 deletions ud/c/argp_drivers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef ARGP_DRIVERS_H
#define ARGP_DRIVERS_H

#include "argparse.h"

extern optmd_t optmds[];
extern const size_t optmds_len;

#endif
66 changes: 66 additions & 0 deletions ud/c/argp_drivers.internals.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#ifndef ARGP_DRIVERS_INTERNALS_H
#define ARGP_DRIVERS_INTERNALS_H

#include <errno.h>
#include <limits.h>

#include "common.h"
#include "config.h"
#include "wrappers.h"
#include "strutils.h"
#include "colorcodes.h"
#include "argp_drivers.h"

typedef struct {
const void **targets;
size_t targets_len;
size_t target_siz;
} errhandle_unrecognized_value_ctx_t;

static opt_driver_t drive_help;
static opt_driver_t drive_msg;
static opt_driver_t drive_iter;
static opt_driver_t drive_lang;

static opt_errhandler_t errhandle_unrecognized_value;

/*==================*
| EXTERN VARIABLES |
*==================*/
optmd_t optmds[] = {
{
.sname = 'h',
.lname = "help",
.drive = drive_help,
.reqv = false,
.help = "prints the manual page",
.unique = true
},
{
.sname = 'm',
.lname = "msg",
Comment thread
logic-finder marked this conversation as resolved.
Resolved
.drive = drive_msg,
.reqv = true,
.help = "specify the message to print out",
.unique = false
},
{
.sname = 'i',
.lname = "iterate",
.drive = drive_iter,
.reqv = true,
.help = "specify the number of iteration",
.unique = true
},
{
.sname = '\0',
.lname = "lang",
.drive = drive_lang,
.reqv = true,
.help = "specify the language to speak",
.unique = true
}
};
const size_t optmds_len = ARRLEN(optmds);

#endif
84 changes: 84 additions & 0 deletions ud/c/config.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "config.h"
#include "config.internals.h"

extern void init_config(config_t *cfg) {
cfg->srcs = array_create(NULL);
cfg->msgs = array_create(NULL);
cfg->iter = 8;
cfg->lang = LangoptEnumEn;
}

extern void destroy_config(config_t *cfg) {
array_destroy(cfg->srcs);
array_destroy(cfg->msgs);
}

extern config_statcode_t apply_config(config_t *cfg) {
config_statcode_t ret;

if ((ret = check_help(cfg)) != ConfigStatcodeOk)
goto cleanup;
if ((ret = check_msg(cfg)) != ConfigStatcodeOk)
goto cleanup;

cleanup: /* nothing to clean up, just return */
return ret;
}

static config_statcode_t check_help(config_t *cfg) {
if (cfg->help == false) {
return ConfigStatcodeOk;
}

return print_manpage();
}

static config_statcode_t check_msg(config_t *cfg) {
if (array_size(cfg->msgs) > 0) {
return ConfigStatcodeOk;
}

fprintf(stderr, ENPREFIX "--msg is a required flag. Terminating.\n");
return ConfigStatcodeNoMsg;
}

static config_statcode_t print_manpage(void) {
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix))
if (!system(NULL)) {
return print_manual_fallback();
}

if (system("man " DIR_MANPAGE)) {
return print_manual_fallback();
}

return ConfigStatcodeNormalExit;
#else
return print_manual_fallback();
#endif
}

static config_statcode_t print_manual_fallback(void) {
FILE *fp;
int ch;

fp = fopen(DIR_MANPAGE_TXT, "r");
Comment thread
logic-finder marked this conversation as resolved.
Resolved
if (fp == NULL) {
fprintf(
stderr,
ENPREFIX "couldn't open the manpage from %s\n",
DIR_MANPAGE_TXT
);
return ConfigStatcodeNoManpage;
}

while ((ch = fgetc(fp)) != EOF) {
fputc(ch, stdout);
}

if (fclose(fp) == EOF) {
return ConfigStatcodeErr;
}

return ConfigStatcodeNormalExit;
}
35 changes: 35 additions & 0 deletions ud/c/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef CONFIG_H
#define CONFIG_H

#include <stdbool.h>

#include "array.adt.h"

typedef enum {
LangoptEnumEn,
LangoptEnumKo
} langopt_enum_t;

typedef struct config {
array_t *srcs;
bool help;
array_t *msgs;
size_t iter;
langopt_enum_t lang;
} config_t;

typedef enum {
ConfigStatcodeOk,
ConfigStatcodeNormalExit,
ConfigStatcodeErr,
ConfigStatcodeNoMsg,
ConfigStatcodeNoManpage
} config_statcode_t;

void init_config(config_t *cfg);
void destroy_config(config_t *cfg);
config_statcode_t apply_config(config_t *cfg);

extern config_t cfg;

#endif
Loading
Loading