Minor change in stream API. Improve POP3 client interface.
* include/mailutils/sys/stream.h (_MU_STR_EVENT_SET) (_MU_STR_EVENT_CLR): New defines. (_mu_stream) <event_cb, event_mask>: New members. * mailbox/stream.c (_stream_setflag, _stream_clrflag): New static functions. All functions use these instead of setting/clearing flags directly. (_mu_stream_cleareof, _mu_stream_seteof): New extern functions. (_stream_cleareof): Remove define, use _mu_stream_cleareof instead. (_stream_fill_buffer): Set EOF marker when end of stream is reached. * mailbox/fltstream.c (filter_read): Call _mu_stream_seteof to set EOF flag. * include/mailutils/pop3.h: Get rid of the superfluous "extern" in front of function prototypes. Add new prototypes. Remove extra whitespace. * libproto/pop/pop3_capatst.c: New file. * libproto/pop/pop3_list_cmd.c: New file. * libproto/pop/pop3_listas.c: New file. * libproto/pop/pop3_rdlist.c: New file. * libproto/pop/pop3_uidl_cmd.c: New file. * libproto/pop/pop3_uidlas.c: New file. * libproto/pop/Makefile.am: Add new files. * libproto/pop/pop3_capa.c (_mu_pop3_fill_list): Remove. Use mu_pop3_read_list instead. (capa_comp): New comparator for capa lists. * libproto/pop/pop3_list.c (mu_pop3_list): Fix format specifier. * libproto/pop/pop3_lista.c (mu_pop3_list_all): Rewrite. * libproto/pop/pop3_retr.c (mu_pop3_retr) <MU_POP3_RETR_RX>: do not reset state, this is done by the EOF event callback. * libproto/pop/pop3_top.c (mu_pop3_top) <MU_POP3_TOP_RX>: Likewise. * libproto/pop/pop3_stream.c (pop3_decode_state): New state pds_char. Change semantics of pds_init. (newstate, _pop3_decoder): Handle .\r\n in the initial state. (_pop3_event_cb): New event callback. (mu_pop3_filter_create): Set event callback on the filter stream. * libproto/pop/pop3_uidla.c (mu_pop3_uidl_all): Rewrite. * examples/Makefile.am (pop3client_CPPFLAGS): Add MU_APP_COMMON_INCLUDES. * examples/pop3client.c: Rewrite command parser.
Showing
20 changed files
with
848 additions
and
458 deletions
... | @@ -111,6 +111,7 @@ sfrom_LDADD =\ | ... | @@ -111,6 +111,7 @@ sfrom_LDADD =\ |
111 | @MU_AUTHLIBS@\ | 111 | @MU_AUTHLIBS@\ |
112 | ${MU_LIB_MAILUTILS} | 112 | ${MU_LIB_MAILUTILS} |
113 | 113 | ||
114 | pop3client_CPPFLAGS = @MU_APP_COMMON_INCLUDES@ | ||
114 | pop3client_LDADD = \ | 115 | pop3client_LDADD = \ |
115 | ../lib/libmuaux.la\ | 116 | ../lib/libmuaux.la\ |
116 | ${MU_LIB_POP}\ | 117 | ${MU_LIB_POP}\ | ... | ... |
... | @@ -34,6 +34,7 @@ | ... | @@ -34,6 +34,7 @@ |
34 | #include <stdlib.h> | 34 | #include <stdlib.h> |
35 | #include <termios.h> | 35 | #include <termios.h> |
36 | #include <signal.h> | 36 | #include <signal.h> |
37 | #include <xalloc.h> | ||
37 | 38 | ||
38 | #ifdef WITH_READLINE | 39 | #ifdef WITH_READLINE |
39 | # include <readline/readline.h> | 40 | # include <readline/readline.h> |
... | @@ -56,64 +57,81 @@ | ... | @@ -56,64 +57,81 @@ |
56 | typedef struct | 57 | typedef struct |
57 | { | 58 | { |
58 | const char *name; /* User printable name of the function. */ | 59 | const char *name; /* User printable name of the function. */ |
59 | int (*func) (char *); /* Function to call to do the job. */ | 60 | int argmin; |
61 | int argmax; | ||
62 | int (*func) (int, char **); /* Function to call to do the job. */ | ||
60 | const char *doc; /* Documentation for this function. */ | 63 | const char *doc; /* Documentation for this function. */ |
61 | } | 64 | } |
62 | COMMAND; | 65 | COMMAND; |
63 | 66 | ||
64 | /* The names of functions that actually do the manipulation. */ | 67 | /* The names of functions that actually do the manipulation. */ |
65 | int com_apop (char *); | 68 | int com_apop (int, char **); |
66 | int com_capa (char *); | 69 | int com_capa (int, char **); |
67 | int com_disconnect (char *); | 70 | int com_disconnect (int, char **); |
68 | int com_dele (char *); | 71 | int com_dele (int, char **); |
69 | int com_exit (char *); | 72 | int com_exit (int, char **); |
70 | int com_help (char *); | 73 | int com_help (int, char **); |
71 | int com_list (char *); | 74 | int com_list (int, char **); |
72 | int com_noop (char *); | 75 | int com_noop (int, char **); |
73 | int com_connect (char *); | 76 | int com_connect (int, char **); |
74 | int com_pass (char *); | 77 | int com_pass (int, char **); |
75 | int com_quit (char *); | 78 | int com_quit (int, char **); |
76 | int com_retr (char *); | 79 | int com_retr (int, char **); |
77 | int com_rset (char *); | 80 | int com_rset (int, char **); |
78 | int com_stat (char *); | 81 | int com_stat (int, char **); |
79 | int com_top (char *); | 82 | int com_top (int, char **); |
80 | int com_uidl (char *); | 83 | int com_uidl (int, char **); |
81 | int com_user (char *); | 84 | int com_user (int, char **); |
82 | int com_verbose (char *); | 85 | int com_verbose (int, char **); |
83 | int com_prompt (char *); | 86 | int com_prompt (int, char **); |
84 | int com_stls (char *); | 87 | int com_stls (int, char **); |
85 | |||
86 | void initialize_readline (void); | ||
87 | COMMAND *find_command (char *); | ||
88 | char *dupstr (const char *); | ||
89 | int execute_line (char *); | ||
90 | int valid_argument (const char *, char *); | ||
91 | 88 | ||
92 | void sig_int (int); | 89 | COMMAND *find_command (char *); |
93 | 90 | ||
94 | COMMAND commands[] = { | 91 | COMMAND commands[] = { |
95 | { "apop", com_apop, "Authenticate with APOP: APOP user secret" }, | 92 | { "apop", 3, 3, com_apop, |
96 | { "capa", com_capa, "List capabilities: capa" }, | 93 | "Authenticate with APOP: APOP user secret" }, |
97 | { "disconnect", com_disconnect, "Close connection: disconnect" }, | 94 | { "capa", 1, -1, com_capa, |
98 | { "dele", com_dele, "Mark message: DELE msgno" }, | 95 | "List capabilities: capa [-reread] [names...]" }, |
99 | { "exit", com_exit, "exit program" }, | 96 | { "disconnect", 1, 1, |
100 | { "help", com_help, "Display this text" }, | 97 | com_disconnect, "Close connection: disconnect" }, |
101 | { "?", com_help, "Synonym for `help'" }, | 98 | { "dele", 2, 2, com_dele, |
102 | { "list", com_list, "List messages: LIST [msgno]" }, | 99 | "Mark message: DELE msgno" }, |
103 | { "noop", com_noop, "Send no operation: NOOP" }, | 100 | { "exit", 1, 1, com_exit, |
104 | { "pass", com_pass, "Send passwd: PASS [passwd]" }, | 101 | "exit program" }, |
105 | { "prompt", com_prompt, "Set command prompt" }, | 102 | { "help", 1, 1, com_help, |
106 | { "connect", com_connect, "Open connection: connect hostname [port]" }, | 103 | "Display this text" }, |
107 | { "quit", com_quit, "Go to Update state : QUIT" }, | 104 | { "?", 1, 1, com_help, |
108 | { "retr", com_retr, "Dowload message: RETR msgno" }, | 105 | "Synonym for `help'" }, |
109 | { "rset", com_rset, "Unmark all messages: RSET" }, | 106 | { "list", 1, 2, com_list, |
110 | { "stat", com_stat, "Get the size and count of mailbox : STAT [msgno]" }, | 107 | "List messages: LIST [msgno]" }, |
111 | { "stls", com_stls, "Start TLS negotiation" }, | 108 | { "noop", 1, 1, com_noop, |
112 | { "top", com_top, "Get the header of message: TOP msgno [lines]" }, | 109 | "Send no operation: NOOP" }, |
113 | { "uidl", com_uidl, "Get the unique id of message: UIDL [msgno]" }, | 110 | { "pass", 1, 2, com_pass, |
114 | { "user", com_user, "send login: USER user" }, | 111 | "Send passwd: PASS [passwd]" }, |
115 | { "verbose", com_verbose, "Enable Protocol tracing: verbose [on|off]" }, | 112 | { "prompt", -1, -1, com_prompt, |
116 | { NULL, NULL, NULL } | 113 | "Set command prompt" }, |
114 | { "connect", 1, 4, com_connect, | ||
115 | "Open connection: connect [-tls] hostname port" }, | ||
116 | { "quit", 1, 1, com_quit, | ||
117 | "Go to Update state : QUIT" }, | ||
118 | { "retr", 2, 2, com_retr, | ||
119 | "Dowload message: RETR msgno" }, | ||
120 | { "rset", 1, 1, com_rset, | ||
121 | "Unmark all messages: RSET" }, | ||
122 | { "stat", 1, 1, com_stat, | ||
123 | "Get the size and count of mailbox : STAT" }, | ||
124 | { "stls", 1, 1, com_stls, | ||
125 | "Start TLS negotiation" }, | ||
126 | { "top", 2, 3, com_top, | ||
127 | "Get the header of message: TOP msgno [lines]" }, | ||
128 | { "uidl", 1, 2, com_uidl, | ||
129 | "Get the unique id of message: UIDL [msgno]" }, | ||
130 | { "user", 2, 2, com_user, | ||
131 | "send login: USER user" }, | ||
132 | { "verbose", 1, 2, com_verbose, | ||
133 | "Enable Protocol tracing: verbose [on|off]" }, | ||
134 | { NULL } | ||
117 | }; | 135 | }; |
118 | 136 | ||
119 | /* Global handle for pop3. */ | 137 | /* Global handle for pop3. */ |
... | @@ -189,20 +207,6 @@ expand_prompt () | ... | @@ -189,20 +207,6 @@ expand_prompt () |
189 | return str; | 207 | return str; |
190 | } | 208 | } |
191 | 209 | ||
192 | char * | ||
193 | dupstr (const char *s) | ||
194 | { | ||
195 | char *r; | ||
196 | |||
197 | r = malloc (strlen (s) + 1); | ||
198 | if (!r) | ||
199 | { | ||
200 | mu_error ("Memory exhausted"); | ||
201 | exit (1); | ||
202 | } | ||
203 | strcpy (r, s); | ||
204 | return r; | ||
205 | } | ||
206 | 210 | ||
207 | 211 | ||
208 | #ifdef WITH_READLINE | 212 | #ifdef WITH_READLINE |
... | @@ -269,7 +273,7 @@ command_generator (const char *text, int state) | ... | @@ -269,7 +273,7 @@ command_generator (const char *text, int state) |
269 | list_index++; | 273 | list_index++; |
270 | 274 | ||
271 | if (strncmp (name, text, len) == 0) | 275 | if (strncmp (name, text, len) == 0) |
272 | return (dupstr (name)); | 276 | return xstrdup (name); |
273 | } | 277 | } |
274 | 278 | ||
275 | /* If no names matched, then return NULL. */ | 279 | /* If no names matched, then return NULL. */ |
... | @@ -304,73 +308,103 @@ add_history (const char *s MU_ARG_UNUSED) | ... | @@ -304,73 +308,103 @@ add_history (const char *s MU_ARG_UNUSED) |
304 | } | 308 | } |
305 | #endif | 309 | #endif |
306 | 310 | ||
311 | int | ||
312 | get_bool (const char *str, int *pb) | ||
313 | { | ||
314 | if (mu_c_strcasecmp (str, "yes") == 0 | ||
315 | || mu_c_strcasecmp (str, "on") == 0 | ||
316 | || mu_c_strcasecmp (str, "true") == 0) | ||
317 | *pb = 1; | ||
318 | else if (mu_c_strcasecmp (str, "no") == 0 | ||
319 | || mu_c_strcasecmp (str, "off") == 0 | ||
320 | || mu_c_strcasecmp (str, "false") == 0) | ||
321 | *pb = 0; | ||
322 | else | ||
323 | { | ||
324 | mu_error ("not a boolean: %s", str); | ||
325 | return 1; | ||
326 | } | ||
327 | return 0; | ||
328 | } | ||
307 | 329 | ||
308 | int | 330 | int |
309 | main (int argc MU_ARG_UNUSED, char **argv) | 331 | get_port (const char *port_str, int *pn) |
310 | { | 332 | { |
311 | char *line, *s; | 333 | short port_num; |
312 | 334 | long num; | |
313 | mu_set_program_name (argv[0]); | 335 | char *p; |
314 | prompt = strdup (DEFAULT_PROMPT); | 336 | |
315 | initialize_readline (); /* Bind our completer. */ | 337 | num = port_num = strtol (port_str, &p, 0); |
316 | #ifdef WITH_TLS | 338 | if (*p == 0) |
317 | mu_init_tls_libs (); | ||
318 | #endif | ||
319 | /* Loop reading and executing lines until the user quits. */ | ||
320 | while (!done) | ||
321 | { | 339 | { |
322 | char *p = expand_prompt (); | 340 | if (num != port_num) |
323 | line = readline (p); | ||
324 | free (p); | ||
325 | |||
326 | if (!line) | ||
327 | break; | ||
328 | |||
329 | /* Remove leading and trailing whitespace from the line. | ||
330 | Then, if there is anything left, add it to the history list | ||
331 | and execute it. */ | ||
332 | s = mu_str_stripws (line); | ||
333 | |||
334 | if (*s) | ||
335 | { | 341 | { |
336 | int status; | 342 | mu_error ("bad port number: %s", port_str); |
337 | add_history (s); | 343 | return 1; |
338 | status = execute_line (s); | ||
339 | if (status != 0) | ||
340 | mu_error ("Error: %s", mu_strerror (status)); | ||
341 | } | 344 | } |
342 | |||
343 | free (line); | ||
344 | } | 345 | } |
345 | exit (0); | 346 | else |
347 | { | ||
348 | struct servent *sp = getservbyname (port_str, "tcp"); | ||
349 | if (!sp) | ||
350 | { | ||
351 | mu_error ("unknown port name"); | ||
352 | return 1; | ||
353 | } | ||
354 | port_num = ntohs (sp->s_port); | ||
355 | } | ||
356 | *pn = port_num; | ||
357 | return 0; | ||
346 | } | 358 | } |
347 | 359 | ||
348 | /* Parse and execute a command line. */ | 360 | /* Parse and execute a command line. */ |
349 | int | 361 | int |
350 | execute_line (char *line) | 362 | execute_line (char *line) |
351 | { | 363 | { |
352 | COMMAND *command; | 364 | int argc; |
353 | char *word, *arg; | 365 | char **argv; |
366 | int status = 0; | ||
354 | 367 | ||
355 | /* Isolate the command word. */ | 368 | if (mu_argcv_get (line, NULL, "#", &argc, &argv)) |
356 | word = mu_str_skip_class (line, MU_CTYPE_SPACE); | ||
357 | arg = mu_str_skip_class_comp (word, MU_CTYPE_SPACE); | ||
358 | if (*arg) | ||
359 | { | 369 | { |
360 | *arg++ = 0; | 370 | mu_error("cannot parse input line"); |
361 | arg = mu_str_skip_class (arg, MU_CTYPE_SPACE); | 371 | return 0; |
362 | } | 372 | } |
363 | |||
364 | command = find_command (word); | ||
365 | 373 | ||
366 | if (!command) | 374 | if (argc >= 0) |
367 | { | 375 | { |
368 | mu_error ("%s: No such command.", word); | 376 | COMMAND *command = find_command (argv[0]); |
369 | return 0; | 377 | |
378 | if (!command) | ||
379 | mu_error ("%s: no such command.", argv[0]); | ||
380 | else if (command->argmin > 0 && argc < command->argmin) | ||
381 | mu_error ("%s: too few arguments", argv[0]); | ||
382 | else if (command->argmax > 0 && argc > command->argmax) | ||
383 | mu_error ("%s: too many arguments", argv[0]); | ||
384 | else | ||
385 | { | ||
386 | if (command->argmin <= 0 && argc != 2) | ||
387 | { | ||
388 | char *word = mu_str_skip_class (line, MU_CTYPE_SPACE); | ||
389 | char *arg = mu_str_skip_class_comp (word, MU_CTYPE_SPACE); | ||
390 | if (*arg) | ||
391 | { | ||
392 | *arg++ = 0; | ||
393 | arg = mu_str_skip_class (arg, MU_CTYPE_SPACE); | ||
394 | } | ||
395 | |||
396 | mu_argcv_free (argc, argv); | ||
397 | argc = 2; | ||
398 | argv = xcalloc (argc + 1, sizeof (argv[0])); | ||
399 | argv[0] = xstrdup (word); | ||
400 | argv[1] = xstrdup (arg); | ||
401 | argv[2] = NULL; | ||
402 | } | ||
403 | status = command->func (argc, argv); | ||
404 | } | ||
370 | } | 405 | } |
371 | 406 | mu_argcv_free (argc, argv); | |
372 | /* Call the function. */ | 407 | return status; |
373 | return ((*(command->func)) (arg)); | ||
374 | } | 408 | } |
375 | 409 | ||
376 | /* Look up NAME as the name of a command, and return a pointer to that | 410 | /* Look up NAME as the name of a command, and return a pointer to that |
... | @@ -378,106 +412,139 @@ execute_line (char *line) | ... | @@ -378,106 +412,139 @@ execute_line (char *line) |
378 | COMMAND * | 412 | COMMAND * |
379 | find_command (char *name) | 413 | find_command (char *name) |
380 | { | 414 | { |
381 | register int i; | 415 | COMMAND *cp; |
382 | 416 | ||
383 | for (i = 0; commands[i].name; i++) | 417 | for (cp = commands; cp->name; cp++) |
384 | if (strcmp (name, commands[i].name) == 0) | 418 | if (strcmp (cp->name, name) == 0) |
385 | return (&commands[i]); | 419 | return cp; |
386 | 420 | ||
387 | return ((COMMAND *) NULL); | 421 | return NULL; |
388 | } | 422 | } |
389 | 423 | ||
390 | int | 424 | int |
391 | com_verbose (char *arg) | 425 | com_verbose (int argc, char **argv) |
392 | { | 426 | { |
393 | int status = 0; | 427 | if (argc == 1) |
394 | if (!valid_argument ("verbose", arg)) | ||
395 | return EINVAL; | ||
396 | |||
397 | verbose = (strcmp (arg, "on") == 0); | ||
398 | if (pop3 != NULL) | ||
399 | { | 428 | { |
400 | if (verbose == 1) | 429 | if (verbose) |
401 | mu_pop3_trace (pop3, MU_POP3_TRACE_SET); | 430 | printf ("verbose is on\n"); |
402 | else | 431 | else |
403 | mu_pop3_trace (pop3, MU_POP3_TRACE_CLR); | 432 | printf ("verbose is off\n"); |
404 | } | 433 | } |
405 | return status; | 434 | else |
435 | { | ||
436 | int bv; | ||
437 | |||
438 | if (get_bool (argv[1], &bv) == 0) | ||
439 | { | ||
440 | verbose = bv; | ||
441 | if (pop3 != NULL) | ||
442 | { | ||
443 | if (verbose == 1) | ||
444 | mu_pop3_trace (pop3, MU_POP3_TRACE_SET); | ||
445 | else | ||
446 | mu_pop3_trace (pop3, MU_POP3_TRACE_CLR); | ||
447 | } | ||
448 | } | ||
449 | } | ||
450 | return 0; | ||
406 | } | 451 | } |
407 | 452 | ||
408 | int | 453 | int |
409 | com_user (char *arg) | 454 | com_user (int argc, char **argv) |
410 | { | 455 | { |
411 | int status; | 456 | int status; |
412 | 457 | ||
413 | if (!valid_argument ("user", arg)) | 458 | status = mu_pop3_user (pop3, argv[1]); |
414 | return EINVAL; | ||
415 | status = mu_pop3_user (pop3, arg); | ||
416 | if (status == 0) | 459 | if (status == 0) |
417 | username = strdup (arg); | 460 | username = strdup (argv[1]); |
418 | return status; | 461 | return status; |
419 | } | 462 | } |
420 | 463 | ||
421 | int | 464 | int |
422 | com_apop (char *arg) | 465 | com_apop (int argc, char **argv) |
423 | { | 466 | { |
424 | int status; | 467 | int status; |
425 | char *user, *digest; | 468 | |
426 | 469 | status = mu_pop3_apop (pop3, argv[1], argv[2]); | |
427 | if (!valid_argument ("apop", arg)) | ||
428 | return EINVAL; | ||
429 | user = strtok (arg, " "); | ||
430 | digest = strtok (NULL, " "); | ||
431 | if (!valid_argument ("apop", user) || !valid_argument ("apop", digest)) | ||
432 | return EINVAL; | ||
433 | status = mu_pop3_apop (pop3, user, digest); | ||
434 | if (status == 0) | 470 | if (status == 0) |
435 | { | 471 | { |
436 | username = strdup (user); | 472 | username = strdup (argv[1]); |
437 | pop_session_status = pop_session_logged_in; | 473 | pop_session_status = pop_session_logged_in; |
438 | } | 474 | } |
439 | return status; | 475 | return status; |
440 | } | 476 | } |
441 | 477 | ||
442 | int | 478 | int |
443 | com_capa (char *arg) | 479 | com_capa (int argc, char **argv) |
444 | { | 480 | { |
445 | mu_iterator_t iterator = NULL; | 481 | mu_iterator_t iterator = NULL; |
446 | int status; | 482 | int status = 0; |
447 | int reread = 0; | 483 | int reread = 0; |
448 | 484 | int i = 1; | |
449 | if (arg && *arg) | 485 | |
486 | for (i = 1; i < argc; i++) | ||
450 | { | 487 | { |
451 | if (strcmp (arg, "reread") == 0) | 488 | if (strcmp (argv[i], "-reread") == 0) |
452 | reread = 1; | 489 | reread = 1; |
453 | else | 490 | else |
491 | break; | ||
492 | } | ||
493 | |||
494 | if (i < argc) | ||
495 | { | ||
496 | if (reread) | ||
454 | { | 497 | { |
455 | mu_error ("%s: unknown argument", "capa"); | 498 | status = mu_pop3_capa (pop3, 1, NULL); |
456 | return 0; | 499 | if (status) |
500 | return status; | ||
501 | } | ||
502 | for (; i < argc; i++) | ||
503 | { | ||
504 | const char *elt; | ||
505 | int rc = pop3_capa_test (pop3, argv[i], &elt); | ||
506 | switch (rc) | ||
507 | { | ||
508 | case 0: | ||
509 | if (*elt) | ||
510 | printf ("%s: %s\n", argv[i], elt); | ||
511 | else | ||
512 | printf ("%s is set\n", argv[i]); | ||
513 | break; | ||
514 | |||
515 | case MU_ERR_NOENT: | ||
516 | printf ("%s is not set\n", argv[i]); | ||
517 | break; | ||
518 | |||
519 | default: | ||
520 | return rc; | ||
521 | } | ||
457 | } | 522 | } |
458 | } | 523 | } |
459 | 524 | else | |
460 | status = mu_pop3_capa (pop3, reread, &iterator); | ||
461 | |||
462 | if (status == 0) | ||
463 | { | 525 | { |
464 | for (mu_iterator_first (iterator); | 526 | status = mu_pop3_capa (pop3, reread, &iterator); |
465 | !mu_iterator_is_done (iterator); mu_iterator_next (iterator)) | 527 | |
528 | if (status == 0) | ||
466 | { | 529 | { |
467 | char *capa = NULL; | 530 | for (mu_iterator_first (iterator); |
468 | mu_iterator_current (iterator, (void **) &capa); | 531 | !mu_iterator_is_done (iterator); mu_iterator_next (iterator)) |
469 | printf ("Capa: %s\n", (capa) ? capa : ""); | 532 | { |
533 | char *capa = NULL; | ||
534 | mu_iterator_current (iterator, (void **) &capa); | ||
535 | printf ("CAPA: %s\n", capa ? capa : ""); | ||
536 | } | ||
537 | mu_iterator_destroy (&iterator); | ||
470 | } | 538 | } |
471 | mu_iterator_destroy (&iterator); | ||
472 | } | 539 | } |
473 | return status; | 540 | return status; |
474 | } | 541 | } |
475 | 542 | ||
476 | int | 543 | int |
477 | com_uidl (char *arg) | 544 | com_uidl (int argc, char **argv) |
478 | { | 545 | { |
479 | int status = 0; | 546 | int status = 0; |
480 | if (arg == NULL || *arg == '\0') | 547 | if (argc == 1) |
481 | { | 548 | { |
482 | mu_iterator_t uidl_iterator = NULL; | 549 | mu_iterator_t uidl_iterator = NULL; |
483 | status = mu_pop3_uidl_all (pop3, &uidl_iterator); | 550 | status = mu_pop3_uidl_all (pop3, &uidl_iterator); |
... | @@ -489,7 +556,7 @@ com_uidl (char *arg) | ... | @@ -489,7 +556,7 @@ com_uidl (char *arg) |
489 | { | 556 | { |
490 | char *uidl = NULL; | 557 | char *uidl = NULL; |
491 | mu_iterator_current (uidl_iterator, (void **) &uidl); | 558 | mu_iterator_current (uidl_iterator, (void **) &uidl); |
492 | printf ("UIDL: %s\n", (uidl) ? uidl : ""); | 559 | printf ("UIDL: %s\n", uidl ? uidl : ""); |
493 | } | 560 | } |
494 | mu_iterator_destroy (&uidl_iterator); | 561 | mu_iterator_destroy (&uidl_iterator); |
495 | } | 562 | } |
... | @@ -497,20 +564,20 @@ com_uidl (char *arg) | ... | @@ -497,20 +564,20 @@ com_uidl (char *arg) |
497 | else | 564 | else |
498 | { | 565 | { |
499 | char *uidl = NULL; | 566 | char *uidl = NULL; |
500 | unsigned int msgno = strtoul (arg, NULL, 10); | 567 | unsigned int msgno = strtoul (argv[1], NULL, 10); |
501 | status = mu_pop3_uidl (pop3, msgno, &uidl); | 568 | status = mu_pop3_uidl (pop3, msgno, &uidl); |
502 | if (status == 0) | 569 | if (status == 0) |
503 | printf ("Msg: %d UIDL: %s\n", msgno, (uidl) ? uidl : ""); | 570 | printf ("Msg: %d UIDL: %s\n", msgno, uidl ? uidl : ""); |
504 | free (uidl); | 571 | free (uidl); |
505 | } | 572 | } |
506 | return status; | 573 | return status; |
507 | } | 574 | } |
508 | 575 | ||
509 | int | 576 | int |
510 | com_list (char *arg) | 577 | com_list (int argc, char **argv) |
511 | { | 578 | { |
512 | int status = 0; | 579 | int status = 0; |
513 | if (arg == NULL || *arg == '\0') | 580 | if (argc == 1) |
514 | { | 581 | { |
515 | mu_iterator_t list_iterator; | 582 | mu_iterator_t list_iterator; |
516 | status = mu_pop3_list_all (pop3, &list_iterator); | 583 | status = mu_pop3_list_all (pop3, &list_iterator); |
... | @@ -530,7 +597,7 @@ com_list (char *arg) | ... | @@ -530,7 +597,7 @@ com_list (char *arg) |
530 | else | 597 | else |
531 | { | 598 | { |
532 | size_t size = 0; | 599 | size_t size = 0; |
533 | unsigned int msgno = strtoul (arg, NULL, 10); | 600 | unsigned int msgno = strtoul (argv[1], NULL, 10); |
534 | status = mu_pop3_list (pop3, msgno, &size); | 601 | status = mu_pop3_list (pop3, msgno, &size); |
535 | if (status == 0) | 602 | if (status == 0) |
536 | printf ("Msg: %u Size: %lu\n", msgno, (unsigned long) size); | 603 | printf ("Msg: %u Size: %lu\n", msgno, (unsigned long) size); |
... | @@ -539,7 +606,7 @@ com_list (char *arg) | ... | @@ -539,7 +606,7 @@ com_list (char *arg) |
539 | } | 606 | } |
540 | 607 | ||
541 | int | 608 | int |
542 | com_noop (char *arg MU_ARG_UNUSED) | 609 | com_noop (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) |
543 | { | 610 | { |
544 | return mu_pop3_noop (pop3); | 611 | return mu_pop3_noop (pop3); |
545 | } | 612 | } |
... | @@ -561,33 +628,31 @@ echo_on (struct termios *stored_settings) | ... | @@ -561,33 +628,31 @@ echo_on (struct termios *stored_settings) |
561 | } | 628 | } |
562 | 629 | ||
563 | int | 630 | int |
564 | com_prompt (char *arg) | 631 | com_prompt (int argc, char **argv) |
565 | { | 632 | { |
566 | int quote; | 633 | int quote; |
567 | size_t size; | 634 | size_t size; |
568 | 635 | ||
569 | if (!valid_argument ("prompt", arg)) | ||
570 | return EINVAL; | ||
571 | |||
572 | free (prompt); | 636 | free (prompt); |
573 | size = mu_argcv_quoted_length (arg, "e); | 637 | size = mu_argcv_quoted_length (argv[1], "e); |
574 | prompt = malloc (size + 1); | 638 | prompt = malloc (size + 1); |
575 | if (!prompt) | 639 | if (!prompt) |
576 | { | 640 | { |
577 | mu_error ("Memory exhausted"); | 641 | mu_error ("Memory exhausted"); |
578 | exit (1); | 642 | exit (1); |
579 | } | 643 | } |
580 | mu_argcv_unquote_copy (prompt, arg, size); | 644 | mu_argcv_unquote_copy (prompt, argv[1], size); |
581 | return 0; | 645 | return 0; |
582 | } | 646 | } |
583 | 647 | ||
584 | int | 648 | int |
585 | com_pass (char *arg) | 649 | com_pass (int argc, char **argv) |
586 | { | 650 | { |
587 | int status; | 651 | int status; |
588 | char pass[256]; | 652 | char pass[256]; |
653 | char *pwd; | ||
589 | 654 | ||
590 | if (!arg || *arg == '\0') | 655 | if (argc == 1) |
591 | { | 656 | { |
592 | struct termios stored_settings; | 657 | struct termios stored_settings; |
593 | 658 | ||
... | @@ -599,16 +664,18 @@ com_pass (char *arg) | ... | @@ -599,16 +664,18 @@ com_pass (char *arg) |
599 | putchar ('\n'); | 664 | putchar ('\n'); |
600 | fflush (stdout); | 665 | fflush (stdout); |
601 | pass[strlen (pass) - 1] = '\0'; /* nuke the trailing line. */ | 666 | pass[strlen (pass) - 1] = '\0'; /* nuke the trailing line. */ |
602 | arg = pass; | 667 | pwd = pass; |
603 | } | 668 | } |
604 | status = mu_pop3_pass (pop3, arg); | 669 | else |
670 | pwd = argv[1]; | ||
671 | status = mu_pop3_pass (pop3, pwd); | ||
605 | if (status == 0) | 672 | if (status == 0) |
606 | pop_session_status = pop_session_logged_in; | 673 | pop_session_status = pop_session_logged_in; |
607 | return status; | 674 | return status; |
608 | } | 675 | } |
609 | 676 | ||
610 | int | 677 | int |
611 | com_stat (char *arg MU_ARG_UNUSED) | 678 | com_stat (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) |
612 | { | 679 | { |
613 | unsigned count = 0; | 680 | unsigned count = 0; |
614 | size_t size = 0; | 681 | size_t size = 0; |
... | @@ -621,32 +688,31 @@ com_stat (char *arg MU_ARG_UNUSED) | ... | @@ -621,32 +688,31 @@ com_stat (char *arg MU_ARG_UNUSED) |
621 | } | 688 | } |
622 | 689 | ||
623 | int | 690 | int |
624 | com_stls (char *arg MU_ARG_UNUSED) | 691 | com_stls (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) |
625 | { | 692 | { |
626 | return mu_pop3_stls (pop3); | 693 | return mu_pop3_stls (pop3); |
627 | } | 694 | } |
628 | 695 | ||
629 | int | 696 | int |
630 | com_dele (char *arg) | 697 | com_dele (int argc, char **argv) |
631 | { | 698 | { |
632 | unsigned msgno; | 699 | unsigned msgno; |
633 | if (!valid_argument ("dele", arg)) | 700 | msgno = strtoul (argv[1], NULL, 10); |
634 | return EINVAL; | ||
635 | msgno = strtoul (arg, NULL, 10); | ||
636 | return mu_pop3_dele (pop3, msgno); | 701 | return mu_pop3_dele (pop3, msgno); |
637 | } | 702 | } |
638 | 703 | ||
639 | /* Print out help for ARG, or for all of the commands if ARG is | 704 | /* Print out help for ARG, or for all of the commands if ARG is |
640 | not present. */ | 705 | not present. */ |
641 | int | 706 | int |
642 | com_help (char *arg) | 707 | com_help (int argc, char **argv) |
643 | { | 708 | { |
644 | int i; | 709 | int i; |
645 | int printed = 0; | 710 | int printed = 0; |
646 | 711 | char *name = argv[1]; | |
712 | |||
647 | for (i = 0; commands[i].name; i++) | 713 | for (i = 0; commands[i].name; i++) |
648 | { | 714 | { |
649 | if (!*arg || (strcmp (arg, commands[i].name) == 0)) | 715 | if (!name || (strcmp (name, commands[i].name) == 0)) |
650 | { | 716 | { |
651 | printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc); | 717 | printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc); |
652 | printed++; | 718 | printed++; |
... | @@ -655,7 +721,7 @@ com_help (char *arg) | ... | @@ -655,7 +721,7 @@ com_help (char *arg) |
655 | 721 | ||
656 | if (!printed) | 722 | if (!printed) |
657 | { | 723 | { |
658 | printf ("No commands match `%s'. Possibilties are:\n", arg); | 724 | printf ("No commands match `%s'. Possibilties are:\n", name); |
659 | 725 | ||
660 | for (i = 0; commands[i].name; i++) | 726 | for (i = 0; commands[i].name; i++) |
661 | { | 727 | { |
... | @@ -677,32 +743,24 @@ com_help (char *arg) | ... | @@ -677,32 +743,24 @@ com_help (char *arg) |
677 | } | 743 | } |
678 | 744 | ||
679 | int | 745 | int |
680 | com_rset (char *arg MU_ARG_UNUSED) | 746 | com_rset (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) |
681 | { | 747 | { |
682 | return mu_pop3_rset (pop3); | 748 | return mu_pop3_rset (pop3); |
683 | } | 749 | } |
684 | 750 | ||
685 | int | 751 | int |
686 | com_top (char *arg) | 752 | com_top (int argc, char **argv) |
687 | { | 753 | { |
688 | mu_stream_t stream; | 754 | mu_stream_t stream; |
689 | unsigned int msgno; | 755 | unsigned int msgno; |
690 | unsigned int lines; | 756 | unsigned int lines; |
691 | char *space; | ||
692 | int status; | 757 | int status; |
693 | 758 | ||
694 | if (!valid_argument ("top", arg)) | 759 | msgno = strtoul (argv[1], NULL, 10); |
695 | return EINVAL; | 760 | if (argc == 3) |
696 | 761 | lines = strtoul (argv[2], NULL, 10); | |
697 | space = strchr (arg, ' '); | ||
698 | if (space) | ||
699 | { | ||
700 | *space++ = '\0'; | ||
701 | lines = strtoul (space, NULL, 10); | ||
702 | } | ||
703 | else | 762 | else |
704 | lines = 0; | 763 | lines = 5; |
705 | msgno = strtoul (arg, NULL, 10); | ||
706 | 764 | ||
707 | status = mu_pop3_top (pop3, msgno, lines, &stream); | 765 | status = mu_pop3_top (pop3, msgno, lines, &stream); |
708 | 766 | ||
... | @@ -718,16 +776,13 @@ com_top (char *arg) | ... | @@ -718,16 +776,13 @@ com_top (char *arg) |
718 | } | 776 | } |
719 | 777 | ||
720 | int | 778 | int |
721 | com_retr (char *arg) | 779 | com_retr (int argc, char **argv) |
722 | { | 780 | { |
723 | mu_stream_t stream; | 781 | mu_stream_t stream; |
724 | unsigned int msgno; | 782 | unsigned int msgno; |
725 | int status; | 783 | int status; |
726 | 784 | ||
727 | if (!valid_argument ("retr", arg)) | 785 | msgno = strtoul (argv[1], NULL, 10); |
728 | return EINVAL; | ||
729 | |||
730 | msgno = strtoul (arg, NULL, 10); | ||
731 | status = mu_pop3_retr (pop3, msgno, &stream); | 786 | status = mu_pop3_retr (pop3, msgno, &stream); |
732 | 787 | ||
733 | if (status == 0) | 788 | if (status == 0) |
... | @@ -742,73 +797,44 @@ com_retr (char *arg) | ... | @@ -742,73 +797,44 @@ com_retr (char *arg) |
742 | } | 797 | } |
743 | 798 | ||
744 | int | 799 | int |
745 | get_port (const char *port_str, int *pn) | 800 | com_connect (int argc, char **argv) |
746 | { | 801 | { |
747 | short port_num; | 802 | int status; |
748 | long num; | 803 | int n = 0; |
749 | char *p; | 804 | int tls = 0; |
805 | int i = 1; | ||
750 | 806 | ||
751 | num = port_num = strtol (port_str, &p, 0); | 807 | for (i = 1; i < argc; i++) |
752 | if (*p == 0) | ||
753 | { | ||
754 | if (num != port_num) | ||
755 | { | ||
756 | mu_error ("bad port number: %s", port_str); | ||
757 | return 1; | ||
758 | } | ||
759 | } | ||
760 | else | ||
761 | { | 808 | { |
762 | struct servent *sp = getservbyname (port_str, "tcp"); | 809 | if (strcmp (argv[i], "-tls") == 0) |
763 | if (!sp) | ||
764 | { | 810 | { |
765 | mu_error ("unknown port name"); | 811 | if (WITH_TLS) |
766 | return 1; | 812 | tls = 1; |
813 | else | ||
814 | { | ||
815 | mu_error ("TLS not supported"); | ||
816 | return 0; | ||
817 | } | ||
767 | } | 818 | } |
768 | port_num = ntohs (sp->s_port); | 819 | else |
820 | break; | ||
769 | } | 821 | } |
770 | *pn = port_num; | ||
771 | return 0; | ||
772 | } | ||
773 | 822 | ||
774 | int | 823 | argc -= i; |
775 | com_connect (char *arg) | 824 | argv += i; |
776 | { | ||
777 | int status; | ||
778 | int n = 110; | ||
779 | int argc; | ||
780 | char **argv; | ||
781 | |||
782 | if (!valid_argument ("connect", arg)) | ||
783 | return 1; | ||
784 | 825 | ||
785 | if (mu_argcv_get (arg, NULL, NULL, &argc, &argv)) | 826 | if (argc >= 2) |
786 | { | 827 | { |
787 | mu_error ("Cannot parse arguments"); | 828 | if (get_port (argv[1], &n)) |
788 | return 0; | 829 | return 0; |
789 | } | ||
790 | |||
791 | if (!valid_argument ("connect", argv[0])) | ||
792 | { | ||
793 | mu_argcv_free (argc, argv); | ||
794 | return EINVAL; | ||
795 | } | ||
796 | |||
797 | if (argc > 2) | ||
798 | { | ||
799 | mu_error ("Too many arguments"); | ||
800 | mu_argcv_free (argc, argv); | ||
801 | return 0; | ||
802 | } | ||
803 | |||
804 | if (argc == 2 && get_port (argv[1], &n)) | ||
805 | { | ||
806 | mu_argcv_free (argc, argv); | ||
807 | return 0; | ||
808 | } | 830 | } |
831 | else if (tls) | ||
832 | n = MU_POP3_DEFAULT_SSL_PORT; | ||
833 | else | ||
834 | n = MU_POP3_DEFAULT_PORT; | ||
809 | 835 | ||
810 | if (pop_session_status != pop_session_disconnected) | 836 | if (pop_session_status != pop_session_disconnected) |
811 | com_disconnect (NULL); | 837 | com_disconnect (0, NULL); |
812 | 838 | ||
813 | status = mu_pop3_create (&pop3); | 839 | status = mu_pop3_create (&pop3); |
814 | if (status == 0) | 840 | if (status == 0) |
... | @@ -816,10 +842,35 @@ com_connect (char *arg) | ... | @@ -816,10 +842,35 @@ com_connect (char *arg) |
816 | mu_stream_t tcp; | 842 | mu_stream_t tcp; |
817 | 843 | ||
818 | if (verbose) | 844 | if (verbose) |
819 | com_verbose ("on"); | 845 | mu_pop3_trace (pop3, MU_POP3_TRACE_SET); |
820 | status = mu_tcp_stream_create (&tcp, argv[0], n, MU_STREAM_READ); | 846 | status = mu_tcp_stream_create (&tcp, argv[0], n, MU_STREAM_READ); |
821 | if (status == 0) | 847 | if (status == 0) |
822 | { | 848 | { |
849 | #ifdef WITH_TLS | ||
850 | if (tls) | ||
851 | { | ||
852 | mu_stream_t tlsstream; | ||
853 | |||
854 | status = mu_stream_open (tcp); | ||
855 | if (status) | ||
856 | { | ||
857 | mu_error ("cannot open connection: %s", | ||
858 | mu_stream_strerror (tcp, status)); | ||
859 | mu_stream_destroy (&tcp); | ||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | status = mu_tls_client_stream_create (&tlsstream, tcp, tcp, 0); | ||
864 | mu_stream_unref (tcp); | ||
865 | if (status) | ||
866 | { | ||
867 | mu_error ("cannot create TLS stream: %s", | ||
868 | mu_strerror (status)); | ||
869 | return 0; | ||
870 | } | ||
871 | tcp = tlsstream; | ||
872 | } | ||
873 | #endif | ||
823 | mu_pop3_set_carrier (pop3, tcp); | 874 | mu_pop3_set_carrier (pop3, tcp); |
824 | status = mu_pop3_connect (pop3); | 875 | status = mu_pop3_connect (pop3); |
825 | } | 876 | } |
... | @@ -831,14 +882,14 @@ com_connect (char *arg) | ... | @@ -831,14 +882,14 @@ com_connect (char *arg) |
831 | } | 882 | } |
832 | 883 | ||
833 | if (status) | 884 | if (status) |
834 | { | 885 | mu_error ("Failed to create pop3: %s", mu_strerror (status)); |
835 | mu_error ("Failed to create pop3: %s", mu_strerror (status)); | ||
836 | mu_argcv_free (argc, argv); | ||
837 | } | ||
838 | else | 886 | else |
839 | { | 887 | { |
840 | connect_argc = argc; | 888 | connect_argc = argc; |
841 | connect_argv = argv; | 889 | connect_argv = xcalloc (argc, sizeof (*connect_argv)); |
890 | for (i = 0; i < argc; i++) | ||
891 | connect_argv[i] = xstrdup (argv[i]); | ||
892 | connect_argv[i] = NULL; | ||
842 | port = n; | 893 | port = n; |
843 | pop_session_status = pop_session_connected; | 894 | pop_session_status = pop_session_connected; |
844 | } | 895 | } |
... | @@ -847,7 +898,7 @@ com_connect (char *arg) | ... | @@ -847,7 +898,7 @@ com_connect (char *arg) |
847 | } | 898 | } |
848 | 899 | ||
849 | int | 900 | int |
850 | com_disconnect (char *arg MU_ARG_UNUSED) | 901 | com_disconnect (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) |
851 | { | 902 | { |
852 | if (pop3) | 903 | if (pop3) |
853 | { | 904 | { |
... | @@ -864,14 +915,14 @@ com_disconnect (char *arg MU_ARG_UNUSED) | ... | @@ -864,14 +915,14 @@ com_disconnect (char *arg MU_ARG_UNUSED) |
864 | } | 915 | } |
865 | 916 | ||
866 | int | 917 | int |
867 | com_quit (char *arg MU_ARG_UNUSED) | 918 | com_quit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) |
868 | { | 919 | { |
869 | int status = 0; | 920 | int status = 0; |
870 | if (pop3) | 921 | if (pop3) |
871 | { | 922 | { |
872 | if (mu_pop3_quit (pop3) == 0) | 923 | if (mu_pop3_quit (pop3) == 0) |
873 | { | 924 | { |
874 | status = com_disconnect (arg); | 925 | status = com_disconnect (0, NULL); |
875 | } | 926 | } |
876 | else | 927 | else |
877 | { | 928 | { |
... | @@ -884,7 +935,7 @@ com_quit (char *arg MU_ARG_UNUSED) | ... | @@ -884,7 +935,7 @@ com_quit (char *arg MU_ARG_UNUSED) |
884 | } | 935 | } |
885 | 936 | ||
886 | int | 937 | int |
887 | com_exit (char *arg MU_ARG_UNUSED) | 938 | com_exit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) |
888 | { | 939 | { |
889 | if (pop3) | 940 | if (pop3) |
890 | { | 941 | { |
... | @@ -895,16 +946,44 @@ com_exit (char *arg MU_ARG_UNUSED) | ... | @@ -895,16 +946,44 @@ com_exit (char *arg MU_ARG_UNUSED) |
895 | return 0; | 946 | return 0; |
896 | } | 947 | } |
897 | 948 | ||
898 | /* Return non-zero if ARG is a valid argument for CALLER, else print | 949 | |
899 | an error message and return zero. */ | ||
900 | int | 950 | int |
901 | valid_argument (const char *caller, char *arg) | 951 | main (int argc MU_ARG_UNUSED, char **argv) |
902 | { | 952 | { |
903 | if (!arg || !*arg) | 953 | char *line, *s; |
954 | |||
955 | mu_set_program_name (argv[0]); | ||
956 | prompt = strdup (DEFAULT_PROMPT); | ||
957 | initialize_readline (); /* Bind our completer. */ | ||
958 | #ifdef WITH_TLS | ||
959 | mu_init_tls_libs (); | ||
960 | #endif | ||
961 | /* Loop reading and executing lines until the user quits. */ | ||
962 | while (!done) | ||
904 | { | 963 | { |
905 | mu_error ("%s: Argument required", caller); | 964 | char *p = expand_prompt (); |
906 | return 0; | 965 | line = readline (p); |
907 | } | 966 | free (p); |
967 | |||
968 | if (!line) | ||
969 | break; | ||
970 | |||
971 | /* Remove leading and trailing whitespace from the line. | ||
972 | Then, if there is anything left, add it to the history list | ||
973 | and execute it. */ | ||
974 | s = mu_str_stripws (line); | ||
908 | 975 | ||
909 | return 1; | 976 | if (*s) |
977 | { | ||
978 | int status; | ||
979 | add_history (s); | ||
980 | status = execute_line (s); | ||
981 | if (status != 0) | ||
982 | mu_error ("Error: %s", mu_strerror (status)); | ||
983 | } | ||
984 | |||
985 | free (line); | ||
986 | } | ||
987 | exit (0); | ||
910 | } | 988 | } |
989 | ... | ... |
... | @@ -32,87 +32,99 @@ struct _mu_pop3; | ... | @@ -32,87 +32,99 @@ struct _mu_pop3; |
32 | typedef struct _mu_pop3 *mu_pop3_t; | 32 | typedef struct _mu_pop3 *mu_pop3_t; |
33 | 33 | ||
34 | #define MU_POP3_DEFAULT_PORT 110 | 34 | #define MU_POP3_DEFAULT_PORT 110 |
35 | #define MU_POP3_DEFAULT_SSL_PORT 995 | ||
35 | 36 | ||
36 | extern int mu_pop3_create (mu_pop3_t *pop3); | 37 | int mu_pop3_create (mu_pop3_t *pop3); |
37 | extern void mu_pop3_destroy (mu_pop3_t *pop3); | 38 | void mu_pop3_destroy (mu_pop3_t *pop3); |
38 | 39 | ||
39 | extern int mu_pop3_set_carrier (mu_pop3_t pop3, mu_stream_t carrier); | 40 | int mu_pop3_set_carrier (mu_pop3_t pop3, mu_stream_t carrier); |
40 | extern int mu_pop3_get_carrier (mu_pop3_t pop3, mu_stream_t *pcarrier); | 41 | int mu_pop3_get_carrier (mu_pop3_t pop3, mu_stream_t *pcarrier); |
41 | 42 | ||
42 | extern int mu_pop3_connect (mu_pop3_t pop3); | 43 | int mu_pop3_connect (mu_pop3_t pop3); |
43 | extern int mu_pop3_disconnect (mu_pop3_t pop3); | 44 | int mu_pop3_disconnect (mu_pop3_t pop3); |
44 | 45 | ||
45 | extern int mu_pop3_set_timeout (mu_pop3_t pop3, int timeout); | 46 | int mu_pop3_set_timeout (mu_pop3_t pop3, int timeout); |
46 | extern int mu_pop3_get_timeout (mu_pop3_t pop3, int *timeout); | 47 | int mu_pop3_get_timeout (mu_pop3_t pop3, int *timeout); |
47 | 48 | ||
48 | #define MU_POP3_TRACE_CLR 0 | 49 | #define MU_POP3_TRACE_CLR 0 |
49 | #define MU_POP3_TRACE_SET 1 | 50 | #define MU_POP3_TRACE_SET 1 |
50 | #define MU_POP3_TRACE_QRY 2 | 51 | #define MU_POP3_TRACE_QRY 2 |
51 | extern int mu_pop3_trace (mu_pop3_t pop3, int op); | 52 | int mu_pop3_trace (mu_pop3_t pop3, int op); |
52 | 53 | ||
53 | extern int mu_pop3_apop (mu_pop3_t pop3, const char *name, const char *digest); | 54 | int mu_pop3_apop (mu_pop3_t pop3, const char *name, const char *digest); |
54 | 55 | ||
55 | extern int mu_pop3_stls (mu_pop3_t pop3); | 56 | int mu_pop3_stls (mu_pop3_t pop3); |
56 | 57 | ||
57 | /* It is the responsability of the caller to call mu_iterator_destroy() when | 58 | /* It is the responsability of the caller to call mu_iterator_destroy() when |
58 | done with the iterator. The items returned by the iterator are of type | 59 | done with the iterator. The items returned by the iterator are of type |
59 | "const char *", no processing is done on the item except the removal of | 60 | "const char *", no processing is done on the item except the removal of |
60 | the trailing newline. */ | 61 | the trailing newline. */ |
61 | extern int mu_pop3_capa (mu_pop3_t pop3, int reread, | 62 | int mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter); |
62 | mu_iterator_t *piter); | 63 | int pop3_capa_test (mu_pop3_t pop3, const char *name, const char **pret); |
63 | 64 | ||
64 | extern int mu_pop3_dele (mu_pop3_t pop3, unsigned int mesgno); | 65 | int mu_pop3_dele (mu_pop3_t pop3, unsigned int mesgno); |
65 | 66 | ||
66 | extern int mu_pop3_list (mu_pop3_t pop3, unsigned int mesgno, size_t *mesg_octet); | 67 | int mu_pop3_list (mu_pop3_t pop3, unsigned int mesgno, size_t *mesg_octet); |
67 | 68 | ||
68 | /* An iterator is return with the multi-line answer. It is the responsability | 69 | /* Send the LIST command and prepare pop3 for receiving a multiline answer. |
69 | of the caller to call mu_iterator_destroy() to dispose of the iterator. */ | 70 | The caller is expected to obtain a stream via mu_pop3_stream_create, |
70 | extern int mu_pop3_list_all (mu_pop3_t pop3, mu_iterator_t *piterator); | 71 | or an iterator via mu_pop3_iterator_create and read data from them. |
71 | 72 | ||
72 | extern int mu_pop3_noop (mu_pop3_t pop3); | 73 | This function is not intended for use by a casual user, better use |
74 | mu_pop3_list_all or mu_pop3_list_all_stream. */ | ||
75 | int mu_pop3_list_cmd (mu_pop3_t pop3); | ||
76 | int mu_pop3_list_all (mu_pop3_t pop3, mu_iterator_t *pitr); | ||
77 | int mu_pop3_list_all_stream (mu_pop3_t pop3, mu_stream_t *pstream); | ||
73 | 78 | ||
74 | extern int mu_pop3_pass (mu_pop3_t pop3, const char *pass); | 79 | int mu_pop3_noop (mu_pop3_t pop3); |
75 | 80 | ||
76 | extern int mu_pop3_quit (mu_pop3_t pop3); | 81 | int mu_pop3_pass (mu_pop3_t pop3, const char *pass); |
82 | |||
83 | int mu_pop3_quit (mu_pop3_t pop3); | ||
77 | 84 | ||
78 | /* A stream is returned with the multi-line answer. It is the responsability | 85 | /* A stream is returned with the multi-line answer. It is the responsability |
79 | of the caller to call mu_stream_destroy() to dipose of the stream. */ | 86 | of the caller to call mu_stream_destroy() to dipose of the stream. */ |
80 | extern int mu_pop3_retr (mu_pop3_t pop3, unsigned int mesgno, | 87 | int mu_pop3_retr (mu_pop3_t pop3, unsigned int mesgno, |
81 | mu_stream_t *pstream); | 88 | mu_stream_t *pstream); |
82 | 89 | ||
83 | extern int mu_pop3_rset (mu_pop3_t pop3); | 90 | int mu_pop3_rset (mu_pop3_t pop3); |
84 | 91 | ||
85 | extern int mu_pop3_stat (mu_pop3_t pop3, unsigned int *count, | 92 | int mu_pop3_stat (mu_pop3_t pop3, unsigned int *count, size_t *octets); |
86 | size_t *octets); | ||
87 | 93 | ||
88 | /* A stream is returned with the multi-line answer. It is the responsability | 94 | /* A stream is returned with the multi-line answer. It is the responsability |
89 | of the caller to call mu_stream_destroy() to dipose of the stream. */ | 95 | of the caller to call mu_stream_destroy() to dipose of the stream. */ |
90 | extern int mu_pop3_top (mu_pop3_t pop3, unsigned int mesgno, | 96 | int mu_pop3_top (mu_pop3_t pop3, unsigned int mesgno, |
91 | unsigned int lines, mu_stream_t *pstream); | 97 | unsigned int lines, mu_stream_t *pstream); |
92 | 98 | ||
93 | /* The uidl is malloc'ed and returned in puidl; it is the responsability of | 99 | /* The uidl is malloc'ed and returned in puidl; it is the responsability of |
94 | the caller to free() the uild when done. */ | 100 | the caller to free() the uild when done. */ |
95 | extern int mu_pop3_uidl (mu_pop3_t pop3, unsigned int mesgno, | 101 | int mu_pop3_uidl (mu_pop3_t pop3, unsigned int mesgno, char **puidl); |
96 | char **puidl); | ||
97 | /* An iterator is returned with the multi-line answer. It is the | ||
98 | responsability of the caller to call mu_iterator_destroy() to dispose of | ||
99 | the iterator. */ | ||
100 | extern int mu_pop3_uidl_all (mu_pop3_t pop3, mu_iterator_t *piterator); | ||
101 | 102 | ||
102 | extern int mu_pop3_user (mu_pop3_t pop3, const char *user); | 103 | /* Send the UIDL command and prepare pop3 for receiving a multiline answer. |
104 | The caller is expected to obtain a stream via mu_pop3_stream_create, | ||
105 | or an iterator via mu_pop3_iterator_create and read data from them. | ||
103 | 106 | ||
107 | This function is not intended for use by a casual user, better use | ||
108 | mu_pop3_uidl_all or mu_pop3_uidl_all_stream. */ | ||
109 | int mu_pop3_uidl_all_cmd (mu_pop3_t pop3); | ||
110 | int mu_pop3_uidl_all (mu_pop3_t pop3, mu_iterator_t *piterator); | ||
111 | int mu_pop3_uidl_all_stream (mu_pop3_t pop3, mu_stream_t *pstream); | ||
104 | 112 | ||
113 | int mu_pop3_user (mu_pop3_t pop3, const char *user); | ||
105 | 114 | ||
106 | /* Returns the last command acknowledge. If the server supports RESP-CODE, | 115 | /* Returns the last command acknowledge. If the server supports RESP-CODE, |
107 | the message could be retrieved, but it is up to the caller to do the | 116 | the message could be retrieved, but it is up to the caller to do the |
108 | parsing. */ | 117 | parsing. */ |
109 | extern int mu_pop3_response (mu_pop3_t pop3, size_t *nread); | 118 | int mu_pop3_response (mu_pop3_t pop3, size_t *nread); |
110 | 119 | ||
111 | extern int mu_pop3_writeline (mu_pop3_t pop3, const char *format, ...) | 120 | int mu_pop3_writeline (mu_pop3_t pop3, const char *format, ...) |
112 | MU_PRINTFLIKE(2,3); | 121 | MU_PRINTFLIKE(2,3); |
113 | 122 | ||
114 | extern int mu_pop3_sendline (mu_pop3_t pop3, const char *line); | 123 | int mu_pop3_sendline (mu_pop3_t pop3, const char *line); |
115 | extern int mu_pop3_getline (mu_pop3_t pop3); | 124 | int mu_pop3_getline (mu_pop3_t pop3); |
125 | int mu_pop3_read_list (mu_pop3_t pop3, mu_list_t list); | ||
126 | int mu_pop3_stream_to_list (mu_pop3_t pop3, mu_stream_t stream, | ||
127 | mu_list_t list); | ||
116 | 128 | ||
117 | #ifdef __cplusplus | 129 | #ifdef __cplusplus |
118 | } | 130 | } | ... | ... |
... | @@ -24,6 +24,9 @@ | ... | @@ -24,6 +24,9 @@ |
24 | 24 | ||
25 | #define _MU_STR_INTERN_MASK 0xf000 | 25 | #define _MU_STR_INTERN_MASK 0xf000 |
26 | 26 | ||
27 | #define _MU_STR_EVENT_SET 1 | ||
28 | #define _MU_STR_EVENT_CLR 2 | ||
29 | |||
27 | struct _mu_stream | 30 | struct _mu_stream |
28 | { | 31 | { |
29 | int ref_count; | 32 | int ref_count; |
... | @@ -54,6 +57,9 @@ struct _mu_stream | ... | @@ -54,6 +57,9 @@ struct _mu_stream |
54 | int (*truncate) (struct _mu_stream *, mu_off_t); | 57 | int (*truncate) (struct _mu_stream *, mu_off_t); |
55 | int (*shutdown) (struct _mu_stream *, int); | 58 | int (*shutdown) (struct _mu_stream *, int); |
56 | 59 | ||
60 | void (*event_cb) (struct _mu_stream *, int, int); | ||
61 | int event_mask; | ||
62 | |||
57 | const char *(*error_string) (struct _mu_stream *, int); | 63 | const char *(*error_string) (struct _mu_stream *, int); |
58 | 64 | ||
59 | }; | 65 | }; |
... | @@ -65,6 +71,9 @@ int mu_stream_write_unbuffered (mu_stream_t stream, | ... | @@ -65,6 +71,9 @@ int mu_stream_write_unbuffered (mu_stream_t stream, |
65 | const void *buf, size_t size, | 71 | const void *buf, size_t size, |
66 | int full_write, size_t *pnwritten); | 72 | int full_write, size_t *pnwritten); |
67 | 73 | ||
74 | void _mu_stream_cleareof (mu_stream_t str); | ||
75 | void _mu_stream_seteof (mu_stream_t str); | ||
76 | |||
68 | #define _MU_SWAP_FIRST_ONLY 0x01 | 77 | #define _MU_SWAP_FIRST_ONLY 0x01 |
69 | #define _MU_SWAP_IOCTL_MUST_SUCCEED 0x02 | 78 | #define _MU_SWAP_IOCTL_MUST_SUCCEED 0x02 |
70 | 79 | ... | ... |
... | @@ -24,13 +24,14 @@ lib_LTLIBRARIES = libmu_pop.la | ... | @@ -24,13 +24,14 @@ lib_LTLIBRARIES = libmu_pop.la |
24 | libmu_pop_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@ | 24 | libmu_pop_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@ |
25 | libmu_pop_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@ | 25 | libmu_pop_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@ |
26 | 26 | ||
27 | # folder.c\ | 27 | # folder.c\ |
28 | # mbox.c\ | 28 | # url.c\ |
29 | # url.c | 29 | # mbox.c |
30 | libmu_pop_la_SOURCES = \ | 30 | libmu_pop_la_SOURCES = \ |
31 | \ | 31 | \ |
32 | pop3_apop.c \ | 32 | pop3_apop.c \ |
33 | pop3_capa.c \ | 33 | pop3_capa.c \ |
34 | pop3_capatst.c \ | ||
34 | pop3_carrier.c \ | 35 | pop3_carrier.c \ |
35 | pop3_connect.c \ | 36 | pop3_connect.c \ |
36 | pop3_create.c \ | 37 | pop3_create.c \ |
... | @@ -39,10 +40,13 @@ libmu_pop_la_SOURCES = \ | ... | @@ -39,10 +40,13 @@ libmu_pop_la_SOURCES = \ |
39 | pop3_disconnect.c \ | 40 | pop3_disconnect.c \ |
40 | pop3_iterator.c \ | 41 | pop3_iterator.c \ |
41 | pop3_lista.c \ | 42 | pop3_lista.c \ |
43 | pop3_listas.c \ | ||
42 | pop3_list.c \ | 44 | pop3_list.c \ |
45 | pop3_list_cmd.c \ | ||
43 | pop3_noop.c \ | 46 | pop3_noop.c \ |
44 | pop3_pass.c \ | 47 | pop3_pass.c \ |
45 | pop3_quit.c \ | 48 | pop3_quit.c \ |
49 | pop3_rdlist.c \ | ||
46 | pop3_readline.c \ | 50 | pop3_readline.c \ |
47 | pop3_response.c \ | 51 | pop3_response.c \ |
48 | pop3_retr.c \ | 52 | pop3_retr.c \ |
... | @@ -54,7 +58,9 @@ libmu_pop_la_SOURCES = \ | ... | @@ -54,7 +58,9 @@ libmu_pop_la_SOURCES = \ |
54 | pop3_timeout.c \ | 58 | pop3_timeout.c \ |
55 | pop3_top.c \ | 59 | pop3_top.c \ |
56 | pop3_trace.c \ | 60 | pop3_trace.c \ |
61 | pop3_uidl_cmd.c \ | ||
57 | pop3_uidla.c \ | 62 | pop3_uidla.c \ |
63 | pop3_uidlas.c \ | ||
58 | pop3_uidl.c \ | 64 | pop3_uidl.c \ |
59 | pop3_user.c | 65 | pop3_user.c |
60 | 66 | ... | ... |
... | @@ -33,36 +33,18 @@ | ... | @@ -33,36 +33,18 @@ |
33 | #include <mailutils/sys/pop3.h> | 33 | #include <mailutils/sys/pop3.h> |
34 | 34 | ||
35 | static int | 35 | static int |
36 | string_comp (const void *item, const void *value) | 36 | capa_comp (const void *item, const void *value) |
37 | { | 37 | { |
38 | return strcmp (item, value); | 38 | const char *capa = item; |
39 | } | 39 | const char *needle = value; |
40 | 40 | for (; *needle; capa++, needle++) | |
41 | int | ||
42 | _mu_pop3_fill_list (mu_pop3_t pop3, mu_list_t list) | ||
43 | { | ||
44 | mu_stream_t stream; | ||
45 | size_t n; | ||
46 | int status = mu_pop3_stream_create (pop3, &stream); | ||
47 | if (status) | ||
48 | return status; | ||
49 | |||
50 | while (mu_stream_getline (stream, &pop3->rdbuf, &pop3->rdsize, &n) == 0 | ||
51 | && n > 0) | ||
52 | { | 41 | { |
53 | char *np = strdup (pop3->rdbuf); | 42 | if (!*capa) |
54 | if (!np) | 43 | return 1; |
55 | { | 44 | if (mu_tolower (*capa) != mu_tolower (*needle)) |
56 | status = ENOMEM; | 45 | return 1; |
57 | break; | ||
58 | } | ||
59 | mu_rtrim_class (np, MU_CTYPE_SPACE); | ||
60 | status = mu_list_append (list, np); | ||
61 | if (status) | ||
62 | break; | ||
63 | } | 46 | } |
64 | mu_stream_destroy (&stream); | 47 | return !(*capa == 0 || mu_isspace (*capa)); |
65 | return status; | ||
66 | } | 48 | } |
67 | 49 | ||
68 | /* | 50 | /* |
... | @@ -91,7 +73,7 @@ mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter) | ... | @@ -91,7 +73,7 @@ mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter) |
91 | status = mu_list_create (&pop3->capa); | 73 | status = mu_list_create (&pop3->capa); |
92 | if (status) | 74 | if (status) |
93 | return status; | 75 | return status; |
94 | mu_list_set_comparator (pop3->capa, string_comp); | 76 | mu_list_set_comparator (pop3->capa, capa_comp); |
95 | mu_list_set_destroy_item (pop3->capa, mu_list_free_item); | 77 | mu_list_set_destroy_item (pop3->capa, mu_list_free_item); |
96 | 78 | ||
97 | switch (pop3->state) | 79 | switch (pop3->state) |
... | @@ -109,7 +91,7 @@ mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter) | ... | @@ -109,7 +91,7 @@ mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter) |
109 | pop3->state = MU_POP3_CAPA_RX; | 91 | pop3->state = MU_POP3_CAPA_RX; |
110 | 92 | ||
111 | case MU_POP3_CAPA_RX: | 93 | case MU_POP3_CAPA_RX: |
112 | status = _mu_pop3_fill_list (pop3, pop3->capa); | 94 | status = mu_pop3_read_list (pop3, pop3->capa); |
113 | MU_POP3_CHECK_ERROR (pop3, status); | 95 | MU_POP3_CHECK_ERROR (pop3, status); |
114 | if (piter) | 96 | if (piter) |
115 | status = mu_list_get_iterator (pop3->capa, piter); | 97 | status = mu_list_get_iterator (pop3->capa, piter); | ... | ... |
libproto/pop/pop3_capatst.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2003, 2004, 2005, 2007, 2010 Free Software Foundation, | ||
3 | Inc. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 3 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General | ||
16 | Public License along with this library; if not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301 USA */ | ||
19 | |||
20 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include <stdlib.h> | ||
25 | #include <mailutils/list.h> | ||
26 | #include <mailutils/sys/pop3.h> | ||
27 | |||
28 | int | ||
29 | pop3_capa_test (mu_pop3_t pop3, const char *name, const char **pret) | ||
30 | { | ||
31 | int rc; | ||
32 | |||
33 | rc = mu_pop3_capa (pop3, 0, NULL); | ||
34 | if (rc) | ||
35 | return rc; | ||
36 | return mu_list_locate (pop3->capa, (void*) name, (void**)pret); | ||
37 | } |
... | @@ -40,7 +40,7 @@ mu_pop3_list (mu_pop3_t pop3, unsigned int msgno, size_t *psize) | ... | @@ -40,7 +40,7 @@ mu_pop3_list (mu_pop3_t pop3, unsigned int msgno, size_t *psize) |
40 | switch (pop3->state) | 40 | switch (pop3->state) |
41 | { | 41 | { |
42 | case MU_POP3_NO_STATE: | 42 | case MU_POP3_NO_STATE: |
43 | status = mu_pop3_writeline (pop3, "LIST %d\r\n", msgno); | 43 | status = mu_pop3_writeline (pop3, "LIST %u\r\n", msgno); |
44 | MU_POP3_CHECK_ERROR (pop3, status); | 44 | MU_POP3_CHECK_ERROR (pop3, status); |
45 | MU_POP3_FCLR (pop3, MU_POP3_ACK); | 45 | MU_POP3_FCLR (pop3, MU_POP3_ACK); |
46 | pop3->state = MU_POP3_LIST; | 46 | pop3->state = MU_POP3_LIST; | ... | ... |
libproto/pop/pop3_list_cmd.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001, 2004, 2007, 2010 Free Software | ||
3 | Foundation, Inc. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 3 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General | ||
16 | Public License along with this library; if not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301 USA */ | ||
19 | |||
20 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include <stdlib.h> | ||
25 | #include <mailutils/sys/pop3.h> | ||
26 | |||
27 | int | ||
28 | mu_pop3_list_cmd (mu_pop3_t pop3) | ||
29 | { | ||
30 | int status = 0; | ||
31 | |||
32 | if (pop3 == NULL) | ||
33 | return EINVAL; | ||
34 | |||
35 | switch (pop3->state) | ||
36 | { | ||
37 | case MU_POP3_NO_STATE: | ||
38 | status = mu_pop3_writeline (pop3, "LIST\r\n"); | ||
39 | MU_POP3_CHECK_ERROR (pop3, status); | ||
40 | MU_POP3_FCLR (pop3, MU_POP3_ACK); | ||
41 | pop3->state = MU_POP3_LIST; | ||
42 | |||
43 | case MU_POP3_LIST: | ||
44 | status = mu_pop3_response (pop3, NULL); | ||
45 | MU_POP3_CHECK_EAGAIN (pop3, status); | ||
46 | MU_POP3_CHECK_OK (pop3); | ||
47 | pop3->state = MU_POP3_LIST_RX; | ||
48 | |||
49 | case MU_POP3_LIST_RX: | ||
50 | /* The mu_iterator_t will read the stream and set the state to | ||
51 | MU_POP3_NO_STATE when done. */ | ||
52 | break; | ||
53 | |||
54 | /* They must deal with the error first by reopening. */ | ||
55 | case MU_POP3_ERROR: | ||
56 | status = ECANCELED; | ||
57 | break; | ||
58 | |||
59 | default: | ||
60 | status = EINPROGRESS; | ||
61 | } | ||
62 | |||
63 | return status; | ||
64 | } |
... | @@ -21,51 +21,19 @@ | ... | @@ -21,51 +21,19 @@ |
21 | # include <config.h> | 21 | # include <config.h> |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | #include <string.h> | ||
25 | #include <errno.h> | ||
26 | #include <stdio.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <mailutils/sys/pop3.h> | 24 | #include <mailutils/sys/pop3.h> |
29 | 25 | ||
30 | int | 26 | int |
31 | mu_pop3_list_all (mu_pop3_t pop3, mu_iterator_t *piterator) | 27 | mu_pop3_list_all (mu_pop3_t pop3, mu_iterator_t *piterator) |
32 | { | 28 | { |
33 | int status = 0; | 29 | int status = mu_pop3_list_cmd (pop3); |
34 | 30 | ||
35 | if (pop3 == NULL) | 31 | if (status) |
36 | return EINVAL; | 32 | return status; |
37 | if (piterator == NULL) | ||
38 | return MU_ERR_OUT_PTR_NULL; | ||
39 | 33 | ||
40 | switch (pop3->state) | 34 | status = mu_pop3_iterator_create (pop3, piterator); |
41 | { | 35 | MU_POP3_CHECK_ERROR (pop3, status); |
42 | case MU_POP3_NO_STATE: | 36 | pop3->state = MU_POP3_LIST_RX; |
43 | status = mu_pop3_writeline (pop3, "LIST\r\n"); | ||
44 | MU_POP3_CHECK_ERROR (pop3, status); | ||
45 | MU_POP3_FCLR (pop3, MU_POP3_ACK); | ||
46 | pop3->state = MU_POP3_LIST; | ||
47 | |||
48 | case MU_POP3_LIST: | ||
49 | status = mu_pop3_response (pop3, NULL); | ||
50 | MU_POP3_CHECK_EAGAIN (pop3, status); | ||
51 | MU_POP3_CHECK_OK (pop3); | ||
52 | status = mu_pop3_iterator_create (pop3, piterator); | ||
53 | MU_POP3_CHECK_ERROR (pop3, status); | ||
54 | pop3->state = MU_POP3_LIST_RX; | ||
55 | |||
56 | case MU_POP3_LIST_RX: | ||
57 | /* The mu_iterator_t will read the stream and set the state to | ||
58 | MU_POP3_NO_STATE when done. */ | ||
59 | break; | ||
60 | |||
61 | /* They must deal with the error first by reopening. */ | ||
62 | case MU_POP3_ERROR: | ||
63 | status = ECANCELED; | ||
64 | break; | ||
65 | |||
66 | default: | ||
67 | status = EINPROGRESS; | ||
68 | } | ||
69 | 37 | ||
70 | return status; | 38 | return status; |
71 | } | 39 | } | ... | ... |
libproto/pop/pop3_listas.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001, 2004, 2007, 2010 Free Software | ||
3 | Foundation, Inc. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 3 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General | ||
16 | Public License along with this library; if not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301 USA */ | ||
19 | |||
20 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include <mailutils/sys/pop3.h> | ||
25 | |||
26 | int | ||
27 | mu_pop3_list_all_stream (mu_pop3_t pop3, mu_stream_t *pstream) | ||
28 | { | ||
29 | int status = mu_pop3_list_cmd (pop3); | ||
30 | |||
31 | if (status) | ||
32 | return status; | ||
33 | |||
34 | status = mu_pop3_stream_create (pop3, pstream); | ||
35 | MU_POP3_CHECK_ERROR (pop3, status); | ||
36 | pop3->state = MU_POP3_LIST_RX; | ||
37 | |||
38 | return status; | ||
39 | } |
libproto/pop/pop3_rdlist.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2003, 2004, 2005, 2007, 2010 Free Software Foundation, | ||
3 | Inc. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 3 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General | ||
16 | Public License along with this library; if not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301 USA */ | ||
19 | |||
20 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include <string.h> | ||
25 | #include <mailutils/stream.h> | ||
26 | #include <mailutils/list.h> | ||
27 | #include <mailutils/cctype.h> | ||
28 | #include <mailutils/cstr.h> | ||
29 | #include <mailutils/sys/pop3.h> | ||
30 | |||
31 | int | ||
32 | mu_pop3_stream_to_list (mu_pop3_t pop3, mu_stream_t stream, mu_list_t list) | ||
33 | { | ||
34 | int status; | ||
35 | size_t n; | ||
36 | |||
37 | while (mu_stream_getline (stream, &pop3->rdbuf, &pop3->rdsize, &n) == 0 | ||
38 | && n > 0) | ||
39 | { | ||
40 | char *np = strdup (pop3->rdbuf); | ||
41 | if (!np) | ||
42 | { | ||
43 | status = ENOMEM; | ||
44 | break; | ||
45 | } | ||
46 | mu_rtrim_class (np, MU_CTYPE_SPACE); | ||
47 | status = mu_list_append (list, np); | ||
48 | if (status) | ||
49 | break; | ||
50 | } | ||
51 | return status; | ||
52 | } | ||
53 | |||
54 | int | ||
55 | mu_pop3_read_list (mu_pop3_t pop3, mu_list_t list) | ||
56 | { | ||
57 | mu_stream_t stream; | ||
58 | int status = mu_pop3_stream_create (pop3, &stream); | ||
59 | if (status) | ||
60 | return status; | ||
61 | status = mu_pop3_stream_to_list (pop3, stream, list); | ||
62 | mu_stream_destroy (&stream); | ||
63 | return status; | ||
64 | } | ||
65 |
... | @@ -48,12 +48,11 @@ mu_pop3_retr (mu_pop3_t pop3, unsigned int msgno, mu_stream_t *pstream) | ... | @@ -48,12 +48,11 @@ mu_pop3_retr (mu_pop3_t pop3, unsigned int msgno, mu_stream_t *pstream) |
48 | status = mu_pop3_response (pop3, NULL); | 48 | status = mu_pop3_response (pop3, NULL); |
49 | MU_POP3_CHECK_EAGAIN (pop3, status); | 49 | MU_POP3_CHECK_EAGAIN (pop3, status); |
50 | MU_POP3_CHECK_OK (pop3); | 50 | MU_POP3_CHECK_OK (pop3); |
51 | status = mu_pop3_stream_create (pop3, pstream); | ||
52 | MU_POP3_CHECK_ERROR (pop3, status); | ||
51 | pop3->state = MU_POP3_RETR_RX; | 53 | pop3->state = MU_POP3_RETR_RX; |
52 | 54 | ||
53 | case MU_POP3_RETR_RX: | 55 | case MU_POP3_RETR_RX: |
54 | status = mu_pop3_stream_create (pop3, pstream); | ||
55 | MU_POP3_CHECK_ERROR (pop3, status); | ||
56 | pop3->state = MU_POP3_NO_STATE; | ||
57 | break; | 56 | break; |
58 | 57 | ||
59 | /* They must deal with the error first by reopening. */ | 58 | /* They must deal with the error first by reopening. */ | ... | ... |
... | @@ -39,6 +39,7 @@ struct mu_pop3_stream | ... | @@ -39,6 +39,7 @@ struct mu_pop3_stream |
39 | enum pop3_decode_state | 39 | enum pop3_decode_state |
40 | { | 40 | { |
41 | pds_init, /* initial state */ | 41 | pds_init, /* initial state */ |
42 | pds_char, /* Any character excepting [\r\n.] */ | ||
42 | pds_cr, /* prev. char was \r */ | 43 | pds_cr, /* prev. char was \r */ |
43 | pds_crlf, /* 2 prev. char were \r\n */ | 44 | pds_crlf, /* 2 prev. char were \r\n */ |
44 | pds_dot, /* 3 prev. chars were \r\n. */ | 45 | pds_dot, /* 3 prev. chars were \r\n. */ |
... | @@ -56,6 +57,16 @@ newstate (int state, int c) | ... | @@ -56,6 +57,16 @@ newstate (int state, int c) |
56 | { | 57 | { |
57 | case '\r': | 58 | case '\r': |
58 | return pds_cr; | 59 | return pds_cr; |
60 | case '.': | ||
61 | return pds_dot; | ||
62 | } | ||
63 | break; | ||
64 | |||
65 | case pds_char: | ||
66 | switch (c) | ||
67 | { | ||
68 | case '\r': | ||
69 | return pds_cr; | ||
59 | } | 70 | } |
60 | break; | 71 | break; |
61 | 72 | ||
... | @@ -93,7 +104,7 @@ newstate (int state, int c) | ... | @@ -93,7 +104,7 @@ newstate (int state, int c) |
93 | return pds_end; | 104 | return pds_end; |
94 | } | 105 | } |
95 | } | 106 | } |
96 | return pds_init; | 107 | return pds_char; |
97 | } | 108 | } |
98 | 109 | ||
99 | /* Move min(isize,osize) bytes from iptr to optr, replacing each \r\n | 110 | /* Move min(isize,osize) bytes from iptr to optr, replacing each \r\n |
... | @@ -140,7 +151,7 @@ _pop3_decoder (void *xd, | ... | @@ -140,7 +151,7 @@ _pop3_decoder (void *xd, |
140 | if (*iptr == '\n') | 151 | if (*iptr == '\n') |
141 | continue; | 152 | continue; |
142 | } | 153 | } |
143 | else if (c == '.' && *pstate == pds_crlf) | 154 | else if (c == '.' && (*pstate == pds_init || *pstate == pds_crlf)) |
144 | { | 155 | { |
145 | /* Make sure we have two more characters in the buffer */ | 156 | /* Make sure we have two more characters in the buffer */ |
146 | if (i + 2 == isize) | 157 | if (i + 2 == isize) |
... | @@ -164,16 +175,39 @@ _pop3_decoder (void *xd, | ... | @@ -164,16 +175,39 @@ _pop3_decoder (void *xd, |
164 | return mu_filter_ok; | 175 | return mu_filter_ok; |
165 | } | 176 | } |
166 | 177 | ||
178 | static void | ||
179 | _pop3_event_cb (mu_stream_t str, int ev, int flags) | ||
180 | { | ||
181 | if (ev == _MU_STR_EVENT_SET) | ||
182 | { | ||
183 | mu_transport_t trans[2]; | ||
184 | |||
185 | if (mu_stream_ioctl (str, MU_IOCTL_GET_TRANSPORT, trans) == 0) | ||
186 | { | ||
187 | struct mu_pop3_stream *sp = (struct mu_pop3_stream *) trans[0]; | ||
188 | sp->pop3->state = MU_POP3_NO_STATE; | ||
189 | } | ||
190 | } | ||
191 | } | ||
192 | |||
167 | static int | 193 | static int |
168 | mu_pop3_filter_create (mu_stream_t *pstream, mu_stream_t stream) | 194 | mu_pop3_filter_create (mu_stream_t *pstream, mu_stream_t stream) |
169 | { | 195 | { |
196 | int rc; | ||
170 | int *state = malloc (sizeof (*state)); | 197 | int *state = malloc (sizeof (*state)); |
171 | if (!state) | 198 | if (!state) |
172 | return ENOMEM; | 199 | return ENOMEM; |
173 | return mu_filter_stream_create (pstream, stream, | 200 | rc = mu_filter_stream_create (pstream, stream, |
174 | MU_FILTER_DECODE, | 201 | MU_FILTER_DECODE, |
175 | _pop3_decoder, state, | 202 | _pop3_decoder, state, |
176 | MU_STREAM_READ); | 203 | MU_STREAM_READ); |
204 | if (rc == 0) | ||
205 | { | ||
206 | mu_stream_t str = *pstream; | ||
207 | str->event_cb = _pop3_event_cb; | ||
208 | str->event_mask = _MU_STR_EOF; | ||
209 | } | ||
210 | return rc; | ||
177 | } | 211 | } |
178 | 212 | ||
179 | 213 | ||
... | @@ -257,6 +291,7 @@ mu_pop3_stream_create (mu_pop3_t pop3, mu_stream_t *pstream) | ... | @@ -257,6 +291,7 @@ mu_pop3_stream_create (mu_pop3_t pop3, mu_stream_t *pstream) |
257 | sp->stream.readdelim = _mu_pop3_readdelim; | 291 | sp->stream.readdelim = _mu_pop3_readdelim; |
258 | sp->stream.flush = _mu_pop3_flush; | 292 | sp->stream.flush = _mu_pop3_flush; |
259 | sp->stream.wait = _mu_pop3_wait; | 293 | sp->stream.wait = _mu_pop3_wait; |
294 | |||
260 | sp->pop3 = pop3; | 295 | sp->pop3 = pop3; |
261 | sp->done = 0; | 296 | sp->done = 0; |
262 | str = (mu_stream_t) sp; | 297 | str = (mu_stream_t) sp; | ... | ... |
... | @@ -48,12 +48,11 @@ mu_pop3_top (mu_pop3_t pop3, unsigned msgno, unsigned int lines, | ... | @@ -48,12 +48,11 @@ mu_pop3_top (mu_pop3_t pop3, unsigned msgno, unsigned int lines, |
48 | status = mu_pop3_response (pop3, NULL); | 48 | status = mu_pop3_response (pop3, NULL); |
49 | MU_POP3_CHECK_EAGAIN (pop3, status); | 49 | MU_POP3_CHECK_EAGAIN (pop3, status); |
50 | MU_POP3_CHECK_OK (pop3); | 50 | MU_POP3_CHECK_OK (pop3); |
51 | status = mu_pop3_stream_create (pop3, pstream); | ||
52 | MU_POP3_CHECK_ERROR (pop3, status); | ||
51 | pop3->state = MU_POP3_TOP_RX; | 53 | pop3->state = MU_POP3_TOP_RX; |
52 | 54 | ||
53 | case MU_POP3_TOP_RX: | 55 | case MU_POP3_TOP_RX: |
54 | status = mu_pop3_stream_create (pop3, pstream); | ||
55 | MU_POP3_CHECK_ERROR (pop3, status); | ||
56 | pop3->state = MU_POP3_NO_STATE; | ||
57 | break; | 56 | break; |
58 | 57 | ||
59 | /* They must deal with the error first by reopening. */ | 58 | /* They must deal with the error first by reopening. */ | ... | ... |
libproto/pop/pop3_uidl_cmd.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2003, 2004, 2007, 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library 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 GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library; if not, write to the | ||
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
17 | Boston, MA 02110-1301 USA */ | ||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | |||
23 | #include <stdlib.h> | ||
24 | #include <mailutils/sys/pop3.h> | ||
25 | |||
26 | int | ||
27 | mu_pop3_uidl_all_cmd (mu_pop3_t pop3) | ||
28 | { | ||
29 | int status = 0; | ||
30 | |||
31 | if (pop3 == NULL) | ||
32 | return EINVAL; | ||
33 | |||
34 | switch (pop3->state) | ||
35 | { | ||
36 | case MU_POP3_NO_STATE: | ||
37 | status = mu_pop3_writeline (pop3, "UIDL\r\n"); | ||
38 | MU_POP3_CHECK_ERROR (pop3, status); | ||
39 | MU_POP3_FCLR (pop3, MU_POP3_ACK); | ||
40 | pop3->state = MU_POP3_UIDL; | ||
41 | |||
42 | case MU_POP3_UIDL: | ||
43 | status = mu_pop3_response (pop3, NULL); | ||
44 | MU_POP3_CHECK_EAGAIN (pop3, status); | ||
45 | MU_POP3_CHECK_OK (pop3); | ||
46 | pop3->state = MU_POP3_UIDL_RX; | ||
47 | |||
48 | case MU_POP3_UIDL_RX: | ||
49 | break; | ||
50 | |||
51 | /* They must deal with the error first by reopening. */ | ||
52 | case MU_POP3_ERROR: | ||
53 | status = ECANCELED; | ||
54 | break; | ||
55 | |||
56 | default: | ||
57 | status = EINPROGRESS; | ||
58 | } | ||
59 | |||
60 | return status; | ||
61 | } |
... | @@ -20,50 +20,17 @@ | ... | @@ -20,50 +20,17 @@ |
20 | # include <config.h> | 20 | # include <config.h> |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | #include <string.h> | ||
24 | # include <errno.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <mailutils/sys/pop3.h> | 23 | #include <mailutils/sys/pop3.h> |
27 | 24 | ||
28 | int | 25 | int |
29 | mu_pop3_uidl_all (mu_pop3_t pop3, mu_iterator_t *piterator) | 26 | mu_pop3_uidl_all (mu_pop3_t pop3, mu_iterator_t *piterator) |
30 | { | 27 | { |
31 | int status = 0; | 28 | int status = mu_pop3_uidl_all_cmd (pop3); |
32 | 29 | if (status) | |
33 | if (pop3 == NULL) | 30 | return status; |
34 | return EINVAL; | 31 | status = mu_pop3_iterator_create (pop3, piterator); |
35 | if (piterator == NULL) | 32 | MU_POP3_CHECK_ERROR (pop3, status); |
36 | return MU_ERR_OUT_PTR_NULL; | 33 | pop3->state = MU_POP3_UIDL_RX; |
37 | |||
38 | switch (pop3->state) | ||
39 | { | ||
40 | case MU_POP3_NO_STATE: | ||
41 | status = mu_pop3_writeline (pop3, "UIDL\r\n"); | ||
42 | MU_POP3_CHECK_ERROR (pop3, status); | ||
43 | MU_POP3_FCLR (pop3, MU_POP3_ACK); | ||
44 | pop3->state = MU_POP3_UIDL; | ||
45 | |||
46 | case MU_POP3_UIDL: | ||
47 | status = mu_pop3_response (pop3, NULL); | ||
48 | MU_POP3_CHECK_EAGAIN (pop3, status); | ||
49 | MU_POP3_CHECK_OK (pop3); | ||
50 | status = mu_pop3_iterator_create (pop3, piterator); | ||
51 | MU_POP3_CHECK_ERROR (pop3, status); | ||
52 | pop3->state = MU_POP3_UIDL_RX; | ||
53 | |||
54 | case MU_POP3_UIDL_RX: | ||
55 | /* The mu_iterator_t will read the stream and set the state to | ||
56 | MU_POP3_NO_STATE when done. */ | ||
57 | break; | ||
58 | |||
59 | /* They must deal with the error first by reopening. */ | ||
60 | case MU_POP3_ERROR: | ||
61 | status = ECANCELED; | ||
62 | break; | ||
63 | |||
64 | default: | ||
65 | status = EINPROGRESS; | ||
66 | } | ||
67 | 34 | ||
68 | return status; | 35 | return status; |
69 | } | 36 | } | ... | ... |
libproto/pop/pop3_uidlas.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2003, 2004, 2007, 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library 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 GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library; if not, write to the | ||
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
17 | Boston, MA 02110-1301 USA */ | ||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | |||
23 | #include <mailutils/sys/pop3.h> | ||
24 | |||
25 | int | ||
26 | mu_pop3_uidl_all_stream (mu_pop3_t pop3, mu_stream_t *pstream) | ||
27 | { | ||
28 | int status = mu_pop3_uidl_all_cmd (pop3); | ||
29 | if (status) | ||
30 | return status; | ||
31 | status = mu_pop3_stream_create (pop3, pstream); | ||
32 | MU_POP3_CHECK_ERROR (pop3, status); | ||
33 | pop3->state = MU_POP3_UIDL_RX; | ||
34 | |||
35 | return status; | ||
36 | } |
... | @@ -164,7 +164,7 @@ filter_read (mu_stream_t stream, char *buf, size_t size, size_t *pret) | ... | @@ -164,7 +164,7 @@ filter_read (mu_stream_t stream, char *buf, size_t size, size_t *pret) |
164 | return MU_ERR_FAILURE; /* FIXME: special error code? */ | 164 | return MU_ERR_FAILURE; /* FIXME: special error code? */ |
165 | if (iobuf.eof) | 165 | if (iobuf.eof) |
166 | { | 166 | { |
167 | stream->flags |= _MU_STR_EOF; | 167 | _mu_stream_seteof (stream); |
168 | stop = 1; | 168 | stop = 1; |
169 | } | 169 | } |
170 | break; | 170 | break; | ... | ... |
... | @@ -32,6 +32,22 @@ | ... | @@ -32,6 +32,22 @@ |
32 | #include <mailutils/stream.h> | 32 | #include <mailutils/stream.h> |
33 | #include <mailutils/sys/stream.h> | 33 | #include <mailutils/sys/stream.h> |
34 | 34 | ||
35 | static void | ||
36 | _stream_setflag (struct _mu_stream *stream, int flag) | ||
37 | { | ||
38 | if (stream->event_cb && (stream->event_mask & flag)) | ||
39 | stream->event_cb (stream, _MU_STR_EVENT_SET, flag); | ||
40 | stream->flags |= flag; | ||
41 | } | ||
42 | |||
43 | static void | ||
44 | _stream_clrflag (struct _mu_stream *stream, int flag) | ||
45 | { | ||
46 | if (stream->event_cb && (stream->event_mask & flag)) | ||
47 | stream->event_cb (stream, _MU_STR_EVENT_CLR, flag); | ||
48 | stream->flags &= ~flag; | ||
49 | } | ||
50 | |||
35 | int | 51 | int |
36 | mu_stream_seterr (struct _mu_stream *stream, int code, int perm) | 52 | mu_stream_seterr (struct _mu_stream *stream, int code, int perm) |
37 | { | 53 | { |
... | @@ -45,12 +61,23 @@ mu_stream_seterr (struct _mu_stream *stream, int code, int perm) | ... | @@ -45,12 +61,23 @@ mu_stream_seterr (struct _mu_stream *stream, int code, int perm) |
45 | 61 | ||
46 | default: | 62 | default: |
47 | if (perm) | 63 | if (perm) |
48 | stream->flags |= _MU_STR_ERR; | 64 | _stream_setflag (stream, _MU_STR_ERR); |
49 | } | 65 | } |
50 | return code; | 66 | return code; |
51 | } | 67 | } |
52 | 68 | ||
53 | #define _stream_cleareof(s) ((s)->flags &= ~_MU_STR_EOF) | 69 | void |
70 | _mu_stream_cleareof (mu_stream_t str) | ||
71 | { | ||
72 | _stream_clrflag (str, _MU_STR_EOF); | ||
73 | } | ||
74 | |||
75 | void | ||
76 | _mu_stream_seteof (mu_stream_t str) | ||
77 | { | ||
78 | _stream_setflag (str, _MU_STR_EOF); | ||
79 | } | ||
80 | |||
54 | #define _stream_advance_buffer(s,n) ((s)->cur += n, (s)->level -= n) | 81 | #define _stream_advance_buffer(s,n) ((s)->cur += n, (s)->level -= n) |
55 | #define _stream_buffer_offset(s) ((s)->cur - (s)->buffer) | 82 | #define _stream_buffer_offset(s) ((s)->cur - (s)->buffer) |
56 | #define _stream_orig_level(s) ((s)->level + _stream_buffer_offset (s)) | 83 | #define _stream_orig_level(s) ((s)->level + _stream_buffer_offset (s)) |
... | @@ -82,9 +109,13 @@ _stream_fill_buffer (struct _mu_stream *stream) | ... | @@ -82,9 +109,13 @@ _stream_fill_buffer (struct _mu_stream *stream) |
82 | for (n = 0; | 109 | for (n = 0; |
83 | n < stream->bufsize | 110 | n < stream->bufsize |
84 | && (rc = mu_stream_read_unbuffered (stream, | 111 | && (rc = mu_stream_read_unbuffered (stream, |
85 | &c, 1, 0, &rdn)) == 0 | 112 | &c, 1, 0, &rdn)) == 0;) |
86 | && rdn; ) | ||
87 | { | 113 | { |
114 | if (rdn == 0) | ||
115 | { | ||
116 | _stream_setflag (stream, _MU_STR_EOF); | ||
117 | break; | ||
118 | } | ||
88 | stream->buffer[n++] = c; | 119 | stream->buffer[n++] = c; |
89 | if (c == '\n') | 120 | if (c == '\n') |
90 | break; | 121 | break; |
... | @@ -175,7 +206,7 @@ _stream_flush_buffer (struct _mu_stream *stream, int all) | ... | @@ -175,7 +206,7 @@ _stream_flush_buffer (struct _mu_stream *stream, int all) |
175 | } | 206 | } |
176 | else | 207 | else |
177 | { | 208 | { |
178 | stream->flags &= ~_MU_STR_DIRTY; | 209 | _stream_clrflag (stream, _MU_STR_DIRTY); |
179 | stream->level = 0; | 210 | stream->level = 0; |
180 | } | 211 | } |
181 | stream->cur = stream->buffer; | 212 | stream->cur = stream->buffer; |
... | @@ -269,7 +300,7 @@ void | ... | @@ -269,7 +300,7 @@ void |
269 | mu_stream_clearerr (mu_stream_t stream) | 300 | mu_stream_clearerr (mu_stream_t stream) |
270 | { | 301 | { |
271 | stream->last_err = 0; | 302 | stream->last_err = 0; |
272 | stream->flags &= ~_MU_STR_ERR; | 303 | _stream_clrflag (stream, _MU_STR_ERR); |
273 | } | 304 | } |
274 | 305 | ||
275 | int | 306 | int |
... | @@ -327,7 +358,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, | ... | @@ -327,7 +358,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, |
327 | return rc; | 358 | return rc; |
328 | if (rc) | 359 | if (rc) |
329 | return mu_stream_seterr (stream, rc, 1); | 360 | return mu_stream_seterr (stream, rc, 1); |
330 | _stream_cleareof (stream); | 361 | _mu_stream_cleareof (stream); |
331 | } | 362 | } |
332 | 363 | ||
333 | if (pres) | 364 | if (pres) |
... | @@ -469,7 +500,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, | ... | @@ -469,7 +500,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, |
469 | { | 500 | { |
470 | if (rdbytes == 0) | 501 | if (rdbytes == 0) |
471 | { | 502 | { |
472 | stream->flags |= _MU_STR_EOF; | 503 | _stream_setflag (stream, _MU_STR_EOF); |
473 | break; | 504 | break; |
474 | } | 505 | } |
475 | buf += rdbytes; | 506 | buf += rdbytes; |
... | @@ -487,7 +518,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, | ... | @@ -487,7 +518,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, |
487 | if (rc == 0) | 518 | if (rc == 0) |
488 | { | 519 | { |
489 | if (nread == 0) | 520 | if (nread == 0) |
490 | stream->flags |= _MU_STR_EOF; | 521 | _stream_setflag (stream, _MU_STR_EOF); |
491 | stream->bytes_in += nread; | 522 | stream->bytes_in += nread; |
492 | } | 523 | } |
493 | mu_stream_seterr (stream, rc, rc != 0); | 524 | mu_stream_seterr (stream, rc, rc != 0); |
... | @@ -551,7 +582,7 @@ mu_stream_write_unbuffered (mu_stream_t stream, | ... | @@ -551,7 +582,7 @@ mu_stream_write_unbuffered (mu_stream_t stream, |
551 | if (rc == 0) | 582 | if (rc == 0) |
552 | stream->bytes_out += nwritten; | 583 | stream->bytes_out += nwritten; |
553 | } | 584 | } |
554 | stream->flags |= _MU_STR_WRT; | 585 | _stream_setflag (stream, _MU_STR_WRT); |
555 | stream->offset += nwritten; | 586 | stream->offset += nwritten; |
556 | if (pnwritten) | 587 | if (pnwritten) |
557 | *pnwritten = nwritten; | 588 | *pnwritten = nwritten; |
... | @@ -806,7 +837,7 @@ mu_stream_write (mu_stream_t stream, const void *buf, size_t size, | ... | @@ -806,7 +837,7 @@ mu_stream_write (mu_stream_t stream, const void *buf, size_t size, |
806 | nbytes += n; | 837 | nbytes += n; |
807 | bufp += n; | 838 | bufp += n; |
808 | size -= n; | 839 | size -= n; |
809 | stream->flags |= _MU_STR_DIRTY; | 840 | _stream_setflag (stream, _MU_STR_DIRTY); |
810 | } | 841 | } |
811 | if (pnwritten) | 842 | if (pnwritten) |
812 | *pnwritten = nbytes; | 843 | *pnwritten = nbytes; |
... | @@ -835,7 +866,7 @@ mu_stream_flush (mu_stream_t stream) | ... | @@ -835,7 +866,7 @@ mu_stream_flush (mu_stream_t stream) |
835 | return rc; | 866 | return rc; |
836 | if ((stream->flags & _MU_STR_WRT) && stream->flush) | 867 | if ((stream->flags & _MU_STR_WRT) && stream->flush) |
837 | return stream->flush (stream); | 868 | return stream->flush (stream); |
838 | stream->flags &= ~_MU_STR_WRT; | 869 | _stream_clrflag (stream, _MU_STR_WRT); |
839 | return 0; | 870 | return 0; |
840 | } | 871 | } |
841 | 872 | ... | ... |
-
Please register or sign in to post a comment