summaryrefslogtreecommitdiff
path: root/examples/pop3client.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-02-06 15:10:14 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2008-02-06 15:10:14 +0000
commit549f2c21d0e1fcb6837063bd6d83dcc190ff792e (patch)
treedf14410eab61dff4ace2d4c7fff462445f60a09a /examples/pop3client.c
parentf906eddfb71a12cb85fca7f258f5562276cc75b5 (diff)
downloadmailutils-549f2c21d0e1fcb6837063bd6d83dcc190ff792e.tar.gz
mailutils-549f2c21d0e1fcb6837063bd6d83dcc190ff792e.tar.bz2
Implement variable expansions in prompt.
Diffstat (limited to 'examples/pop3client.c')
-rw-r--r--examples/pop3client.c288
1 files changed, 229 insertions, 59 deletions
diff --git a/examples/pop3client.c b/examples/pop3client.c
index 5506de393..7f1d8e6bf 100644
--- a/examples/pop3client.c
+++ b/examples/pop3client.c
@@ -2,7 +2,7 @@
GNU Mailutils pop3 functions. This application interactively allows users
to contact a pop3 server.
- Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation
+ Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@
# include <config.h>
#endif
#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
@@ -42,6 +44,8 @@
#include <mailutils/iterator.h>
#include <mailutils/error.h>
#include <mailutils/errno.h>
+#include <mailutils/vartab.h>
+#include <mailutils/argcv.h>
/* A structure which contains information on the commands this program
can understand. */
@@ -73,6 +77,7 @@ int com_top (char *);
int com_uidl (char *);
int com_user (char *);
int com_verbose (char *);
+int com_prompt (char *);
void initialize_readline (void);
char *stripwhite (char *);
@@ -84,31 +89,29 @@ int valid_argument (const char *, char *);
void sig_int (int);
COMMAND commands[] = {
- {"apop", com_apop, "Authenticate with APOP: APOP user secret"},
- {"capa", com_capa, "List capabilities: capa"},
- {"disconnect", com_disconnect, "Close connection: disconnect"},
- {"dele", com_dele, "Mark message: DELE msgno"},
- {"exit", com_exit, "exit program"},
- {"help", com_help, "Display this text"},
- {"?", com_help, "Synonym for `help'"},
- {"list", com_list, "List messages: LIST [msgno]"},
- {"noop", com_noop, "Send no operation: NOOP"},
- {"pass", com_pass, "Send passwd: PASS [passwd]"},
- {"connect", com_connect, "Open connection: connect hostname [port]"},
- {"quit", com_quit, "Go to Update state : QUIT"},
- {"retr", com_retr, "Dowload message: RETR msgno"},
- {"rset", com_rset, "Unmark all messages: RSET"},
- {"stat", com_stat, "Get the size and count of mailbox : STAT [msgno]"},
- {"top", com_top, "Get the header of message: TOP msgno [lines]"},
- {"uidl", com_uidl, "Get the unique id of message: UIDL [msgno]"},
- {"user", com_user, "send login: USER user"},
- {"verbose", com_verbose, "Enable Protocol tracing: verbose [on|off]"},
- {NULL, NULL, NULL}
+ { "apop", com_apop, "Authenticate with APOP: APOP user secret" },
+ { "capa", com_capa, "List capabilities: capa" },
+ { "disconnect", com_disconnect, "Close connection: disconnect" },
+ { "dele", com_dele, "Mark message: DELE msgno" },
+ { "exit", com_exit, "exit program" },
+ { "help", com_help, "Display this text" },
+ { "?", com_help, "Synonym for `help'" },
+ { "list", com_list, "List messages: LIST [msgno]" },
+ { "noop", com_noop, "Send no operation: NOOP" },
+ { "pass", com_pass, "Send passwd: PASS [passwd]" },
+ { "prompt", com_prompt, "Set command prompt" },
+ { "connect", com_connect, "Open connection: connect hostname [port]" },
+ { "quit", com_quit, "Go to Update state : QUIT" },
+ { "retr", com_retr, "Dowload message: RETR msgno" },
+ { "rset", com_rset, "Unmark all messages: RSET" },
+ { "stat", com_stat, "Get the size and count of mailbox : STAT [msgno]" },
+ { "top", com_top, "Get the header of message: TOP msgno [lines]" },
+ { "uidl", com_uidl, "Get the unique id of message: UIDL [msgno]" },
+ { "user", com_user, "send login: USER user" },
+ { "verbose", com_verbose, "Enable Protocol tracing: verbose [on|off]" },
+ { NULL, NULL, NULL }
};
-/* The name of this program, as taken from argv[0]. */
-char *progname;
-
/* Global handle for pop3. */
mu_pop3_t pop3;
@@ -118,6 +121,69 @@ int verbose;
/* When non-zero, this global means the user is done using this program. */
int done;
+enum pop_session_status
+ {
+ pop_session_disconnected,
+ pop_session_connected,
+ pop_session_logged_in
+ };
+
+enum pop_session_status pop_session_status;
+
+int connect_argc;
+char **connect_argv;
+
+/* Host we are connected to. */
+#define host connect_argv[0]
+int port = 110;
+char *username;
+
+/* Command line prompt */
+#define DEFAULT_PROMPT "pop3> "
+char *prompt;
+
+const char *
+pop_session_str (enum pop_session_status stat)
+{
+ switch (stat)
+ {
+ case pop_session_disconnected:
+ return "disconnected";
+
+ case pop_session_connected:
+ return "connected";
+
+ case pop_session_logged_in:
+ return "logged in";
+ }
+}
+
+char *
+expand_prompt ()
+{
+ mu_vartab_t vtab;
+ char *str;
+
+ if (mu_vartab_create (&vtab))
+ return strdup (prompt);
+ mu_vartab_define (vtab, "user",
+ (pop_session_status == pop_session_logged_in) ?
+ username : "not logged in", 1);
+ mu_vartab_define (vtab, "host",
+ (pop_session_status != pop_session_disconnected) ?
+ host : "not connected", 1);
+ mu_vartab_define (vtab, "program-name", mu_program_name, 1);
+ mu_vartab_define (vtab, "canonical-program-name", "pop3client", 1);
+ mu_vartab_define (vtab, "package", PACKAGE, 1);
+ mu_vartab_define (vtab, "version", PACKAGE_VERSION, 1);
+ mu_vartab_define (vtab, "status", pop_session_str (pop_session_status), 1);
+
+ if (mu_vartab_expand (vtab, prompt, &str))
+ str = strdup (prompt);
+ mu_vartab_destroy (&vtab);
+ return str;
+}
+
char *
dupstr (const char *s)
{
@@ -126,7 +192,7 @@ dupstr (const char *s)
r = malloc (strlen (s) + 1);
if (!r)
{
- fprintf (stderr, "Memory exhausted\n");
+ mu_error ("Memory exhausted");
exit (1);
}
strcpy (r, s);
@@ -159,11 +225,10 @@ initialize_readline ()
in case we want to do some simple parsing. Return the array of matches,
or NULL if there aren't any. */
char **
-pop_completion (char *text, int start, int end)
+pop_completion (char *text, int start, int end MU_ARG_UNUSED)
{
char **matches;
- (void) end;
matches = (char **) NULL;
/* If this word is at the start of the line, then it is a command
@@ -203,7 +268,7 @@ command_generator (const char *text, int state)
}
/* If no names matched, then return NULL. */
- return ((char *) NULL);
+ return NULL;
}
#else
@@ -240,20 +305,17 @@ main (int argc MU_ARG_UNUSED, char **argv)
{
char *line, *s;
- progname = strrchr (argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
+ mu_set_program_name (argv[0]);
+ prompt = strdup (DEFAULT_PROMPT);
initialize_readline (); /* Bind our completer. */
/* Loop reading and executing lines until the user quits. */
while (!done)
{
-
- line = readline ((char *) "pop3> ");
-
+ char *p = expand_prompt ();
+ line = readline (p);
+ free (p);
+
if (!line)
break;
@@ -268,7 +330,7 @@ main (int argc MU_ARG_UNUSED, char **argv)
add_history (s);
status = execute_line (s);
if (status != 0)
- fprintf (stderr, "Error: %s\n", mu_strerror (status));
+ mu_error ("Error: %s", mu_strerror (status));
}
free (line);
@@ -300,8 +362,8 @@ execute_line (char *line)
if (!command)
{
- fprintf (stderr, "%s: No such command for %s.\n", word, progname);
- return (-1);
+ mu_error ("%s: No such command.", word);
+ return 0;
}
/* Get argument to command, if any. */
@@ -378,14 +440,20 @@ com_verbose (char *arg)
int
com_user (char *arg)
{
+ int status;
+
if (!valid_argument ("user", arg))
return EINVAL;
- return mu_pop3_user (pop3, arg);
+ status = mu_pop3_user (pop3, arg);
+ if (status == 0)
+ username = strdup (arg);
+ return status;
}
int
com_apop (char *arg)
{
+ int status;
char *user, *digest;
if (!valid_argument ("apop", arg))
@@ -394,7 +462,13 @@ com_apop (char *arg)
digest = strtok (NULL, " ");
if (!valid_argument ("apop", user) || !valid_argument ("apop", digest))
return EINVAL;
- return mu_pop3_apop (pop3, user, digest);
+ status = mu_pop3_apop (pop3, user, digest);
+ if (status == 0)
+ {
+ username = strdup (user);
+ pop_session_status = pop_session_logged_in;
+ }
+ return status;
}
int
@@ -505,9 +579,32 @@ echo_on (struct termios *stored_settings)
}
int
+com_prompt (char *arg)
+{
+ int quote;
+ size_t size;
+
+ if (!valid_argument ("prompt", arg))
+ return EINVAL;
+
+ free (prompt);
+ size = mu_argcv_quoted_length (arg, &quote);
+ prompt = malloc (size + 1);
+ if (!prompt)
+ {
+ mu_error ("Memory exhausted");
+ exit (1);
+ }
+ mu_argcv_unquote_copy (prompt, arg, size);
+ return 0;
+}
+
+int
com_pass (char *arg)
{
+ int status;
char pass[256];
+
if (!arg || *arg == '\0')
{
struct termios stored_settings;
@@ -522,7 +619,10 @@ com_pass (char *arg)
pass[strlen (pass) - 1] = '\0'; /* nuke the trailing line. */
arg = pass;
}
- return mu_pop3_pass (pop3, arg);
+ status = mu_pop3_pass (pop3, arg);
+ if (status == 0)
+ pop_session_status = pop_session_logged_in;
+ return status;
}
int
@@ -533,7 +633,7 @@ com_stat (char *arg MU_ARG_UNUSED)
count = size = 0;
status = mu_pop3_stat (pop3, &count, &size);
- fprintf (stdout, "Mesgs: %d Size %d\n", count, size);
+ printf ("Mesgs: %d Size %d\n", count, size);
return status;
}
@@ -653,19 +753,74 @@ com_retr (char *arg)
}
int
+get_port (const char *port_str, int *pn)
+{
+ short port_num;
+ long num;
+ char *p;
+
+ num = port_num = strtol (port_str, &p, 0);
+ if (*p == 0)
+ {
+ if (num != port_num)
+ {
+ mu_error ("bad port number: %s", port_str);
+ return 1;
+ }
+ }
+ else
+ {
+ struct servent *sp = getservbyname (port_str, "tcp");
+ if (!sp)
+ {
+ mu_error ("unknown port name");
+ return 1;
+ }
+ port_num = ntohs (sp->s_port);
+ }
+ *pn = port_num;
+ return 0;
+}
+
+int
com_connect (char *arg)
{
- char host[256];
- int port = 110;
int status;
+ int n = 110;
+ int argc;
+ char **argv;
+
if (!valid_argument ("connect", arg))
return 1;
- *host = '\0';
- sscanf (arg, "%256s %d", host, &port);
- if (!valid_argument ("connect", host))
- return EINVAL;
- if (pop3)
+
+ if (mu_argcv_get (arg, NULL, NULL, &argc, &argv))
+ {
+ mu_error ("Cannot parse arguments");
+ return 0;
+ }
+
+ if (!valid_argument ("connect", argv[0]))
+ {
+ mu_argcv_free (argc, argv);
+ return EINVAL;
+ }
+
+ if (argc > 2)
+ {
+ mu_error ("Too many arguments");
+ mu_argcv_free (argc, argv);
+ return 0;
+ }
+
+ if (argc == 2 && get_port (argv[1], &n))
+ {
+ mu_argcv_free (argc, argv);
+ return 0;
+ }
+
+ if (pop_session_status != pop_session_disconnected)
com_disconnect (NULL);
+
status = mu_pop3_create (&pop3);
if (status == 0)
{
@@ -674,8 +829,8 @@ com_connect (char *arg)
if (verbose)
com_verbose ("on");
status =
- mu_tcp_stream_create (&tcp, host, port,
- MU_STREAM_READ | MU_STREAM_NO_CHECK);
+ mu_tcp_stream_create (&tcp, argv[0], n,
+ MU_STREAM_READ | MU_STREAM_NO_CHECK);
if (status == 0)
{
mu_pop3_set_carrier (pop3, tcp);
@@ -688,20 +843,35 @@ com_connect (char *arg)
}
}
- if (status != 0)
- fprintf (stderr, "Failed to create pop3: %s\n", mu_strerror (status));
+ if (status)
+ {
+ mu_error ("Failed to create pop3: %s", mu_strerror (status));
+ mu_argcv_free (argc, argv);
+ }
+ else
+ {
+ connect_argc = argc;
+ connect_argv = argv;
+ port = n;
+ pop_session_status = pop_session_connected;
+ }
+
return status;
}
int
com_disconnect (char *arg MU_ARG_UNUSED)
{
- (void) arg;
if (pop3)
{
mu_pop3_disconnect (pop3);
mu_pop3_destroy (&pop3);
pop3 = NULL;
+
+ mu_argcv_free (connect_argc, connect_argv);
+ connect_argc = 0;
+ connect_argv = NULL;
+ pop_session_status = pop_session_disconnected;
}
return 0;
}
@@ -718,11 +888,11 @@ com_quit (char *arg MU_ARG_UNUSED)
}
else
{
- fprintf (stdout, "Try 'exit' to leave %s\n", progname);
+ printf ("Try 'exit' to leave %s\n", mu_program_name);
}
}
else
- fprintf (stdout, "Try 'exit' to leave %s\n", progname);
+ printf ("Try 'exit' to leave %s\n", mu_program_name);
return status;
}
@@ -745,7 +915,7 @@ valid_argument (const char *caller, char *arg)
{
if (!arg || !*arg)
{
- fprintf (stderr, "%s: Argument required.\n", caller);
+ mu_error ("%s: Argument required", caller);
return 0;
}

Return to:

Send suggestions and report system problems to the System administrator.