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