Add support for mail notification for local maildirs
Patch status: rejected
Patch by Timo Buhrmester
To apply this patch, use:
curl http://cr.i3wm.org/patch/670/raw.patch | git am
b/i3status.c
16 |
@@ -405,6 +405,18 @@ int main(int argc, char *argv[]) { |
17 |
CFG_END() |
18 |
}; |
19 |
|
20 |
+ cfg_opt_t maildir_opts[] = { |
21 |
+ CFG_STR("format", "%num new %mail", CFGF_NONE), /* format to use when there is new mail */ |
22 |
+ CFG_STR("format_nomail", "no mail", CFGF_NONE), /* format to use when there is NO new mail */ |
23 |
+ CFG_STR("path", "Maildir", CFGF_NONE), /* Path to maildir, absolute or relative to homedir */ |
24 |
+ CFG_STR("name", "INBOX", CFGF_NONE), /* Arbitrary name (for displaying purposes only) */ |
25 |
+ CFG_INT("max", 9, CFGF_NONE), /* Max. number of new mails to count (for huge maildirs) */ |
26 |
+ CFG_CUSTOM_ALIGN_OPT, |
27 |
+ CFG_CUSTOM_COLOR_OPTS, |
28 |
+ CFG_CUSTOM_MIN_WIDTH_OPT, |
29 |
+ CFG_END() |
30 |
+ }; |
31 |
+ |
32 |
cfg_opt_t opts[] = { |
33 |
CFG_STR_LIST("order", "{}", CFGF_NONE), |
34 |
CFG_SEC("general", general_opts, CFGF_NONE), |
35 |
@@ -416,6 +428,7 @@ int main(int argc, char *argv[]) { |
36 |
CFG_SEC("cpu_temperature", temp_opts, CFGF_TITLE | CFGF_MULTI), |
37 |
CFG_SEC("disk", disk_opts, CFGF_TITLE | CFGF_MULTI), |
38 |
CFG_SEC("volume", volume_opts, CFGF_TITLE | CFGF_MULTI), |
39 |
+ CFG_SEC("maildir", maildir_opts, CFGF_TITLE | CFGF_MULTI), |
40 |
CFG_SEC("ipv6", ipv6_opts, CFGF_NONE), |
41 |
CFG_SEC("time", time_opts, CFGF_NONE), |
42 |
CFG_SEC("tztime", tztime_opts, CFGF_TITLE | CFGF_MULTI), |
43 |
@@ -644,6 +657,13 @@ int main(int argc, char *argv[]) { |
44 |
SEC_CLOSE_MAP; |
45 |
} |
46 |
|
47 |
+ CASE_SEC_TITLE("maildir") { |
48 |
+ SEC_OPEN_MAP("maildir"); |
49 |
+ print_maildir(json_gen, buffer, cfg_getstr(sec, "format"), cfg_getstr(sec, "format_nomail"), |
50 |
+ cfg_getstr(sec, "path"), cfg_getstr(sec, "name"), cfg_getint(sec, "max")); |
51 |
+ SEC_CLOSE_MAP; |
52 |
+ } |
53 |
+ |
54 |
CASE_SEC_TITLE("cpu_temperature") { |
55 |
SEC_OPEN_MAP("cpu_temperature"); |
56 |
print_cpu_temperature_info(json_gen, buffer, atoi(title), cfg_getstr(sec, "path"), cfg_getstr(sec, "format"), cfg_getint(sec, "max_threshold")); |
b/include/i3status.h
61 |
@@ -184,6 +184,7 @@ void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format); |
62 |
void print_eth_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down); |
63 |
void print_load(yajl_gen json_gen, char *buffer, const char *format, const float max_threshold); |
64 |
void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *fmt_muted, const char *device, const char *mixer, int mixer_idx); |
65 |
+void print_maildir(yajl_gen json_gen, char *buffer, const char *fmt, const char *fmt_nomail, const char *path, const char *name, int max); |
66 |
bool process_runs(const char *path); |
67 |
|
68 |
/* socket file descriptor for general purposes */ |
b/src/print_maildir.c
74 |
@@ -0,0 +1,106 @@ |
75 |
+// vim:ts=8:expandtab |
76 |
+#include <time.h> |
77 |
+#include <string.h> |
78 |
+#include <stdbool.h> |
79 |
+#include <stdlib.h> |
80 |
+#include <stdio.h> |
81 |
+#include <yajl/yajl_gen.h> |
82 |
+#include <yajl/yajl_version.h> |
83 |
+ |
84 |
+#include <fcntl.h> |
85 |
+#include <unistd.h> |
86 |
+#include <dirent.h> |
87 |
+#include <pwd.h> |
88 |
+ |
89 |
+#include "i3status.h" |
90 |
+#include "queue.h" |
91 |
+ |
92 |
+void print_maildir(yajl_gen json_gen, char *buffer, const char *fmt, const char *fmt_nomail, const char *path, const char *name, int max) { |
93 |
+ char *outwalk = buffer; |
94 |
+ |
95 |
+ if (output_format == O_I3BAR) { |
96 |
+ INSTANCE(path); |
97 |
+ } |
98 |
+ |
99 |
+ /* If `path' is relative, look up user's home dir and store in `pathpfx' */ |
100 |
+ char pathpfx[128]; |
101 |
+ if (path[0] != '/') { |
102 |
+ /* path is relative, look up user's home dir */ |
103 |
+ struct passwd *pw = getpwuid(geteuid()); |
104 |
+ if (!pw) { |
105 |
+ fprintf(stderr, "Failed to query user information for uid %d\n", geteuid()); |
106 |
+ return; |
107 |
+ } |
108 |
+ |
109 |
+ snprintf(pathpfx, sizeof pathpfx, "%s/", pw->pw_dir); |
110 |
+ } else { |
111 |
+ pathpfx[0] = '\0'; |
112 |
+ } |
113 |
+ |
114 |
+ char fullpath[512]; /* full path to <maildir>/new */ |
115 |
+ snprintf(fullpath, sizeof fullpath, "%s%s/new", pathpfx, path); |
116 |
+ |
117 |
+ DIR *d = opendir(fullpath); |
118 |
+ if (!d) { |
119 |
+ fprintf(stderr, "Failed to opendir('%s')\n", fullpath); |
120 |
+ return; |
121 |
+ } |
122 |
+ |
123 |
+ /* Count files in 'new', but don't count more than `max' */ |
124 |
+ int cnt = -2; /* start w/ -2 because of . and .. */ |
125 |
+ bool overmax = false; |
126 |
+ struct dirent *de; |
127 |
+ while ((de = readdir(d))) { |
128 |
+ if (++cnt > max && max) { |
129 |
+ /* if we have a maximum, stop listing to preserve resources */ |
130 |
+ overmax = true; |
131 |
+ break; |
132 |
+ } |
133 |
+ } |
134 |
+ |
135 |
+ closedir(d); |
136 |
+ |
137 |
+ if (!cnt) { |
138 |
+ fmt = fmt_nomail; |
139 |
+ } |
140 |
+ |
141 |
+ /* no news is good news */ |
142 |
+ START_COLOR(!cnt ? "color_good" : "color_bad"); |
143 |
+ |
144 |
+ const char *walk = fmt; |
145 |
+ for (; *walk != '\0'; walk++) { |
146 |
+ if (*walk != '%') { |
147 |
+ *(outwalk++) = *walk; |
148 |
+ continue; |
149 |
+ } |
150 |
+ |
151 |
+ if (BEGINS_WITH(walk+1, "%")) { |
152 |
+ outwalk += sprintf(outwalk, "%%"); |
153 |
+ walk += strlen("%"); |
154 |
+ } |
155 |
+ |
156 |
+ /* %num expands to the amount of new mail |
157 |
+ * However, if `max' is >0, and there are more than `max' new mails, %num expands to `max'+ instead */ |
158 |
+ if (BEGINS_WITH(walk+1, "num")) { |
159 |
+ outwalk += sprintf(outwalk, "%d%s", cnt - overmax, overmax ? "+" : ""); |
160 |
+ walk += strlen("num"); |
161 |
+ } |
162 |
+ |
163 |
+ /* %mail expands to "mail" or "mails", depending on whether we need singular or plural */ |
164 |
+ if (BEGINS_WITH(walk+1, "mail")) { |
165 |
+ outwalk += sprintf(outwalk, "mail%s", cnt == 1 ? "" : "s"); |
166 |
+ walk += strlen("mail"); |
167 |
+ } |
168 |
+ |
169 |
+ /* %name expands to the (arbitrary) name specified for this maildir in i3status.conf */ |
170 |
+ if (BEGINS_WITH(walk+1, "name")) { |
171 |
+ outwalk += sprintf(outwalk, "%s", name); |
172 |
+ walk += strlen("name"); |
173 |
+ } |
174 |
+ } |
175 |
+ |
176 |
+ *outwalk = '\0'; |
177 |
+ OUTPUT_FULL_TEXT(buffer); |
178 |
+ |
179 |
+ END_COLOR; |
180 |
+} |