added --debug
[ptask.git] / src / tw.c
1 /*
2  * Copyright (C) 2012-2013 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/stat.h>
24
25 #include <json/json.h>
26
27 #include <log.h>
28 #include "note.h"
29 #include "tw.h"
30
31 static int has_taskrc()
32 {
33         char *home, *path;
34         int ret;
35         struct stat st;
36
37         home = getenv("HOME");
38
39         if (!home) {
40                 log_err("HOME environment variable not defined");
41                 return 0;
42         }
43
44         path = malloc(strlen(home) + 1 + strlen(".taskrc") + 1);
45         sprintf(path, "%s/%s", home, ".taskrc");
46
47         ret = lstat(path, &st);
48
49         free(path);
50
51         return ret == 0;
52
53 }
54
55 static char *task_exec(char *opts)
56 {
57         FILE *f;
58         int ret;
59         size_t s;
60         char *str, *tmp, *cmd, buf[1024];
61
62         if (!has_taskrc())
63                 return NULL;
64
65         cmd = malloc(strlen("task rc.json.array=on ") + strlen(opts) + 1);
66         strcpy(cmd, "task rc.json.array=on ");
67         strcat(cmd, opts);
68
69         log_debug("execute: %s", cmd);
70
71         f = popen(cmd, "r");
72
73         if (!f) {
74                 perror("popen");
75                 str = NULL;
76                 goto exit_free;
77         }
78
79         str = strdup("");
80         while ((s = fread(buf, 1, 1024, f))) {
81                 tmp = malloc(strlen(str) + s + (size_t)1);
82                 memcpy(tmp, str, strlen(str));
83                 memcpy(tmp + strlen(str), buf, s);
84                 tmp[strlen(str) + s] = '\0';
85                 free(str);
86                 str = tmp;
87         }
88
89         ret = pclose(f);
90
91         if (ret == -1)
92                 log_err("pclose fails");
93
94  exit_free:
95         free(cmd);
96
97         return str;
98 }
99
100 static struct json_object *task_exec_json(char *opts)
101 {
102         struct json_object *o;
103         char *str;
104
105         str = task_exec(opts);
106
107         if (str) {
108                 o = json_tokener_parse(str);
109                 free(str);
110                 return o;
111         }
112
113         return NULL;
114 }
115
116 struct task **tw_get_all_tasks(const char *status)
117 {
118         int i, n;
119         struct json_object *jtasks, *jtask, *json;
120         struct task **tasks;
121         char *opts;
122
123         opts = malloc(strlen("export status:") + strlen(status) + 1);
124         sprintf(opts, "export status:%s", status);
125
126         jtasks = task_exec_json(opts);
127         free(opts);
128
129         if (!jtasks)
130                 return NULL;
131
132         n = json_object_array_length(jtasks);
133
134         tasks = malloc((n + 1) * sizeof(struct task *));
135
136         for (i = 0; i < n; i++) {
137                 jtask = json_object_array_get_idx(jtasks, i);
138
139                 tasks[i] = malloc(sizeof(struct task));
140
141                 json = json_object_object_get(jtask, "id");
142                 tasks[i]->id = json_object_get_int(json);
143
144                 json = json_object_object_get(jtask, "description");
145                 tasks[i]->description = strdup(json_object_get_string(json));
146
147                 json = json_object_object_get(jtask, "status");
148                 tasks[i]->status = strdup(json_object_get_string(json));
149
150                 json = json_object_object_get(jtask, "project");
151                 if (json)
152                         tasks[i]->project
153                                 = strdup(json_object_get_string(json));
154                 else
155                         tasks[i]->project = NULL;
156
157                 json = json_object_object_get(jtask, "priority");
158                 if (json)
159                         tasks[i]->priority
160                                 = strdup(json_object_get_string(json));
161                 else
162                         tasks[i]->priority = strdup("");
163
164                 json = json_object_object_get(jtask, "uuid");
165                 tasks[i]->uuid = strdup(json_object_get_string(json));
166
167                 tasks[i]->note = note_get(tasks[i]->uuid);
168         }
169
170         tasks[n] = NULL;
171
172         json_object_put(jtasks);
173
174         return tasks;
175 }
176
177 static char *escape(const char *txt)
178 {
179         char *result;
180         char *c;
181
182         result = malloc(2*strlen(txt)+1);
183         c = result;
184
185         while (*txt) {
186                 switch (*txt) {
187                 case '"':
188                         *c = '\\'; c++;
189                         *c = '"';
190                         break;
191                 case '$':
192                         *c = '\\'; c++;
193                         *c = '$';
194                         break;
195                 case '&':
196                         *c = '\\'; c++;
197                         *c = '&';
198                         break;
199                 default:
200                         *c = *txt;
201                 }
202                 c++;
203                 txt++;
204         }
205
206         *c = '\0';
207
208         return result;
209 }
210
211 void tw_modify_description(const char *uuid, const char *newdesc)
212 {
213         char *str;
214         char *opts;
215
216         str = escape(newdesc);
217
218         opts = malloc(1
219                       + strlen(uuid)
220                       + strlen(" modify :\"")
221                       + strlen(str)
222                       + strlen("\"")
223                       + 1);
224         sprintf(opts, " %s modify \"%s\"", uuid, str);
225
226         task_exec(opts);
227
228         free(str);
229         free(opts);
230 }
231
232 void tw_modify_project(const char *uuid, const char *newproject)
233 {
234         char *str;
235         char *opts;
236
237         str = escape(newproject);
238
239         opts = malloc(1
240                       + strlen(uuid)
241                       + strlen(" modify project:\"")
242                       + strlen(str)
243                       + strlen("\"")
244                       + 1);
245         sprintf(opts, " %s modify project:\"%s\"", uuid, str);
246
247         task_exec(opts);
248
249         free(str);
250         free(opts);
251 }
252
253 void tw_modify_priority(const char *uuid, const char *priority)
254 {
255         char *str;
256         char *opts;
257
258         str = escape(priority);
259
260         opts = malloc(1
261                       + strlen(uuid)
262                       + strlen(" modify priority:\"")
263                       + strlen(str)
264                       + strlen("\"")
265                       + 1);
266         sprintf(opts, " %s modify priority:\"%s\"", uuid, str);
267
268         task_exec(opts);
269
270         free(str);
271         free(opts);
272 }
273
274 void tw_add(const char *newdesc)
275 {
276         char *str;
277         char *opts;
278
279         str = escape(newdesc);
280
281         opts = malloc(1
282                       + strlen(" add \"")
283                       + strlen(str)
284                       + strlen("\"")
285                       + 1);
286         sprintf(opts, " add \"%s\"", str);
287
288         task_exec(opts);
289
290         free(str);
291         free(opts);
292 }
293
294 void tw_done(const char *uuid)
295 {
296         char *opts;
297
298         opts = malloc(1
299                       + strlen(uuid)
300                       + strlen(" done")
301                       + 1);
302         sprintf(opts, " %s done", uuid);
303
304         task_exec(opts);
305
306         free(opts);
307 }
308
309 static void task_free(struct task *task)
310 {
311         if (!task)
312                 return ;
313
314         free(task->description);
315         free(task->status);
316         free(task->uuid);
317         free(task->note);
318         free(task->project);
319         free(task->priority);
320
321         free(task);
322 }
323
324 void tw_task_list_free(struct task **tasks)
325 {
326         struct task **cur;
327
328         if (!tasks)
329                 return ;
330
331         for (cur = tasks; *cur; cur++)
332                 task_free(*cur);
333
334         free(tasks);
335 }