dovecot-2.0-sslstream: doveadm who: Added -1 parameter. Added co...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Feb 13 02:55:29 EET 2010
details: http://hg.dovecot.org/dovecot-2.0-sslstream/rev/257bb6f74138
changeset: 10151:257bb6f74138
user: Timo Sirainen <tss at iki.fi>
date: Thu Oct 22 21:15:37 2009 -0400
description:
doveadm who: Added -1 parameter. Added connection's protocol.
diffstat:
1 file changed, 108 insertions(+), 45 deletions(-)
src/doveadm/doveadm-who.c | 153 +++++++++++++++++++++++++++++++--------------
diffs (237 lines):
diff -r 6fcc5a684b83 -r 257bb6f74138 src/doveadm/doveadm-who.c
--- a/src/doveadm/doveadm-who.c Thu Oct 22 21:00:39 2009 -0400
+++ b/src/doveadm/doveadm-who.c Thu Oct 22 21:15:37 2009 -0400
@@ -11,8 +11,17 @@
#include <stdlib.h>
#include <unistd.h>
+struct who_line {
+ const char *username;
+ const char *service;
+ struct ip_addr ip;
+ pid_t pid;
+ unsigned int refcount;
+};
+
struct who_user {
const char *username;
+ const char *service;
ARRAY_DEFINE(ips, struct ip_addr);
ARRAY_DEFINE(pids, pid_t);
unsigned int connection_count;
@@ -32,6 +41,27 @@ struct who_context {
struct hash_table *users; /* username -> who_user */
};
+typedef void who_callback_t(struct who_context *ctx,
+ const struct who_line *line);
+
+static unsigned int who_user_hash(const void *p)
+{
+ const struct who_user *user = p;
+
+ return str_hash(user->username) + str_hash(user->service);
+}
+
+static int who_user_cmp(const void *p1, const void *p2)
+{
+ const struct who_user *user1 = p1, *user2 = p2;
+
+ if (strcmp(user1->username, user2->username) != 0)
+ return 1;
+ if (strcmp(user1->service, user2->service) != 0)
+ return 1;
+ return 0;
+}
+
static bool
who_user_has_ip(const struct who_user *user, const struct ip_addr *ip)
{
@@ -44,48 +74,57 @@ who_user_has_ip(const struct who_user *u
return FALSE;
}
-static void who_line(struct who_context *ctx,
- const char *const *args)
-{
+static void who_parse_line(const char *line, struct who_line *line_r)
+{
+ const char *const *args = t_strsplit(line, "\t");
const char *ident = args[0];
- pid_t pid = strtoul(args[1], NULL, 10);
- unsigned int refcount = atoi(args[2]);
- const char *p, *service, *ip_str, *username;
- struct who_user *user;
- struct ip_addr ip;
+ const char *pid_str = args[1];
+ const char *refcount_str = args[2];
+ const char *p, *ip_str;
+
+ memset(line_r, 0, sizeof(*line_r));
+
+ p = strchr(ident, '/');
+ line_r->pid = strtoul(pid_str, NULL, 10);
+ line_r->service = t_strdup_until(ident, p++);
+ line_r->username = strchr(p, '/');
+ line_r->refcount = atoi(refcount_str);
+ ip_str = t_strdup_until(p, line_r->username++);
+ (void)net_addr2ip(ip_str, &line_r->ip);
+}
+
+static void who_aggregate_line(struct who_context *ctx,
+ const struct who_line *line)
+{
+ struct who_user *user, lookup_user;
const pid_t *ex_pid;
- char *username_dup;
-
- p = strchr(ident, '/');
- service = t_strdup_until(ident, p++);
- username = strchr(p, '/');
- ip_str = t_strdup_until(p, username++);
- if (net_addr2ip(ip_str, &ip) < 0)
- memset(&ip, 0, sizeof(ip));
-
- user = hash_table_lookup(ctx->users, username);
+
+ lookup_user.username = line->username;
+ lookup_user.service = line->service;
+
+ user = hash_table_lookup(ctx->users, &lookup_user);
if (user == NULL) {
user = p_new(ctx->pool, struct who_user, 1);
- username_dup = p_strdup(ctx->pool, username);
- user->username = username_dup;
+ user->username = p_strdup(ctx->pool, line->username);
+ user->service = p_strdup(ctx->pool, line->service);
p_array_init(&user->ips, ctx->pool, 3);
p_array_init(&user->pids, ctx->pool, 8);
- hash_table_insert(ctx->users, username_dup, user);
- }
- user->connection_count += refcount;
-
- if (ip.family != 0 && !who_user_has_ip(user, &ip))
- array_append(&user->ips, &ip, 1);
+ hash_table_insert(ctx->users, user, user);
+ }
+ user->connection_count += line->refcount;
+
+ if (line->ip.family != 0 && !who_user_has_ip(user, &line->ip))
+ array_append(&user->ips, &line->ip, 1);
array_foreach(&user->pids, ex_pid) {
- if (*ex_pid == pid)
- break;
- }
- if (*ex_pid != pid)
- array_append(&user->pids, &pid, 1);
-}
-
-static void who_lookup(struct who_context *ctx)
+ if (*ex_pid == line->pid)
+ break;
+ }
+ if (*ex_pid != line->pid)
+ array_append(&user->pids, &line->pid, 1);
+}
+
+static void who_lookup(struct who_context *ctx, who_callback_t *callback)
{
#define ANVIL_HANDSHAKE "VERSION\tanvil\t1\t0\n"
#define ANVIL_CMD ANVIL_HANDSHAKE"CONNECT-DUMP\n"
@@ -105,7 +144,10 @@ static void who_lookup(struct who_contex
if (*line == '\0')
break;
T_BEGIN {
- who_line(ctx, t_strsplit(line, "\t"));
+ struct who_line who_line;
+
+ who_parse_line(line, &who_line);
+ callback(ctx, &who_line);
} T_END;
}
if (input->stream_errno != 0)
@@ -143,7 +185,7 @@ static void who_print(struct who_context
struct hash_iterate_context *iter;
void *key, *value;
- fprintf(stderr, "%-30s # (ips) (pids)\n", "username");
+ fprintf(stderr, "%-30s # proto (ips) (pids)\n", "username");
iter = hash_table_iterate_init(ctx->users);
while (hash_table_iterate(iter, &key, &value)) {
@@ -155,7 +197,8 @@ static void who_print(struct who_context
if (!who_filter_match(user, &ctx->filter))
continue;
- printf("%-30s %2u ", user->username, user->connection_count);
+ printf("%-30s %2u %-5s ", user->username,
+ user->connection_count, user->service);
printf("(");
array_foreach(&user->ips, ip) T_BEGIN {
@@ -179,21 +222,36 @@ static void who_print(struct who_context
hash_table_iterate_deinit(&iter);
}
+static void who_print_line(struct who_context *ctx ATTR_UNUSED,
+ const struct who_line *line)
+{
+ unsigned int i;
+
+ for (i = 0; i < line->refcount; i++) T_BEGIN {
+ printf("%-30s %-15s %-5s %ld\n", line->username,
+ net_ip2addr(&line->ip), line->service, (long)line->pid);
+ } T_END;
+}
+
static void cmd_who(int argc, char *argv[])
{
struct who_context ctx;
struct ip_addr net_ip;
unsigned int net_bits;
+ bool separate_connections = FALSE;
int c;
memset(&ctx, 0, sizeof(ctx));
ctx.anvil_path = PKG_RUNDIR"/anvil";
ctx.pool = pool_alloconly_create("who users", 10240);
- ctx.users = hash_table_create(default_pool, ctx.pool, 0, str_hash,
- (hash_cmp_callback_t *)strcmp);
-
- while ((c = getopt(argc, argv, "a:")) > 0) {
+ ctx.users = hash_table_create(default_pool, ctx.pool, 0,
+ who_user_hash, who_user_cmp);
+
+ while ((c = getopt(argc, argv, "1a:")) > 0) {
switch (c) {
+ case '1':
+ separate_connections = TRUE;
+ break;
case 'a':
ctx.anvil_path = optarg;
break;
@@ -217,8 +275,13 @@ static void cmd_who(int argc, char *argv
argv++;
}
- who_lookup(&ctx);
- who_print(&ctx);
+ if (!separate_connections) {
+ who_lookup(&ctx, who_aggregate_line);
+ who_print(&ctx);
+ } else {
+ fprintf(stderr, "%-30s %-15s proto pid\n", "username", "ip");
+ who_lookup(&ctx, who_print_line);
+ }
hash_table_destroy(&ctx.users);
pool_unref(&ctx.pool);
@@ -226,5 +289,5 @@ static void cmd_who(int argc, char *argv
struct doveadm_cmd doveadm_cmd_who = {
cmd_who, "who",
- "[-a <anvil socket path>] [<user>] [<ip/bits>]", NULL
-};
+ "[-a <anvil socket path>] [-1] [<user>] [<ip/bits>]", NULL
+};
More information about the dovecot-cvs
mailing list