tim.c (4213B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <ctype.h> 3 #include <limits.h> 4 #include <pwd.h> 5 #include <stdarg.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <unistd.h> 10 11 #include "arg.h" 12 #include "str.h" 13 #include "tim-lua.h" 14 #include "util.h" 15 16 /* macros */ 17 #define MAX_CMD 2048 18 19 /* typedefs */ 20 21 /* functions */ 22 char *get_tim_ans(char *s); 23 24 char *fmt_cmd(char *s); 25 void run_cmd(void); 26 void print_out(void); 27 28 void setup(void); 29 void cleanup(void); 30 void usage(void); 31 32 /* variables */ 33 char *argv0; 34 35 char *in; 36 char *cmd; 37 char *out; 38 int fmtout = 1; 39 40 #include "config.h" 41 42 /* returns the path to fname based on: 43 * 1) $XDG_CONFIG_HOME/tim/ (~/.config/tim/) 44 * 3) /etc/tim/ (system wide config) 45 * 2) /usr/local/share/tim/ (default when installed) 46 * 4) ./ (current directory) 47 */ 48 char * 49 get_path(const char *fname) 50 { 51 if (!fname) return NULL; 52 int i; 53 static char ret[PATH_MAX]; 54 const char *paths[] = { "/etc/tim/", "/usr/local/share/tim/", "./" }; 55 const char *home = getenv("HOME"); 56 const char *xdg_config = getenv("XDG_CONFIG_HOME"); 57 struct passwd *pw; 58 59 #ifdef DEBUG 60 /* if DEBUG is set check current directory first */ 61 strcpy(ret, "./"); 62 strcat(ret, fname); 63 if (access(ret, F_OK) != -1) 64 return ret; 65 #endif 66 67 /* try to get users home directory */ 68 if (!home || !*home) 69 if ((pw = getpwuid(getuid()))) 70 home = pw->pw_dir; 71 72 /* get XDG_CONFIG_HOME path */ 73 if (xdg_config) 74 snprintf(ret, sizeof(ret), "%s/tim/%s", xdg_config, fname); 75 else if (home && *home) 76 snprintf(ret, sizeof(ret), "%s/.config/tim/%s", home, fname); 77 78 /* try rest of paths in paths[] */ 79 for (i = 0; access(ret, F_OK) == -1; i++) { 80 if (i >= LEN(paths)) die("%s: file '%s' not found", argv0, fname); 81 strcpy(ret, paths[i]); 82 strcat(ret, fname); 83 } 84 85 return ret; 86 } 87 88 char * 89 get_tim_ans(char *s) 90 { 91 if (!s) return NULL; 92 char *ans = NULL; 93 int c, i = 2; 94 char **cmds; 95 char *fname = NULL; 96 char args[MAX_CMD]; 97 98 s = str_replace(s, "to", ""); 99 char *tmp = str_rmspaces(s); 100 cmds = str_split(tmp, ' ', &c); 101 102 if (c > 2) { 103 if (strcmp(cmds[1], "my") == 0) 104 fname = get_path(memfile); 105 else if (strcmp(cmds[1], "your") == 0) 106 fname = get_path(cogfile); 107 else { 108 fname = get_path(cogfile); 109 i--; 110 } 111 } 112 113 if (strcmp(cmds[0], "get") == 0 && c > 2) { 114 snprintf(args, sizeof(args), "%s %s", fname, cmds[i]); 115 ans = tim_lua_run(get_path("plugins/json-get.lua"), args); 116 } else if (strcmp(cmds[0], "set") == 0 && c > 3) { 117 snprintf(args, sizeof(args), "%s %s %s", fname, cmds[i], cmds[i+1]); 118 ans = tim_lua_run(get_path("plugins/json-set.lua"), args); 119 } 120 121 free(s); 122 free(tmp); 123 for (int j = 0; j < c; j++) 124 free(cmds[j]); 125 free(cmds); 126 127 return ans; 128 } 129 130 char * 131 fmt_cmd(char *s) 132 { 133 int i; 134 for (i = 0; s[i]; i++) 135 s[i] = tolower(s[i]); /* TODO not for proper nouns */ 136 return s; 137 } 138 139 /* generate tim's response */ 140 void 141 run_cmd(void) 142 { 143 char args[MAX_CMD]; 144 cmd = fmt_cmd(in); 145 snprintf(args, sizeof(args), "%s %s", get_path(actfile), cmd); 146 out = tim_lua_run(get_path("plugins/json-get.lua"), args); 147 if (STREMPTY(out)) 148 out = get_tim_ans(cmd); 149 if (STREMPTY(out)) 150 out = tim_lua_run(get_path("plugins/weather.lua"), cmd); 151 if (STREMPTY(out)) 152 out = tim_lua_run(get_path("plugins/rand.lua"), cmd); 153 if (STREMPTY(out)) { 154 out = tim_lua_run(get_path("plugins/ddg.lua"), in); 155 fmtout = 0; 156 } 157 if (STREMPTY(out)) 158 out = estrdup("Sorry I didn't get that"); 159 } 160 161 /* print tim's respond */ 162 void 163 print_out(void) 164 { 165 if (!out) return; 166 printf("%s\n", out); 167 out = NULL; 168 } 169 170 /* allocate strs */ 171 void 172 setup(void) 173 { 174 in = ecalloc(MAX_CMD, sizeof(char)); 175 out = ecalloc(MAX_CMD, sizeof(char)); 176 } 177 178 /* free memory */ 179 void 180 cleanup(void) 181 { 182 free(in); 183 free(out); 184 } 185 186 void 187 usage(void) 188 { 189 die("usage: %s [-iv] [CMD]", argv0); 190 } 191 192 int 193 main(int argc, char *argv[]) 194 { 195 ARGBEGIN { 196 case 'i': 197 interactive = 1; 198 break; 199 case 'v': 200 printf("%s v%s (c) 2017 Ed van Bruggen\n", argv0, VERSION); 201 return 0; 202 default: 203 usage(); 204 } ARGEND; 205 206 setup(); 207 208 do { 209 if (argc > 0) { 210 in = str_concat(argv, argc); 211 argc = 0; 212 } else 213 fgets(in, MAX_CMD, stdin); 214 str_trim(in); 215 run_cmd(); 216 print_out(); 217 } while (interactive && !feof(stdin)); 218 219 cleanup(); 220 221 return 0; 222 }