sle/src/main.c

142 lines
3.7 KiB
C

/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2021 KikooDX */
#include "editing_area/main.h"
#include "shared_data.h"
#include "tile_picker/main.h"
#include <getopt.h>
#include <raylib.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
static const int buffer_size = 256;
static void *create_shared_memory(size_t size);
static void overflow_prevention(void); /* work on optarg */
static void process_arguments(int argc, char **argv,
char tileset_path[buffer_size],
char level_path[buffer_size]);
/* The editor fork to create two windows. One will be the level editor
* and the other the tile selection. This is done to allow the user to
* organize these panels in the way they want to. */
int main(int argc, char **argv)
{
pid_t child_process;
char level_path[buffer_size] = "";
char tileset_path[buffer_size] = "";
struct SharedData *shared_data =
(struct SharedData *)create_shared_memory(
sizeof(struct SharedData));
shared_data->end_child = false;
shared_data->selected_tile = 69;
/* set log level */
SetTraceLogLevel(LOG_ERROR);
/* process arguments */
process_arguments(argc, argv, tileset_path, level_path);
/* forking here */
child_process = fork();
if (child_process < 0) {
fprintf(stderr, "ERROR: process couldn't fork");
return EXIT_FAILURE;
} else if (child_process == 0) {
/* child process, start the tile picker */
return tile_picker_main(tileset_path, shared_data);
} else {
/* main process, start the editing area */
editing_area_main(level_path, tileset_path,
shared_data);
return EXIT_SUCCESS;
}
}
static void *create_shared_memory(size_t size)
{
/* shared memory will be read & write */
int protection = PROT_READ | PROT_WRITE;
/* anonymous and shared, only child process will be able to
* access it */
int visibility = MAP_SHARED | MAP_ANONYMOUS;
return mmap(NULL, size, protection, visibility, -1, 0);
}
static void overflow_prevention(void)
{
/* make sure arguments won't overflow */
if (strlen(optarg) > buffer_size) {
fprintf(stderr,
"ERROR: option size %lu is "
"bigger than maximum %d\n",
strlen(optarg), buffer_size);
exit(EXIT_FAILURE);
}
}
static void process_arguments(int argc, char **argv,
char tileset_path[buffer_size],
char level_path[buffer_size])
{
int opt;
while (1) {
static struct option long_options[] = {
{"level", required_argument, 0, 'l'},
{"tileset", required_argument, 0, 't'},
{0, 0, 0, 0},
};
/* getopt_long stores the option index here */
int option_index = 0;
opt = getopt_long_only(argc, argv, "", long_options,
&option_index);
/* detect the end of the options */
if (opt == -1)
break;
switch (opt) {
case 'l':
overflow_prevention();
strcpy(level_path, optarg);
break;
case 't':
overflow_prevention();
strcpy(tileset_path, optarg);
break;
case '?':
/* getopt_long already printed an error message
*/
exit(EXIT_FAILURE);
default:
fprintf(stderr,
"ERROR: option -%c non handled "
"(open an issue!)\n",
opt);
exit(EXIT_FAILURE);
}
}
/* missing arguments? */
{
int error = 0;
if (level_path[0] == '\0') {
fprintf(stderr, "ERROR: no level path "
"specified (-level <path>)\n");
error = 1;
}
if (tileset_path[0] == '\0') {
fprintf(stderr,
"ERROR: no tileset path specified "
"(-tileset <path>)\n");
error = 1;
}
if (error)
exit(EXIT_FAILURE);
}
}