initial commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
compile_commands.json
|
||||||
|
.cache
|
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[submodule "lib/log.c"]
|
||||||
|
path = lib/log.c
|
||||||
|
url = https://github.com/rxi/log.c
|
||||||
|
[submodule "lib/ds"]
|
||||||
|
path = lib/ds
|
||||||
|
url = https://git.squi.bid/squibid/ds
|
10
README.md
Normal file
10
README.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Womblic
|
||||||
|
command line helper tool which does everything for me
|
||||||
|
|
||||||
|
usage:
|
||||||
|
```bash
|
||||||
|
wom
|
||||||
|
```
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
add dev env creator
|
22
completions/_wom.zsh
Normal file
22
completions/_wom.zsh
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#compdef wom
|
||||||
|
|
||||||
|
_arguments \
|
||||||
|
'1:flag:->flags' \
|
||||||
|
'*:: :->args'
|
||||||
|
|
||||||
|
case "$state" in
|
||||||
|
flags)
|
||||||
|
local -a opts
|
||||||
|
opts=(
|
||||||
|
'-c:Path to config file'
|
||||||
|
'-v:Show version and exit'
|
||||||
|
'-h:Show help text'
|
||||||
|
$(wom subcmds)
|
||||||
|
)
|
||||||
|
_describe 'flags' opts
|
||||||
|
;;
|
||||||
|
args)
|
||||||
|
case $line[1] in
|
||||||
|
-c) _files ;;
|
||||||
|
esac
|
||||||
|
esac
|
47
include/api.h
Normal file
47
include/api.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ds.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
void (*cb)(void *, int argc, char *argv[]);
|
||||||
|
void *data;
|
||||||
|
} wom_subcmd_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief pointer to all registered subcommands
|
||||||
|
*/
|
||||||
|
extern ds_sll_t *subcmds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief register a new subcommand
|
||||||
|
*
|
||||||
|
* @param name name which should be used to call subcommand
|
||||||
|
* @param cb function to run when name is called
|
||||||
|
* @param data pointer to data to pass to the cb
|
||||||
|
* @return 0 on success
|
||||||
|
*/
|
||||||
|
int register_subcmd(char *name, void (*cb)(void *, int argc, char *argv[]), void *data);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief list out all registered subcmds
|
||||||
|
*
|
||||||
|
* @return list of subcmds
|
||||||
|
*/
|
||||||
|
char **list_subcmds();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief run subcmds mentioned in argv
|
||||||
|
*
|
||||||
|
* @param argc argc
|
||||||
|
* @param argv argv
|
||||||
|
*/
|
||||||
|
void run_subcmds(int argc, char *argv[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief unregister and free all subcmds
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
*/
|
||||||
|
int cleanup_subcmds();
|
15
include/conf.h
Normal file
15
include/conf.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief attempt to find the config path
|
||||||
|
*
|
||||||
|
* @return the path
|
||||||
|
*/
|
||||||
|
char *conf_config_path(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief attempt to find the state path
|
||||||
|
*
|
||||||
|
* @return the path
|
||||||
|
*/
|
||||||
|
char *conf_state_path(void);
|
20
include/lua/wom.h
Normal file
20
include/lua/wom.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <lauxlib.h>
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief list of all functions
|
||||||
|
*/
|
||||||
|
extern struct luaL_Reg *womlib;
|
||||||
|
|
||||||
|
int wom_register_subcmd(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief push a lua table with all the subcmds onto the lua stack
|
||||||
|
*
|
||||||
|
* @param L the lua state
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int wom_list_subcmds(lua_State *L);
|
26
include/lua/wom_fs.h
Normal file
26
include/lua/wom_fs.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <lauxlib.h>
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief list of all filesystem functions
|
||||||
|
*/
|
||||||
|
extern struct luaL_Reg *womfslib;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief create a fs iter for lua
|
||||||
|
*
|
||||||
|
* @param L the lua state
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int wom_fs_dir(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get the type of a directory in lua
|
||||||
|
*
|
||||||
|
* @param L the lua state
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int wom_fs_type(lua_State *L);
|
11
include/subcmds.h
Normal file
11
include/subcmds.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The funcs below are not in need of documentation because they follow the
|
||||||
|
* subcmd pattern
|
||||||
|
*/
|
||||||
|
|
||||||
|
void timer_subcmd(void *, int argc, char *argv[]);
|
||||||
|
void subcmds_dev(void *, int argc, char *argv[]);
|
||||||
|
void motd_subcmd(void *, int argc, char *argv[]);
|
||||||
|
void subcmds_subcmd(void *, int argc, char *argv[]);
|
1
lib/ds
Submodule
1
lib/ds
Submodule
Submodule lib/ds added at 16470f2592
1
lib/log.c
Submodule
1
lib/log.c
Submodule
Submodule lib/log.c added at f9ea34994b
51
meson.build
Normal file
51
meson.build
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
project('womblic', 'c',
|
||||||
|
version: '0.0.1',
|
||||||
|
license: 'GPLv3')
|
||||||
|
|
||||||
|
add_project_arguments([
|
||||||
|
'-DVERSION="@0@"'.format(meson.project_version()),
|
||||||
|
'-DLOG_USE_COLOR' # enable colored logs
|
||||||
|
], language: 'c')
|
||||||
|
|
||||||
|
# get all the source files for the executable
|
||||||
|
luafiles = files(
|
||||||
|
'src/lua/wom.c',
|
||||||
|
'src/lua/wom_fs.c'
|
||||||
|
)
|
||||||
|
|
||||||
|
subcmds = files(
|
||||||
|
'src/subcmds/clock.c',
|
||||||
|
'src/subcmds/dev.c',
|
||||||
|
'src/subcmds/motd.c',
|
||||||
|
'src/subcmds/project.c',
|
||||||
|
'src/subcmds/subcmds.c',
|
||||||
|
)
|
||||||
|
|
||||||
|
srcfiles = files(
|
||||||
|
'src/main.c',
|
||||||
|
'src/api.c',
|
||||||
|
'src/conf.c'
|
||||||
|
) + luafiles + subcmds
|
||||||
|
|
||||||
|
# build the executable
|
||||||
|
executable('wom', srcfiles,
|
||||||
|
dependencies: [
|
||||||
|
dependency('lua', version: '>=5.1 <6.0'),
|
||||||
|
],
|
||||||
|
include_directories: [
|
||||||
|
include_directories('include'),
|
||||||
|
|
||||||
|
include_directories('lib/log.c/src'),
|
||||||
|
include_directories('lib/ds'),
|
||||||
|
],
|
||||||
|
link_with: [
|
||||||
|
static_library('ds', 'lib/ds/ds.c',
|
||||||
|
include_directories: 'lib/ds'),
|
||||||
|
|
||||||
|
static_library('log.c', 'lib/log.c/src/log.c',
|
||||||
|
include_directories: 'lib/log.c/src'),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
install_data('completions/_wom.zsh',
|
||||||
|
install_dir: '/usr/local/share/zsh/site-functions/'
|
||||||
|
)
|
120
src/api.c
Normal file
120
src/api.c
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "ds.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include "api.h"
|
||||||
|
|
||||||
|
ds_sll_t *subcmds;
|
||||||
|
|
||||||
|
int
|
||||||
|
register_subcmd(char *name, void (*cb)(void *, int argc, char *argv[]), void *data)
|
||||||
|
{
|
||||||
|
char *c;
|
||||||
|
ds_sll_t *newnode = calloc(1, sizeof(ds_sll_t));
|
||||||
|
wom_subcmd_t *newsubcmd = calloc(1, sizeof(wom_subcmd_t));
|
||||||
|
|
||||||
|
/* make sure the subcmd name doesn't contain a space */
|
||||||
|
for (c = name; *c != '\0'; c++) {
|
||||||
|
if (isspace(*c)) {
|
||||||
|
log_fatal("subcmd '%s' can't contain any whitespace characters", name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup data */
|
||||||
|
newsubcmd->name = name;
|
||||||
|
newsubcmd->cb = cb;
|
||||||
|
newsubcmd->data = data;
|
||||||
|
newnode->data = newsubcmd;
|
||||||
|
newnode->next = NULL;
|
||||||
|
|
||||||
|
/* if this is the first node */
|
||||||
|
if (!subcmds) {
|
||||||
|
subcmds = newnode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* otherwise append the node to the end of the current nodes */
|
||||||
|
ds_ll_foreach(ds_sll_t, subcmds) {
|
||||||
|
if (!cur->next) {
|
||||||
|
cur->next = newnode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char
|
||||||
|
**list_subcmds(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char **subcmdp;
|
||||||
|
ds_sll_t *node;
|
||||||
|
wom_subcmd_t *subcmd;
|
||||||
|
|
||||||
|
/* get the number of elements in the linked list */
|
||||||
|
/* TEST: for some reason we need to allocate an extra space in the array or
|
||||||
|
* else */
|
||||||
|
for (i = 1, node = subcmds; node; node = node->next, i++)
|
||||||
|
;
|
||||||
|
|
||||||
|
subcmdp = calloc(i, sizeof(char *));
|
||||||
|
|
||||||
|
for (i = 0, node = subcmds; node; node = node->next, i++) {
|
||||||
|
subcmd = node->data;
|
||||||
|
if (subcmd->name) {
|
||||||
|
subcmdp[i] = subcmd->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return subcmdp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run_subcmds(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
char **args;
|
||||||
|
wom_subcmd_t *subcmd;
|
||||||
|
|
||||||
|
/* check for subcommands to run */
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
ds_ll_foreach(ds_sll_t, subcmds) {
|
||||||
|
subcmd = cur->data;
|
||||||
|
if (strcmp(argv[i], subcmd->name) == 0) {
|
||||||
|
goto args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
args:
|
||||||
|
args = calloc(argc - i, sizeof(char *));
|
||||||
|
for (j = 0; i < argc; i++, j++) {
|
||||||
|
args[j] = argv[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
subcmd->cb(subcmd->data, j, args);
|
||||||
|
free(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cleanup_subcmds(void)
|
||||||
|
{
|
||||||
|
ds_sll_t *prevnode, *node;
|
||||||
|
|
||||||
|
for (node = subcmds; node;) {
|
||||||
|
free(node->data);
|
||||||
|
prevnode = node;
|
||||||
|
node = node->next;
|
||||||
|
free(prevnode);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(node);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
54
src/conf.c
Normal file
54
src/conf.c
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
|
||||||
|
char *_conf_state_path = NULL;
|
||||||
|
|
||||||
|
char
|
||||||
|
*conf_config_path(void)
|
||||||
|
{
|
||||||
|
char *path, *config_path;
|
||||||
|
|
||||||
|
config_path = NULL;
|
||||||
|
|
||||||
|
if ((path = getenv("XDG_CONFIG_HOME"))) {
|
||||||
|
config_path = calloc(
|
||||||
|
strlen(path) + strlen("/wom/init.lua") + 1,
|
||||||
|
sizeof(char)
|
||||||
|
);
|
||||||
|
config_path = strcat(path, "/wom/init.lua");
|
||||||
|
} else if ((path = getenv("HOME"))) {
|
||||||
|
config_path = calloc(
|
||||||
|
strlen(path) + strlen("/.config/wom/init.lua") + 1,
|
||||||
|
sizeof(char)
|
||||||
|
);
|
||||||
|
config_path = strcat(path, "/.config/wom/init.lua");
|
||||||
|
}
|
||||||
|
|
||||||
|
return config_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
char
|
||||||
|
*conf_state_path(void)
|
||||||
|
{
|
||||||
|
char *path, *state_path;
|
||||||
|
|
||||||
|
if (_conf_state_path) {
|
||||||
|
return _conf_state_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_path = NULL;
|
||||||
|
|
||||||
|
if ((path = getenv("XDG_DATA_HOME"))) {
|
||||||
|
state_path = calloc(strlen(path), sizeof(char));
|
||||||
|
state_path = strcat(path, "/wom/");
|
||||||
|
} else if ((path = getenv("HOME"))) {
|
||||||
|
state_path = calloc(strlen(path), sizeof(char));
|
||||||
|
state_path = strcat(path, "/.local/share/wom/");
|
||||||
|
}
|
||||||
|
|
||||||
|
_conf_state_path = state_path;
|
||||||
|
|
||||||
|
return _conf_state_path;
|
||||||
|
}
|
87
src/lua/wom.c
Normal file
87
src/lua/wom.c
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#include <lauxlib.h>
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "lua/wom.h"
|
||||||
|
#include "api.h"
|
||||||
|
|
||||||
|
struct luaL_Reg *womlib = (luaL_Reg[]){
|
||||||
|
{ .name = "register_subcmd", .func = wom_register_subcmd },
|
||||||
|
{ .name = "list_subcmds", .func = wom_list_subcmds },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static lua_State *l;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief wrap a lua function in C
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
wrapper_func(void *data, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
lua_rawgeti(l, LUA_REGISTRYINDEX, *(int *)data);
|
||||||
|
lua_pushvalue(l, 1);
|
||||||
|
|
||||||
|
/* populate lua table with argv */
|
||||||
|
lua_createtable(l, 0, argc);
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
lua_pushstring(l, argv[i]);
|
||||||
|
lua_rawseti(l, -2, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_call(l, 1, 0);
|
||||||
|
l = NULL;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wom_register_subcmd(lua_State *L)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
int ret, *cb = calloc(1, sizeof(int));
|
||||||
|
|
||||||
|
luaL_checktype(L, 1, LUA_TSTRING);
|
||||||
|
name = (char *)luaL_checkstring(L, 1);
|
||||||
|
|
||||||
|
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||||
|
|
||||||
|
/* store the function */
|
||||||
|
*cb = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
l = L;
|
||||||
|
|
||||||
|
ret = register_subcmd(name, wrapper_func, cb);
|
||||||
|
if (ret != 0) {
|
||||||
|
lua_error(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushinteger(L, ret);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wom_list_subcmds(lua_State *L)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char **p = list_subcmds();
|
||||||
|
|
||||||
|
/* get the number of elements in the array */
|
||||||
|
for (i = 0; p[i]; i++)
|
||||||
|
;
|
||||||
|
|
||||||
|
lua_createtable(L, i, 0);
|
||||||
|
|
||||||
|
/* fill up the lua table from the c array */
|
||||||
|
for (i = 0; p[i]; i++) {
|
||||||
|
lua_pushstring(L, p[i]);
|
||||||
|
lua_rawseti(L, -2, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
96
src/lua/wom_fs.c
Normal file
96
src/lua/wom_fs.c
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include <lauxlib.h>
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "lua/wom_fs.h"
|
||||||
|
|
||||||
|
struct luaL_Reg *womfslib = (luaL_Reg[]){
|
||||||
|
{ .name = "dir", .func = wom_fs_dir },
|
||||||
|
{ .name = "type", .func = wom_fs_type },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
dir_gc(lua_State *L)
|
||||||
|
{
|
||||||
|
DIR *d = *(DIR **)lua_touserdata(L, 1);
|
||||||
|
|
||||||
|
if (d) {
|
||||||
|
closedir(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
dir_iter(lua_State *L)
|
||||||
|
{
|
||||||
|
DIR *d = *(DIR **)lua_touserdata(L, lua_upvalueindex(1));
|
||||||
|
struct dirent *entry;
|
||||||
|
|
||||||
|
if ((entry = readdir(d)) != NULL) {
|
||||||
|
lua_pushstring(L, entry->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* no more values to return */
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wom_fs_dir(lua_State *L)
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
DIR **d;
|
||||||
|
|
||||||
|
path = luaL_checkstring(L, 1);
|
||||||
|
|
||||||
|
/* create directory pointer in the user data */
|
||||||
|
d = lua_newuserdata(L, sizeof(DIR *));
|
||||||
|
|
||||||
|
/* set its metatable */
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushcfunction(L, dir_gc);
|
||||||
|
lua_setfield(L, -2, "__gc");
|
||||||
|
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
|
||||||
|
/* try to open the specified directory */
|
||||||
|
if ((*d = opendir(path)) == NULL) {
|
||||||
|
luaL_error(L, "cannot open %s: %s", path, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* creates and returns the iterator function with the data *DIR attached */
|
||||||
|
lua_pushcclosure(L, dir_iter, 1);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wom_fs_type(lua_State *L)
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
struct stat s;
|
||||||
|
|
||||||
|
path = luaL_checkstring(L, 1);
|
||||||
|
|
||||||
|
if (stat(path, &s) != 0) {
|
||||||
|
luaL_error(L, "cannot open '%s': %s", path, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (s.st_mode & 0170000) {
|
||||||
|
case __S_IFDIR: lua_pushstring(L, "directory"); break;
|
||||||
|
case __S_IFCHR: lua_pushstring(L, "chardevice"); break;
|
||||||
|
case __S_IFBLK: lua_pushstring(L, "blockdevice"); break;
|
||||||
|
case __S_IFREG: lua_pushstring(L, "file"); break;
|
||||||
|
case __S_IFIFO: lua_pushstring(L, "fifo"); break;
|
||||||
|
case __S_IFLNK: lua_pushstring(L, "symlink"); break;
|
||||||
|
case __S_IFSOCK: lua_pushstring(L, "socket"); break;
|
||||||
|
default: luaL_error(L, "not able to determine type of %s", path); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
95
src/main.c
Normal file
95
src/main.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include <lauxlib.h>
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
#include "lua/wom.h"
|
||||||
|
#include "lua/wom_fs.h"
|
||||||
|
#include "subcmds.h"
|
||||||
|
#include "api.h"
|
||||||
|
|
||||||
|
static lua_State
|
||||||
|
*load_wom_lua_lib(lua_State *L)
|
||||||
|
{
|
||||||
|
/* open up default libraries */
|
||||||
|
luaL_openlibs(L);
|
||||||
|
|
||||||
|
/* load in the wom library */
|
||||||
|
lua_newtable(L);
|
||||||
|
|
||||||
|
/* load in version info */
|
||||||
|
lua_pushstring(L, "version");
|
||||||
|
lua_pushstring(L, VERSION);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
/* load in the filesystem library */
|
||||||
|
lua_pushstring(L, "fs");
|
||||||
|
lua_createtable(L, 0, 0);
|
||||||
|
luaL_setfuncs(L, womfslib, 0);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
/* load in all the clua functions */
|
||||||
|
luaL_setfuncs(L, womlib, 0);
|
||||||
|
lua_setglobal(L, "wom");
|
||||||
|
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int c, l;
|
||||||
|
/* FIXME: config path can't be freed after being passed to lualib which causes
|
||||||
|
* a minor memory leak */
|
||||||
|
char *config_path = { 0 };
|
||||||
|
lua_State *L;
|
||||||
|
|
||||||
|
/* general options for womblic */
|
||||||
|
while ((c = getopt(argc, argv, "hvc:")) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 'c':
|
||||||
|
l = strlen(optarg);
|
||||||
|
config_path = calloc(l + 1, sizeof(char));
|
||||||
|
strncpy(config_path, optarg, l);
|
||||||
|
break;
|
||||||
|
case 'v': printf("%s-%s\n", argv[0], VERSION); break;
|
||||||
|
case 'h':
|
||||||
|
default:
|
||||||
|
printf("help text\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup for subcommands */
|
||||||
|
register_subcmd("motd", motd_subcmd, NULL);
|
||||||
|
register_subcmd("timer", timer_subcmd, NULL);
|
||||||
|
register_subcmd("subcmds", subcmds_subcmd, NULL);
|
||||||
|
register_subcmd("dev", subcmds_dev, NULL);
|
||||||
|
|
||||||
|
/* if the user didn't specify a config path */
|
||||||
|
if (!config_path) {
|
||||||
|
config_path = conf_config_path();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load lua library */
|
||||||
|
L = luaL_newstate();
|
||||||
|
L = load_wom_lua_lib(L);
|
||||||
|
|
||||||
|
/* run lua code */
|
||||||
|
if (luaL_loadfile(L, config_path) || lua_pcall(L, 0, 0, 0)) {
|
||||||
|
lua_error(L);
|
||||||
|
} else {
|
||||||
|
lua_pop(L, lua_gettop(L));
|
||||||
|
}
|
||||||
|
|
||||||
|
run_subcmds(argc, argv);
|
||||||
|
|
||||||
|
lua_close(L);
|
||||||
|
cleanup_subcmds();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
98
src/subcmds/clock.c
Normal file
98
src/subcmds/clock.c
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "subcmds.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief convert a sting to a time in seconds ie:
|
||||||
|
* 12s -> 12 seconds
|
||||||
|
*
|
||||||
|
* 12m -> 720 seconds
|
||||||
|
*
|
||||||
|
* 12h -> 43,200 seconds
|
||||||
|
*
|
||||||
|
* 12d -> 1,036,800 seconds
|
||||||
|
*
|
||||||
|
* @param str input time
|
||||||
|
* @return time in seconds
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
string2time(char *str)
|
||||||
|
{
|
||||||
|
char *d;
|
||||||
|
int i;
|
||||||
|
double time;
|
||||||
|
|
||||||
|
/* find the length of the string */
|
||||||
|
for (i = 0; str[i] != '\0'; i++)
|
||||||
|
;
|
||||||
|
|
||||||
|
/* if there is a trailing character make sure to remove it */
|
||||||
|
if (str[i] < '0' || str[i] > '9') {
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate space for numerical string */
|
||||||
|
d = (char *)calloc(i, sizeof(char));
|
||||||
|
strncpy(d, str, i);
|
||||||
|
|
||||||
|
/* atoi the numerical string into an int */
|
||||||
|
time = atof(d);
|
||||||
|
free(d);
|
||||||
|
|
||||||
|
/* modify the time using the last trailing character */
|
||||||
|
switch (str[i]) {
|
||||||
|
case 's': break;
|
||||||
|
case 'm': time *= 60; break;
|
||||||
|
case 'h': time *= 60 * 60; break;
|
||||||
|
case 'd': time *= 60 * 60 * 24; break;
|
||||||
|
default: return -1; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
timer_subcmd(void *, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int i, l, sum;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
for (i = 1, sum = 0, l = 0; i < argc; i++) {
|
||||||
|
sum += string2time(argv[i]);
|
||||||
|
l += strlen(argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate and populate a string with the length of the timer */
|
||||||
|
s = (char *)calloc(l + i - 1, sizeof(char));
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
/* TODO: reorder based on magnitude */
|
||||||
|
s = strcat(s, argv[i]);
|
||||||
|
if (i != argc - 1) {
|
||||||
|
s = strcat(s, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sum <= 0) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print out the number of time */
|
||||||
|
printf("Waiting for %s...\n", s);
|
||||||
|
|
||||||
|
/* TODO: instead of sleeping implement polling that way if need be we can have
|
||||||
|
* a countdown */
|
||||||
|
sleep(sum);
|
||||||
|
|
||||||
|
puts("returned");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stopwatch_subcmd(void *, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
}
|
105
src/subcmds/dev.c
Normal file
105
src/subcmds/dev.c
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
#include "subcmds.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
add(char *path)
|
||||||
|
{
|
||||||
|
char *wpath, *l;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
wpath = calloc(strlen(conf_state_path()) + 4, sizeof(char));
|
||||||
|
strcpy(wpath, conf_state_path());
|
||||||
|
strcat(wpath, "dev");
|
||||||
|
|
||||||
|
/* ensure that the file exists */
|
||||||
|
if (access(wpath, F_OK) != 0) {
|
||||||
|
fclose(fopen(wpath, "w"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if it already exists */
|
||||||
|
f = fopen(wpath, "r");
|
||||||
|
l = calloc(PATH_MAX, sizeof(char));
|
||||||
|
while (fgets(l, PATH_MAX, f)) {
|
||||||
|
l[strlen(l) - 1] = '\0';
|
||||||
|
if (strcmp(l, path) == 0) {
|
||||||
|
printf("'%s' is already in the list of projects\n", path);
|
||||||
|
free(l);
|
||||||
|
free(wpath);
|
||||||
|
fclose(f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bzero(l, PATH_MAX);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
/* add the project to the list */
|
||||||
|
f = fopen(wpath, "a");
|
||||||
|
if (fprintf(f, "%s\n", path) < 0) {
|
||||||
|
printf("failed to add new project to dev list\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
free(wpath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
subcmds_dev(void *, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char cwd[PATH_MAX];
|
||||||
|
char *wpath, *editor;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
if (strcmp(argv[1], "add") == 0) {
|
||||||
|
if (argc > 2) {
|
||||||
|
/* if the directory doesn't exist, then make it */
|
||||||
|
if (!opendir(conf_state_path())) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
if (mkdir(conf_state_path(), 0755) < 0) {
|
||||||
|
printf("Failed to create state path: %s\n", conf_state_path());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the directory to the path */
|
||||||
|
add(argv[2]);
|
||||||
|
} else {
|
||||||
|
if (getcwd(cwd, PATH_MAX) == NULL) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the directory to the path */
|
||||||
|
add(cwd);
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[1], "edit") == 0) {
|
||||||
|
wpath = calloc(strlen(conf_state_path()) + 4, sizeof(char));
|
||||||
|
strcpy(wpath, conf_state_path());
|
||||||
|
strcat(wpath, "dev");
|
||||||
|
|
||||||
|
editor = getenv("EDITOR");
|
||||||
|
if (editor) {
|
||||||
|
execvp(editor, (char *[]){ editor, wpath, NULL });
|
||||||
|
goto free_stuff;
|
||||||
|
}
|
||||||
|
printf("Failed to open editor\n");
|
||||||
|
free_stuff:
|
||||||
|
free(editor);
|
||||||
|
free(wpath);
|
||||||
|
} else if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "h") == 0) {
|
||||||
|
printf("Help text\n");
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
112
src/subcmds/motd.c
Normal file
112
src/subcmds/motd.c
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#include <dirent.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "subcmds.h"
|
||||||
|
|
||||||
|
static const char *months[12] = {
|
||||||
|
"January", "Febuary", "March", "April", "May", "June", "July", "August",
|
||||||
|
"September", "October", "November", "December"
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
num_mail(char *path)
|
||||||
|
{
|
||||||
|
long newmail = 0;
|
||||||
|
int len;
|
||||||
|
DIR *d, *sd, *ssd;
|
||||||
|
struct dirent *dir;
|
||||||
|
char *spath, *sspath;
|
||||||
|
|
||||||
|
d = opendir(path);
|
||||||
|
if (d == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while ((dir = readdir(d)) != NULL) {
|
||||||
|
if ((dir->d_type != DT_DIR && dir->d_type != DT_LNK) || dir->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* allocate space for path and populate it */
|
||||||
|
len = strlen(path) + strlen(dir->d_name) + 3;
|
||||||
|
spath = (char *)malloc(sizeof(char) * len);
|
||||||
|
if (snprintf(spath, len, "%s/%s", path, dir->d_name) < 0)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
sd = opendir(spath);
|
||||||
|
if (sd == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* find all inboxes, and new mail within */
|
||||||
|
while ((dir = readdir(sd)) != NULL) {
|
||||||
|
if (((dir->d_type != DT_DIR && dir->d_type != DT_LNK) || dir->d_name[0] == '.')
|
||||||
|
|| !strcasestr(dir->d_name, "inbox"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
len = strlen(spath) + strlen(dir->d_name) + 6;
|
||||||
|
sspath = (char *)malloc(sizeof(char) * len);
|
||||||
|
if (snprintf(sspath, len, "%s/%s/new", spath, dir->d_name) < 0)
|
||||||
|
return -3;
|
||||||
|
|
||||||
|
ssd = opendir(sspath);
|
||||||
|
free(sspath);
|
||||||
|
if (ssd == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* count all the new mail */
|
||||||
|
while ((dir = readdir(ssd)) != NULL)
|
||||||
|
if (dir->d_name[0] != '.')
|
||||||
|
newmail++;
|
||||||
|
|
||||||
|
closedir(ssd);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(spath);
|
||||||
|
free(dir);
|
||||||
|
closedir(d);
|
||||||
|
|
||||||
|
return newmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
motd_subcmd(void *, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
time_t t = time(NULL);
|
||||||
|
struct tm tm = *localtime(&t);
|
||||||
|
char *daysuffix;
|
||||||
|
int newmail;
|
||||||
|
|
||||||
|
/* allocate space for day string */
|
||||||
|
daysuffix = (char *)malloc(sizeof(char) * 3);
|
||||||
|
|
||||||
|
/* day of month */
|
||||||
|
if (tm.tm_mday > 3 && tm.tm_mday < 21)
|
||||||
|
snprintf(daysuffix, 3, "th");
|
||||||
|
else if ((tm.tm_mday / 1) % 10 == 1)
|
||||||
|
snprintf(daysuffix, 3, "st");
|
||||||
|
else if ((tm.tm_mday / 1) % 10 == 2)
|
||||||
|
snprintf(daysuffix, 3, "nd");
|
||||||
|
else if ((tm.tm_mday / 1) % 10 == 3)
|
||||||
|
snprintf(daysuffix, 3, "rd");
|
||||||
|
else
|
||||||
|
snprintf(daysuffix, 3, "th");
|
||||||
|
|
||||||
|
/* format and return */
|
||||||
|
printf("Today is \033[0;35m%s\033[m \033[0;36m%d%s\033[m, \033[0;33m%d\033[0m.\n",
|
||||||
|
months[tm.tm_mon], tm.tm_mday, daysuffix, tm.tm_year + 1900);
|
||||||
|
|
||||||
|
if ((newmail = num_mail(strcat(getenv("XDG_DATA_HOME"), "/mail"))) > 0) {
|
||||||
|
printf("You've got \033[0;36m%d\033[m unread \033[0;35memail%s\033[0m!\n",
|
||||||
|
newmail, newmail > 1 ? "s" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(daysuffix);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
9
src/subcmds/project.c
Normal file
9
src/subcmds/project.c
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include "subcmds.h"
|
||||||
|
|
||||||
|
/* TODO: figure out how to properly store all the licenses in a nice and
|
||||||
|
* parseable way */
|
||||||
|
|
||||||
|
static void
|
||||||
|
license_subcmd(void *, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
}
|
16
src/subcmds/subcmds.c
Normal file
16
src/subcmds/subcmds.c
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "api.h"
|
||||||
|
#include "subcmds.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
subcmds_subcmd(void *, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char **p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
p = list_subcmds();
|
||||||
|
for (i = 0; p[i]; i++) {
|
||||||
|
puts(p[i]);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user