259 lines
5.1 KiB
C
259 lines
5.1 KiB
C
// SPDX-License-Identifier: BSD-3-Clause
|
|
/* Generate C project
|
|
*
|
|
* Copyright (C) 2025, GCK.
|
|
* Written by vx-clutch (vx-clutch)
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include <pwd.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/wait.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <lib/err.h>
|
|
#include <lib/fs.h>
|
|
#include <lib/proginfo.h>
|
|
#include <lib/say.h>
|
|
#include <lib/textc.h>
|
|
|
|
#include "license.h"
|
|
|
|
typedef enum { MIT, GPL, BSD, UNL } license_t;
|
|
|
|
static const struct option longopts[] = {
|
|
{ "author", required_argument, 0, 'a' },
|
|
{ "license", required_argument, 0, 'l' },
|
|
{ 0, 0, 0, 0 }
|
|
};
|
|
|
|
static int exit_status;
|
|
|
|
static void print_help();
|
|
static void print_version();
|
|
|
|
static char *get_name()
|
|
{
|
|
int fds[2];
|
|
if (pipe(fds) == -1)
|
|
goto sysuser;
|
|
|
|
pid_t pid = fork();
|
|
if (pid == -1) {
|
|
close(fds[0]);
|
|
close(fds[1]);
|
|
goto sysuser;
|
|
}
|
|
|
|
if (pid == 0) {
|
|
dup2(fds[1], STDOUT_FILENO);
|
|
close(fds[0]);
|
|
close(fds[1]);
|
|
execlp("git", "git", "config", "--get", "user.name",
|
|
(char *)NULL);
|
|
_exit(127);
|
|
}
|
|
|
|
close(fds[1]);
|
|
char buf[256];
|
|
ssize_t n = read(fds[0], buf, sizeof buf - 1);
|
|
close(fds[0]);
|
|
int status;
|
|
waitpid(pid, &status, 0);
|
|
if (n > 0 && WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
|
buf[n] = 0;
|
|
buf[strcspn(buf, "\n")] = 0;
|
|
return str_dup(buf);
|
|
}
|
|
|
|
sysuser: {
|
|
char *name = getlogin();
|
|
if (name)
|
|
return str_dup(name);
|
|
struct passwd *pw = getpwuid(getuid());
|
|
if (pw && pw->pw_name)
|
|
return str_dup(pw->pw_name);
|
|
}
|
|
return str_dup("author");
|
|
}
|
|
|
|
static int get_year()
|
|
{
|
|
time_t now = time(NULL);
|
|
struct tm *t = localtime(&now);
|
|
|
|
return t->tm_year + 1900;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int optc;
|
|
int lose = 0;
|
|
char *m = str_dup("Does a thing"), *package;
|
|
bool shell = false;
|
|
char *author = get_name();
|
|
exit_status = EXIT_SUCCESS;
|
|
int year = get_year();
|
|
license_t license = BSD;
|
|
char *license_str = "BSD-3-Clause";
|
|
set_prog_name(argv[0]);
|
|
|
|
parse_standard_options(argc, argv, print_help, print_version);
|
|
|
|
while ((optc = getopt_long(argc, argv, "a:l:m:EqfS", longopts, NULL)) !=
|
|
-1)
|
|
switch (optc) {
|
|
case 'a':
|
|
if (optarg) {
|
|
if (author)
|
|
free(author);
|
|
author = str_dup(optarg);
|
|
}
|
|
break;
|
|
case 'm':
|
|
if (optarg) {
|
|
if (m)
|
|
free(m);
|
|
m = str_dup(optarg);
|
|
}
|
|
break;
|
|
case 'l':
|
|
if (!strcmp(optarg, "list")) {
|
|
puts("BSD\nGPL\nMIT\nUNL");
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
if (!strcmp(optarg, "GPL")) {
|
|
license = GPL;
|
|
license_str = "GPL-3.0-only";
|
|
} else if (!strcmp(optarg, "MIT")) {
|
|
license = MIT;
|
|
license_str = "MIT";
|
|
} else if (!strcmp(optarg, "BSD")) {
|
|
license = BSD;
|
|
license_str = "BSD-3-Clause";
|
|
} else if (!strcmp(optarg, "UNL")) {
|
|
license = UNL;
|
|
license_str = "Unlicense";
|
|
} else {
|
|
puts("BSD\nGPL\nMIT\nUNL");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
break;
|
|
case 'S':
|
|
shell = true;
|
|
break;
|
|
default:
|
|
lose = 1;
|
|
}
|
|
if (lose) {
|
|
emit_try_help();
|
|
}
|
|
|
|
if (optind >= argc) {
|
|
fatalf("no input name");
|
|
}
|
|
|
|
if (optind + 1 < argc) {
|
|
errorf("extra operand: %s", argv[optind + 1]);
|
|
emit_try_help();
|
|
}
|
|
|
|
package = str_dup(argv[optind]);
|
|
|
|
if (shell) {
|
|
fs_write(package, "\
|
|
#!/bin/sh\n\
|
|
# SPDX-License-Identifier: %s\n\
|
|
#\n\
|
|
# %s\n\
|
|
\n\
|
|
me=$0\n\
|
|
scriptversion=\"1.0.0\"\n\
|
|
\n\
|
|
version=\"$me $scriptversion\n\
|
|
\n\
|
|
Copyright (C) %d %s\n\
|
|
This is free software; you are free to change and redistribute it.\n\
|
|
There is NO WARRANTY, to the textent permitted by law.\"\n\
|
|
\n\
|
|
usage=\"\\\n\
|
|
Usage: $me [OPTION]...\n\
|
|
%s\n\
|
|
\n\
|
|
Options:\n\
|
|
\n\
|
|
--help print this help and exit\n\
|
|
--version output version information\"\n\
|
|
\n\
|
|
while [ $# -gt 0 ]; do\n\
|
|
case $1 in\n\
|
|
--help) echo \"$usage\"; exit 0;;\n\
|
|
--version) echo \"$version\"; exit 0;;\n\
|
|
-*)\n\
|
|
echo \"$0: Unknwon option '$1'.\" >&2\n\
|
|
echo \"$0: Try '--help' for more information.\" >&2\n\
|
|
exit 1 ;;\n\
|
|
esac\n\
|
|
shift\n\
|
|
done\n\
|
|
\n\
|
|
echo \"$0: done.\"\n\
|
|
\n\
|
|
# End: %s\
|
|
",
|
|
license_str, m, year, author, m, package);
|
|
struct stat st;
|
|
|
|
if (stat(package, &st) != 0) {
|
|
fatalfa(errno);
|
|
}
|
|
|
|
mode_t mode = st.st_mode | S_IXUSR;
|
|
|
|
if (chmod(package, mode) != 0) {
|
|
fatalfa(errno);
|
|
}
|
|
return exit_status;
|
|
}
|
|
|
|
return exit_status;
|
|
}
|
|
|
|
static void print_help()
|
|
{
|
|
printf("Usage: %s [OPTION]... [project-name]...\n", PROGRAM);
|
|
fputs("\
|
|
Generates an opinionated C project.\n",
|
|
stdout);
|
|
puts("");
|
|
fputs("\
|
|
--help display this help and exit\n\
|
|
--version display version information and exit\n",
|
|
stdout);
|
|
puts("");
|
|
fputs("\
|
|
--author=NAME Set the program author (default git username|system username)\n\
|
|
--license=LICENSE Set the program license (default BSD)\n",
|
|
stdout);
|
|
exit(exit_status);
|
|
}
|
|
|
|
static void print_version()
|
|
{
|
|
printf("%s %s %d\n", prog_name, VERSION, COMMIT);
|
|
|
|
printf("Copyright (C) %d GCK.\n", YEAR);
|
|
|
|
puts("This is free software: you are free to change and redistribute it.");
|
|
puts("There is NO WARRANTY, to the extent permitted by law.");
|
|
exit(exit_status);
|
|
}
|
|
|
|
/* end of file yait.c */
|