New program
Showing
1 changed file
with
373 additions
and
0 deletions
examples/header.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2007 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils; if not, write to the Free Software | ||
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | ||
17 | MA 02110-1301 USA */ | ||
18 | |||
19 | #include <stdio.h> | ||
20 | #include <string.h> | ||
21 | #include <errno.h> | ||
22 | #include <sys/stat.h> | ||
23 | #include <mailutils/mailutils.h> | ||
24 | |||
25 | char *file; | ||
26 | mu_header_t header; | ||
27 | |||
28 | char *ps[] = { "> ", ". " }; | ||
29 | int interactive; | ||
30 | |||
31 | static void | ||
32 | prompt(int l) | ||
33 | { | ||
34 | if (interactive) | ||
35 | { | ||
36 | printf ("%s", ps[l]); | ||
37 | fflush (stdout); | ||
38 | } | ||
39 | } | ||
40 | |||
41 | static int | ||
42 | load_file (const char *name) | ||
43 | { | ||
44 | struct stat st; | ||
45 | size_t nread; | ||
46 | char *buf; | ||
47 | FILE *fp; | ||
48 | int status; | ||
49 | |||
50 | if (stat (name, &st)) | ||
51 | { | ||
52 | mu_error ("cannot stat %s: %s", name, mu_strerror (errno)); | ||
53 | return 1; | ||
54 | } | ||
55 | |||
56 | buf = malloc (st.st_size + 2); | ||
57 | if (!buf) | ||
58 | { | ||
59 | mu_error ("not enough memory"); | ||
60 | return 1; | ||
61 | } | ||
62 | |||
63 | fp = fopen (name, "r"); | ||
64 | if (!fp) | ||
65 | { | ||
66 | mu_error ("cannot open file %s: %s", name, mu_strerror (errno)); | ||
67 | free (buf); | ||
68 | return 1; | ||
69 | } | ||
70 | |||
71 | nread = fread (buf, 1, st.st_size, fp); | ||
72 | fclose (fp); | ||
73 | if (nread != st.st_size) | ||
74 | { | ||
75 | mu_error ("short read on file %s", name); | ||
76 | free (buf); | ||
77 | return 1; | ||
78 | } | ||
79 | |||
80 | buf[st.st_size] = '\n'; | ||
81 | buf[st.st_size+1] = 0; | ||
82 | status = mu_header_create (&header, buf, st.st_size + 1, NULL); | ||
83 | free (buf); | ||
84 | if (status) | ||
85 | { | ||
86 | mu_error ("cannot create header: %s", mu_strerror (status)); | ||
87 | return 1; | ||
88 | } | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | unsigned line_num = 0; | ||
93 | |||
94 | static int | ||
95 | check_args (char const *cmdname, int argc, int amin, int amax) | ||
96 | { | ||
97 | if (argc < amin) | ||
98 | { | ||
99 | mu_error ("%u: %s: too few arguments", | ||
100 | line_num, cmdname); | ||
101 | return 1; | ||
102 | } | ||
103 | if (amax > 0 && argc > amax) | ||
104 | { | ||
105 | mu_error ("%u: %s: too many arguments", | ||
106 | line_num, cmdname); | ||
107 | return 1; | ||
108 | } | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | void | ||
113 | cmd_quit (int argc, char **argv) | ||
114 | { | ||
115 | exit (0); | ||
116 | } | ||
117 | |||
118 | void | ||
119 | cmd_load (int argc, char **argv) | ||
120 | { | ||
121 | if (check_args (argv[0], argc, 2, 2)) | ||
122 | return; | ||
123 | mu_header_destroy (&header, NULL); | ||
124 | load_file (argv[1]); | ||
125 | } | ||
126 | |||
127 | void | ||
128 | cmd_free (int argc, char **argv) | ||
129 | { | ||
130 | if (check_args (argv[0], argc, 1, 1)) | ||
131 | return; | ||
132 | mu_header_destroy (&header, NULL); | ||
133 | } | ||
134 | |||
135 | void | ||
136 | cmd_print (int argc, char **argv) | ||
137 | { | ||
138 | char *fn; | ||
139 | int num = 1; | ||
140 | int status; | ||
141 | const char *str; | ||
142 | |||
143 | if (check_args (argv[0], argc, 2, 3)) | ||
144 | return; | ||
145 | fn = argv[1]; | ||
146 | if (argc == 3) | ||
147 | num = atoi (argv[2]); | ||
148 | |||
149 | status = mu_header_sget_value_n (header, fn, num, &str); | ||
150 | if (status == 0) | ||
151 | printf ("%s: %s\n", fn, str); | ||
152 | else | ||
153 | mu_error ("%u: %s", line_num, mu_strerror (status)); | ||
154 | } | ||
155 | |||
156 | void | ||
157 | cmd_dump (int argc, char **argv) | ||
158 | { | ||
159 | mu_off_t off = 0; | ||
160 | size_t n; | ||
161 | mu_stream_t stream; | ||
162 | char buf[512]; | ||
163 | int status; | ||
164 | |||
165 | if (check_args (argv[0], argc, 1, 2)) | ||
166 | return; | ||
167 | |||
168 | if (argc == 2) | ||
169 | off = strtoul (argv[1], NULL, 0); | ||
170 | |||
171 | status = mu_header_get_stream (header, &stream); | ||
172 | if (status) | ||
173 | { | ||
174 | mu_error ("%u: cannot get stream: %s", line_num, mu_strerror (status)); | ||
175 | return; | ||
176 | } | ||
177 | |||
178 | status = mu_stream_seek (stream, off, SEEK_SET); | ||
179 | if (status) | ||
180 | { | ||
181 | mu_error ("%u: cannot seek: %s", line_num, mu_strerror (status)); | ||
182 | return; | ||
183 | } | ||
184 | |||
185 | while (mu_stream_sequential_read (stream, buf, sizeof buf, &n) == 0 | ||
186 | && n > 0) | ||
187 | { | ||
188 | fwrite (buf, 1, n, stdout); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | void | ||
193 | cmd_remove (int argc, char **argv) | ||
194 | { | ||
195 | char *fn; | ||
196 | int num = 1; | ||
197 | int status; | ||
198 | |||
199 | if (check_args (argv[0], argc, 2, 3)) | ||
200 | return; | ||
201 | fn = argv[1]; | ||
202 | if (argc == 3) | ||
203 | num = atoi (argv[2]); | ||
204 | status = mu_header_remove (header, fn, num); | ||
205 | if (status) | ||
206 | mu_error ("%u: %s: %s", line_num, argv[0], mu_strerror (status)); | ||
207 | } | ||
208 | |||
209 | /* insert header value [ref [num] [before|after] [replace]] */ | ||
210 | void | ||
211 | cmd_insert (int argc, char **argv) | ||
212 | { | ||
213 | int status; | ||
214 | int flags = 0; | ||
215 | char *ref = NULL; | ||
216 | int num = 1; | ||
217 | int n; | ||
218 | |||
219 | if (check_args (argv[0], argc, 3, 7)) | ||
220 | return; | ||
221 | |||
222 | if (argc >= 4) | ||
223 | { | ||
224 | ref = argv[3]; | ||
225 | n = 4; | ||
226 | if (n < argc) | ||
227 | { | ||
228 | char *p; | ||
229 | int tmp; | ||
230 | |||
231 | tmp = strtoul(argv[4], &p, 0); | ||
232 | if (*p == 0) | ||
233 | { | ||
234 | num = tmp; | ||
235 | n++; | ||
236 | } | ||
237 | |||
238 | for (; n < argc; n++) | ||
239 | { | ||
240 | if (strcmp(argv[n], "before") == 0) | ||
241 | flags |= MU_HEADER_BEFORE; | ||
242 | else if (strcmp(argv[n], "after") == 0) | ||
243 | ; | ||
244 | else if (strcmp(argv[n], "replace") == 0) | ||
245 | flags |= MU_HEADER_REPLACE; | ||
246 | else | ||
247 | { | ||
248 | mu_error("%u: %s: unknown option", line_num, argv[4]); | ||
249 | return; | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | status = mu_header_insert (header, argv[1], argv[2], | ||
255 | ref, num, flags); | ||
256 | if (status) | ||
257 | mu_error ("%u: %s: %s", line_num, argv[0], mu_strerror (status)); | ||
258 | } | ||
259 | |||
260 | void | ||
261 | cmd_write (int argc, char **argv) | ||
262 | { | ||
263 | char buf[512]; | ||
264 | mu_stream_t str; | ||
265 | int status; | ||
266 | |||
267 | if (check_args (argv[0], argc, 1, 1)) | ||
268 | return; | ||
269 | |||
270 | status = mu_header_get_stream (header, &str); | ||
271 | if (status) | ||
272 | { | ||
273 | mu_error ("%u: cannot get stream: %s", line_num, mu_strerror (status)); | ||
274 | return; | ||
275 | } | ||
276 | mu_stream_seek (str, 0, SEEK_SET); | ||
277 | while (prompt (1), fgets(buf, sizeof buf, stdin)) | ||
278 | { | ||
279 | mu_stream_sequential_write (str, buf, strlen (buf)); | ||
280 | if (buf[0] == '\n') | ||
281 | break; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | struct cmdtab | ||
286 | { | ||
287 | char *name; | ||
288 | void (*fun) (int argc, char **argv); | ||
289 | }; | ||
290 | |||
291 | static struct cmdtab cmdtab[] = { | ||
292 | { "quit", cmd_quit }, | ||
293 | { "load", cmd_load }, | ||
294 | { "free", cmd_free }, | ||
295 | { "print", cmd_print }, | ||
296 | { "dump", cmd_dump }, | ||
297 | { "remove", cmd_remove }, | ||
298 | { "insert", cmd_insert }, | ||
299 | { "write", cmd_write }, | ||
300 | { NULL } | ||
301 | }; | ||
302 | |||
303 | static struct cmdtab * | ||
304 | find_cmd (const char *name) | ||
305 | { | ||
306 | struct cmdtab *p; | ||
307 | for (p = cmdtab; p->name; p++) | ||
308 | if (strcmp (p->name, name) == 0) | ||
309 | return p; | ||
310 | return NULL; | ||
311 | } | ||
312 | |||
313 | int | ||
314 | main (int argc, char **argv) | ||
315 | { | ||
316 | int c; | ||
317 | char buf[512]; | ||
318 | |||
319 | interactive = isatty (0); | ||
320 | while ((c = getopt (argc, argv, "f:h")) != EOF) | ||
321 | { | ||
322 | switch (c) | ||
323 | { | ||
324 | case 'f': | ||
325 | file = optarg; | ||
326 | break; | ||
327 | |||
328 | case 'h': | ||
329 | printf ("usage: header [-f file]\n"); | ||
330 | exit (0); | ||
331 | |||
332 | default: | ||
333 | exit (1); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | if (file) | ||
338 | { | ||
339 | if (load_file (file)) | ||
340 | exit (1); | ||
341 | } | ||
342 | |||
343 | while (prompt(0), fgets(buf, sizeof buf, stdin)) | ||
344 | { | ||
345 | int c; | ||
346 | char **v; | ||
347 | struct cmdtab *cmd; | ||
348 | int status; | ||
349 | |||
350 | line_num++; | ||
351 | status = mu_argcv_get (buf, NULL, "#", &c, &v); | ||
352 | if (status) | ||
353 | { | ||
354 | mu_error ("%u: cannot parse: %s", | ||
355 | line_num, mu_strerror (status)); | ||
356 | continue; | ||
357 | } | ||
358 | |||
359 | cmd = find_cmd (v[0]); | ||
360 | if (!cmd) | ||
361 | { | ||
362 | mu_error ("%u: unknown command %s", | ||
363 | line_num, v[0]); | ||
364 | } | ||
365 | else | ||
366 | cmd->fun (c, v); | ||
367 | |||
368 | mu_argcv_free (c, v); | ||
369 | |||
370 | } | ||
371 | exit (0); | ||
372 | } | ||
373 |
-
Please register or sign in to post a comment