changeset 6940:414c9d631a81 HEAD

Replaced t_push/t_pop calls with T_FRAME*() macros.
author Timo Sirainen <tss@iki.fi>
date Wed, 05 Dec 2007 17:47:44 +0200
parents c7b42fea5fcc
children 9a050d3a87b1
files src/auth/auth-client-connection.c src/auth/auth-master-connection.c src/auth/auth-request-handler.c src/auth/auth-request.c src/auth/auth-worker-client.c src/auth/auth-worker-server.c src/auth/auth.c src/auth/db-ldap.c src/auth/db-passwd-file.c src/auth/main.c src/auth/mech-digest-md5.c src/auth/passdb-pam.c src/auth/passdb-passwd-file.c src/auth/passdb-sql.c src/auth/userdb-nss.c src/auth/userdb-passwd-file.c src/auth/userdb-static.c src/deliver/deliver.c src/dict/dict-server.c src/imap/client.c src/imap/cmd-list.c src/imap/imap-fetch-body.c src/imap/imap-fetch.c src/imap/imap-status.c src/imap/imap-sync.c src/imap/imap-thread.c src/imap/mail-storage-callbacks.c src/lib-auth/auth-server-connection.c src/lib-auth/auth-server-request.c src/lib-dict/dict-client.c src/lib-dict/dict-sql.c src/lib-dict/dict.c src/lib-imap/imap-bodystructure.c src/lib-imap/imap-match.c src/lib-imap/imap-quote.c src/lib-index/mail-cache-fields.c src/lib-index/mail-cache-lookup.c src/lib-index/mail-cache-transaction.c src/lib-index/mail-cache.c src/lib-index/mail-index-fsck.c src/lib-index/mail-index-map.c src/lib-index/mail-index-sync-ext.c src/lib-index/mail-index-sync-update.c src/lib-index/mail-index-sync.c src/lib-index/mail-index-view-sync.c src/lib-index/mail-transaction-log-append.c src/lib-index/mail-transaction-log-file.c src/lib-index/mail-transaction-log-view.c src/lib-index/mailbox-list-index-sync.c src/lib-index/mailbox-list-index.c src/lib-mail/message-address.c src/lib-mail/message-date.c src/lib-mail/message-decoder.c src/lib-mail/message-parser.c src/lib-mail/message-search.c src/lib-settings/settings.c src/lib-sql/driver-mysql.c src/lib-sql/driver-pgsql.c src/lib-sql/sql-pool.c src/lib-storage/index/cydir/cydir-save.c src/lib-storage/index/cydir/cydir-storage.c src/lib-storage/index/dbox/dbox-file.c src/lib-storage/index/dbox/dbox-index.c src/lib-storage/index/dbox/dbox-storage.c src/lib-storage/index/dbox/dbox-sync-file.c src/lib-storage/index/dbox/dbox-sync-rebuild.c src/lib-storage/index/index-mail-headers.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-search.c src/lib-storage/index/index-sort.c src/lib-storage/index/index-storage.c src/lib-storage/index/maildir/maildir-copy.c src/lib-storage/index/maildir/maildir-keywords.c src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/maildir/maildir-sync.c src/lib-storage/index/maildir/maildir-uidlist.c src/lib-storage/index/maildir/maildir-util.c src/lib-storage/index/mbox/mbox-save.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/index/mbox/mbox-sync-parse.c src/lib-storage/index/mbox/mbox-sync-update.c src/lib-storage/index/mbox/mbox-sync.c src/lib-storage/index/raw/raw-storage.c src/lib-storage/list/index-mailbox-list-sync.c src/lib-storage/list/mailbox-list-fs-iter.c src/lib-storage/list/mailbox-list-maildir-iter.c src/lib-storage/list/mailbox-list-maildir.c src/lib-storage/list/mailbox-list-subscriptions.c src/lib-storage/mail-namespace.c src/lib-storage/mail-storage.c src/lib-storage/mailbox-list.c src/lib-storage/mailbox-tree.c src/lib/compat.c src/lib/failures.c src/lib/file-copy.c src/lib/file-dotlock.c src/lib/imem.c src/lib/mkdir-parents.c src/lib/module-dir.c src/lib/nfs-workarounds.c src/lib/restrict-access.c src/lib/strfuncs.c src/lib/unlink-lockfiles.c src/login-common/client-common.c src/login-common/ssl-proxy-gnutls.c src/master/auth-process.c src/master/dup2-array.c src/master/listener.c src/master/log.c src/master/login-process.c src/master/mail-process.c src/master/main.c src/master/master-settings.c src/plugins/acl/acl-api.c src/plugins/acl/acl-backend-vfile-acllist.c src/plugins/acl/acl-backend-vfile.c src/plugins/acl/acl-backend.c src/plugins/acl/acl-cache.c src/plugins/acl/acl-mailbox-list.c src/plugins/acl/acl-storage.c src/plugins/convert/convert-storage.c src/plugins/expire/expire-plugin.c src/plugins/expire/expire-tool.c src/plugins/fts-squat/squat-trie.c src/plugins/fts-squat/squat-uidlist.c src/plugins/fts/fts-api.c src/plugins/fts/fts-search.c src/plugins/fts/fts-storage.c src/plugins/imap-quota/imap-quota-plugin.c src/plugins/lazy-expunge/lazy-expunge-plugin.c src/plugins/mail-log/mail-log-plugin.c src/plugins/quota/quota-dict.c src/plugins/quota/quota-dirsize.c src/plugins/quota/quota-fs.c src/plugins/quota/quota-maildir.c src/plugins/quota/quota-plugin.c src/plugins/quota/quota.c src/pop3-login/client.c src/pop3/client.c src/pop3/commands.c src/util/idxview.c src/util/listview.c src/util/logview.c
diffstat 144 files changed, 1817 insertions(+), 1613 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/auth-client-connection.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/auth-client-connection.c	Wed Dec 05 17:47:44 2007 +0200
@@ -245,10 +245,10 @@
 
         conn->refcount++;
 	while ((line = i_stream_next_line(conn->input)) != NULL) {
-		t_push();
-		ret = auth_client_handle_line(conn, line);
-		safe_memset(line, 0, strlen(line));
-		t_pop();
+		T_FRAME(
+			ret = auth_client_handle_line(conn, line);
+			safe_memset(line, 0, strlen(line));
+		);
 
 		if (!ret) {
 			struct auth_client_connection *tmp_conn = conn;
--- a/src/auth/auth-master-connection.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/auth-master-connection.c	Wed Dec 05 17:47:44 2007 +0200
@@ -156,6 +156,28 @@
 	return TRUE;
 }
 
+static bool
+auth_master_input_line(struct auth_master_connection *conn, const char *line)
+{
+	if (conn->listener->auth->verbose_debug)
+		i_info("master in: %s", line);
+
+	if (strncmp(line, "REQUEST\t", 8) == 0)
+		return master_input_request(conn, line + 8);
+	else if (strncmp(line, "USER\t", 5) == 0)
+		return master_input_user(conn, line + 5);
+	else if (strncmp(line, "CPID\t", 5) == 0) {
+		i_error("Authentication client trying to connect to "
+			"master socket");
+		return FALSE;
+	} else {
+		/* ignore unknown command */
+		i_error("BUG: Unknown command in master socket: %s",
+			str_sanitize(line, 80));
+		return FALSE;
+	}
+}
+
 static void master_input(struct auth_master_connection *conn)
 {
  	char *line;
@@ -194,26 +216,9 @@
 	}
 
 	while ((line = i_stream_next_line(conn->input)) != NULL) {
-		if (conn->listener->auth->verbose_debug)
-			i_info("master in: %s", line);
-
-		t_push();
-		if (strncmp(line, "REQUEST\t", 8) == 0)
-			ret = master_input_request(conn, line + 8);
-		else if (strncmp(line, "USER\t", 5) == 0)
-			ret = master_input_user(conn, line + 5);
-		else if (strncmp(line, "CPID\t", 5) == 0) {
-			i_error("Authentication client trying to connect to "
-				"master socket");
-			ret = FALSE;
-		} else {
-			/* ignore unknown command */
-			i_error("BUG: Unknown command in master socket: %s",
-				str_sanitize(line, 80));
-			ret = FALSE;
-		}
-		t_pop();
-
+		T_FRAME(
+			ret = auth_master_input_line(conn, line);
+		);
 		if (!ret) {
 			auth_master_connection_destroy(&conn);
 			return;
--- a/src/auth/auth-request-handler.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/auth-request-handler.c	Wed Dec 05 17:47:44 2007 +0200
@@ -155,8 +155,6 @@
 	string_t *str;
 	const char *fields;
 
-	t_push();
-
 	str = t_str_new(128 + MAX_BASE64_ENCODED_SIZE(reply_size));
 	switch (result) {
 	case AUTH_CLIENT_RESULT_CONTINUE:
@@ -224,8 +222,6 @@
 	/* NOTE: request may be destroyed now */
 
         auth_request_handler_unref(&handler);
-
-	t_pop();
 }
 
 static void auth_request_handler_auth_fail(struct auth_request_handler *handler,
--- a/src/auth/auth-request.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/auth-request.c	Wed Dec 05 17:47:44 2007 +0200
@@ -749,13 +749,11 @@
 		old_username = request->user;
 		request->user = user;
 
-		t_push();
 		dest = t_str_new(256);
 		table = auth_request_get_var_expand_table(request,
 						auth_request_str_escape);
 		var_expand(dest, request->auth->username_format, table);
 		user = p_strdup(request->pool, str_c(dest));
-		t_pop();
 
 		request->user = old_username;
 	}
@@ -919,7 +917,6 @@
 		return;
 	}
 
-	t_push();
 	for (net = t_strsplit_spaces(networks, ", "); *net != NULL; net++) {
 		auth_request_log_debug(request, "auth",
 			"allow_nets: Matching for network %s", *net);
@@ -935,7 +932,6 @@
 			break;
 		}
 	}
-	t_pop();
 
 	if (!found) {
 		auth_request_log_info(request, "passdb",
@@ -1084,7 +1080,6 @@
 {
 	const char *key, *value;
 
-	t_push();
 	for (; *fields != NULL; fields++) {
 		if (**fields == '\0')
 			continue;
@@ -1099,7 +1094,6 @@
 		}
 		auth_request_set_field(request, key, value, default_scheme);
 	}
-	t_pop();
 }
 
 void auth_request_init_userdb_reply(struct auth_request *request)
@@ -1117,7 +1111,6 @@
 	if (strcmp(user, request->user) == 0)
 		return;
 
-	t_push();
 	str = t_strdup(auth_stream_reply_export(request->userdb_reply));
 
 	/* reset the reply and add the new username */
@@ -1130,7 +1123,6 @@
 	str = strchr(str, '\t');
 	i_assert(str != NULL);
 	auth_stream_reply_import(request->userdb_reply, str + 1);
-	t_pop();
 }
 
 static void auth_request_set_uidgid_file(struct auth_request *request,
@@ -1139,7 +1131,6 @@
 	string_t *path;
 	struct stat st;
 
-	t_push();
 	path = t_str_new(256);
 	var_expand(path, path_template,
 		   auth_request_get_var_expand_table(request, NULL));
@@ -1152,7 +1143,6 @@
 		auth_stream_reply_add(request->userdb_reply,
 				      "gid", dec2str(st.st_gid));
 	}
-	t_pop();
 }
 
 void auth_request_set_userdb_field(struct auth_request *request,
@@ -1201,13 +1191,11 @@
 		string_t *value;
 		gid_t gid;
 
-		t_push();
 		value = t_str_new(128);
 		for (; *values != NULL; values++) {
 			gid = userdb_parse_gid(request, *values);
 			if (gid == (gid_t)-1) {
 				request->userdb_lookup_failed = TRUE;
-				t_pop();
 				return;
 			}
 
@@ -1217,7 +1205,6 @@
 		}
 		auth_stream_reply_add(request->userdb_reply, name,
 				      str_c(value));
-		t_pop();
 	} else {
 		/* add only one */
 		auth_request_set_userdb_field(request, name, *values);
@@ -1401,9 +1388,9 @@
 		return;
 
 	va_start(va, format);
-	t_push();
-	i_info("%s", get_log_str(auth_request, subsystem, format, va));
-	t_pop();
+	T_FRAME(
+		i_info("%s", get_log_str(auth_request, subsystem, format, va));
+	);
 	va_end(va);
 }
 
@@ -1417,9 +1404,9 @@
 		return;
 
 	va_start(va, format);
-	t_push();
-	i_info("%s", get_log_str(auth_request, subsystem, format, va));
-	t_pop();
+	T_FRAME(
+		i_info("%s", get_log_str(auth_request, subsystem, format, va));
+	);
 	va_end(va);
 }
 
@@ -1430,8 +1417,8 @@
 	va_list va;
 
 	va_start(va, format);
-	t_push();
-	i_error("%s", get_log_str(auth_request, subsystem, format, va));
-	t_pop();
+	T_FRAME(
+		i_error("%s", get_log_str(auth_request, subsystem, format, va));
+	);
 	va_end(va);
 }
--- a/src/auth/auth-worker-client.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/auth-worker-client.c	Wed Dec 05 17:47:44 2007 +0200
@@ -56,7 +56,6 @@
 	auth_request->id = id;
 
 	if (args != NULL) {
-		t_push();
 		for (tmp = t_strsplit(args, "\t"); *tmp != NULL; tmp++) {
 			value = strchr(*tmp, '=');
 			if (value == NULL)
@@ -67,7 +66,6 @@
 
 			(void)auth_request_import(auth_request, key, value);
 		}
-		t_pop();
 	}
 
 	return auth_request;
@@ -443,9 +441,9 @@
 
         client->refcount++;
 	while ((line = i_stream_next_line(client->input)) != NULL) {
-		t_push();
-		ret = auth_worker_handle_line(client, line);
-		t_pop();
+		T_FRAME(
+			ret = auth_worker_handle_line(client, line);
+		);
 
 		if (!ret) {
 			auth_worker_client_destroy(&client);
--- a/src/auth/auth-worker-server.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/auth-worker-server.c	Wed Dec 05 17:47:44 2007 +0200
@@ -122,7 +122,10 @@
 	reply = t_strdup_printf("FAIL\t%d", PASSDB_RESULT_INTERNAL_FAILURE);
 	for (i = 0; i < size; i++) {
 		if (request[i].id != 0) {
-			request[i].callback(request[i].auth_request, reply);
+			T_FRAME(
+				request[i].callback(request[i].auth_request,
+						    reply);
+			);
 			auth_request_unref(&request[i].auth_request);
 		}
 	}
@@ -230,10 +233,11 @@
 		if (line == NULL)
 			continue;
 
-		t_push();
-		id = (unsigned int)strtoul(t_strcut(id_str, '\t'), NULL, 10);
-		request = auth_worker_request_lookup(conn, id);
-		t_pop();
+		T_FRAME(
+			id = (unsigned int)strtoul(t_strcut(id_str, '\t'),
+						   NULL, 10);
+			request = auth_worker_request_lookup(conn, id);
+		);
 
 		if (request != NULL)
 			auth_worker_handle_request(conn, request, line + 1);
--- a/src/auth/auth.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/auth.c	Wed Dec 05 17:47:44 2007 +0200
@@ -33,7 +33,6 @@
 		auth->verbose_debug_passwords;
 	auth->verbose = getenv("VERBOSE") != NULL || auth->verbose_debug;
 
-	t_push();
 	passdb_p = &auth->passdbs;
 	masterdb_p = &auth->masterdbs;
 	auth_passdb = NULL;
@@ -69,9 +68,7 @@
 				"if there are no passdbs");
 		}
 	}
-	t_pop();
 
-	t_push();
 	for (i = 1; ; i++) {
 		driver = getenv(t_strdup_printf("USERDB_%u_DRIVER", i));
 		if (driver == NULL)
@@ -80,7 +77,6 @@
                 args = getenv(t_strdup_printf("USERDB_%u_ARGS", i));
 		userdb_preinit(auth, driver, args);
 	}
-	t_pop();
 
 	if (auth->userdbs == NULL) {
 		/* use a dummy userdb static. */
--- a/src/auth/db-ldap.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/db-ldap.c	Wed Dec 05 17:47:44 2007 +0200
@@ -387,7 +387,9 @@
 				msgid);
 		} else {
 			hash_remove(conn->requests, POINTER_CAST(msgid));
-			request->callback(conn, request, res);
+			T_FRAME(
+				request->callback(conn, request, res);
+			);
 		}
 
 		ldap_msgfree(res);
@@ -678,7 +680,6 @@
 	if (*attrlist == '\0')
 		return;
 
-	t_push();
 	attr = t_strsplit(attrlist, ",");
 	static_data = t_str_new(128);
 
@@ -715,7 +716,6 @@
 		hash_insert(attr_map, "",
 			    p_strdup(conn->pool, str_c(static_data)));
 	}
-	t_pop();
 }
 
 struct var_expand_table *
--- a/src/auth/db-passwd-file.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/db-passwd-file.c	Wed Dec 05 17:47:44 2007 +0200
@@ -158,7 +158,6 @@
 {
 	const char *no_args = NULL;
 	struct istream *input;
-	const char *const *args;
 	const char *line;
 	struct stat st;
 	int fd;
@@ -188,16 +187,16 @@
 		if (*line == '\0' || *line == ':' || *line == '#')
 			continue; /* no username or comment */
 
-		t_push();
-		args = t_strsplit(line, ":");
-		if (args[1] != NULL) {
-			/* at least username+password */
-			passwd_file_add(pw, args[0], args[1], args+2);
-		} else {
-			/* only username */
-			passwd_file_add(pw, args[0], NULL, &no_args);
-		}
-		t_pop();
+		T_FRAME(
+			const char *const *args = t_strsplit(line, ":");
+			if (args[1] != NULL) {
+				/* at least username+password */
+				passwd_file_add(pw, args[0], args[1], args+2);
+			} else {
+				/* only username */
+				passwd_file_add(pw, args[0], NULL, &no_args);
+			}
+		);
 	}
 	i_stream_destroy(&input);
 
@@ -395,8 +394,6 @@
 		const struct var_expand_table *table;
 		string_t *dest;
 
-		t_push();
-
 		table = auth_request_get_var_expand_table(request, path_fix);
 		dest = t_str_new(256);
 		var_expand(dest, db->path, table);
@@ -406,17 +403,13 @@
 			/* doesn't exist yet. create lookup for it. */
 			pw = passwd_file_new(db, str_c(dest));
 		}
-
-		t_pop();
 	}
 
-	t_push();
 	path = t_strdup(pw->path);
 	if (!passwd_file_sync(pw)) {
 		/* pw may be freed now */
 		auth_request_log_info(request, "passwd-file",
 				      "no passwd file: %s", path);
-		t_pop();
 		return NULL;
 	}
 
@@ -432,8 +425,6 @@
 	pu = hash_lookup(pw->users, str_c(username));
 	if (pu == NULL)
                 auth_request_log_info(request, "passwd-file", "unknown user");
-	t_pop();
-
 	return pu;
 }
 
--- a/src/auth/main.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/main.c	Wed Dec 05 17:47:44 2007 +0200
@@ -155,13 +155,10 @@
 	unsigned int i;
 
 	for (i = 1;; i++) {
-		t_push();
 		client_path = getenv(t_strdup_printf("AUTH_%u", i));
 		master_path = getenv(t_strdup_printf("AUTH_%u_MASTER", i));
-		if (client_path == NULL && master_path == NULL) {
-			t_pop();
+		if (client_path == NULL && master_path == NULL)
 			break;
-		}
 
 		str = t_strdup_printf("AUTH_%u", i);
 		client_fd = create_unix_listener(str, 64);
@@ -177,7 +174,6 @@
 			auth_master_listener_add(listener, client_fd,
 						 client_path, LISTENER_CLIENT);
 		}
-		t_pop();
 	}
 }
 
@@ -208,7 +204,6 @@
 	modules = module_dir_load(AUTH_MODULE_DIR, NULL, TRUE, version);
 	module_dir_init(modules);
 	auth = auth_preinit();
-
 	auth_master_listeners_init();
 	if (!worker)
 		add_extra_listeners();
@@ -234,7 +229,7 @@
 	lib_signals_ignore(SIGUSR2, TRUE);
 
 	mech_init();
-        password_schemes_init();
+	password_schemes_init();
 	auth_init(auth);
 	auth_request_handler_init();
 
@@ -326,9 +321,10 @@
 		argv++;
 	}
 
-	drop_privileges();
-
-	main_init(foreground);
+	T_FRAME(
+		drop_privileges();
+		main_init(foreground);
+	);
         io_loop_run(ioloop);
 	main_deinit();
 
--- a/src/auth/mech-digest-md5.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/mech-digest-md5.c	Wed Dec 05 17:47:44 2007 +0200
@@ -78,17 +78,14 @@
 	/* get 128bit of random data as nonce */
 	random_fill(nonce, sizeof(nonce));
 
-	t_push();
 	buf = buffer_create_static_hard(pool_datastack_create(),
 				MAX_BASE64_ENCODED_SIZE(sizeof(nonce))+1);
 
 	base64_encode(nonce, sizeof(nonce), buf);
 	buffer_append_c(buf, '\0');
 	request->nonce = p_strdup(request->pool, buffer_get_data(buf, NULL));
-	t_pop();
 
 	str = t_str_new(256);
-
 	if (*auth->auth_realms == NULL) {
 		/* If no realms are given, at least Cyrus SASL client defaults
 		   to destination host name */
--- a/src/auth/passdb-pam.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/passdb-pam.c	Wed Dec 05 17:47:44 2007 +0200
@@ -280,7 +280,6 @@
 	module->module.default_pass_scheme = "PLAIN";
 	module->module.blocking = TRUE;
 
-	t_push();
 	t_args = t_strsplit_spaces(args, " ");
 	for(i = 0; t_args[i] != NULL; i++) {
 		/* -session for backwards compatibility */
@@ -307,8 +306,6 @@
 			i_fatal("Unexpected PAM parameter: %s", t_args[i]);
 		}
 	}
-	t_pop();
-
 	return &module->module;
 }
 
--- a/src/auth/passdb-passwd-file.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/passdb-passwd-file.c	Wed Dec 05 17:47:44 2007 +0200
@@ -40,7 +40,6 @@
         }
 
 	if (pu->extra_fields != NULL) {
-		t_push();
 		str = t_str_new(512);
 		table = auth_request_get_var_expand_table(request, NULL);
 
@@ -57,7 +56,6 @@
 			}
 			auth_request_set_field(request, key, value, NULL);
 		}
-		t_pop();
 	}
 }
 
@@ -121,7 +119,6 @@
 		if (*args == '/')
 			break;
 
-		t_push();
 		key = args;
 		value = strchr(key, '=');
 		if (value == NULL) {
@@ -142,7 +139,6 @@
 			scheme = p_strdup(auth_passdb->auth->pool, value);
 		else if (strcmp(key, "username_format") == 0)
 			format = p_strdup(auth_passdb->auth->pool, value);
-		t_pop();
 	}
 
 	module = p_new(auth_passdb->auth->pool,
--- a/src/auth/passdb-sql.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/passdb-sql.c	Wed Dec 05 17:47:44 2007 +0200
@@ -206,8 +206,6 @@
 	struct passdb_sql_request *sql_request;
 	string_t *query;
 
-	t_push();
-
 	request->mech_password = p_strdup(request->pool, new_credentials);
 
 	query = t_str_new(512);
@@ -223,8 +221,6 @@
 	sql_update(transaction, str_c(query));
 	sql_transaction_commit(&transaction,
 			       sql_set_credentials_callback, sql_request);
-
-	t_pop();
 	return 0;
 }
 
--- a/src/auth/userdb-nss.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/userdb-nss.c	Wed Dec 05 17:47:44 2007 +0200
@@ -110,7 +110,6 @@
 	module->bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
 	module->buf = p_malloc(pool, module->bufsize);
 
-	t_push();
 	for (tmp = t_strsplit(args, " "); *tmp != NULL; tmp++) {
 		if (strcmp(*tmp, "blocking=yes") == 0)
 			module->module.blocking = TRUE;
@@ -119,7 +118,6 @@
 		else
 			i_fatal("userdb nss: Unknown parameter: %s", *tmp);
 	}
-	t_pop();
 
 	if (module->nss_module.name == NULL)
 		i_fatal("userdb nss: Missing service");
--- a/src/auth/userdb-passwd-file.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/userdb-passwd-file.c	Wed Dec 05 17:47:44 2007 +0200
@@ -51,7 +51,6 @@
 		auth_request_set_userdb_field(auth_request, "home", pu->home);
 
 	if (pu->extra_fields != NULL) {
-		t_push();
 		str = t_str_new(512);
 		table = auth_request_get_var_expand_table(auth_request, NULL);
 
@@ -69,7 +68,6 @@
 			}
 			auth_request_set_userdb_field(auth_request, key, value);
 		}
-		t_pop();
 	}
 
 	callback(USERDB_RESULT_OK, auth_request);
--- a/src/auth/userdb-static.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/auth/userdb-static.c	Wed Dec 05 17:47:44 2007 +0200
@@ -23,7 +23,6 @@
 	uid_t uid;
 	gid_t gid;
 
-	t_push();
 	tmpl = p_new(pool, struct userdb_static_template, 1);
 
 	tmp = t_strsplit_spaces(args, " ");
@@ -62,7 +61,6 @@
 		array_append(&tmpl->args, &key, 1);
 		array_append(&tmpl->args, &value, 1);
 	}
-	t_pop();
 	return tmpl;
 }
 
@@ -107,7 +105,6 @@
 	const char *const *args, *value;
 	unsigned int i, count;
 
-	t_push();
 	str = t_str_new(256);
 	table = auth_request_get_var_expand_table(auth_request, NULL);
 
@@ -123,7 +120,6 @@
 		}
 		auth_request_set_userdb_field(auth_request, args[i], value);
 	}
-	t_pop();
 }
 
 #ifdef USERDB_STATIC
--- a/src/deliver/deliver.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/deliver/deliver.c	Wed Dec 05 17:47:44 2007 +0200
@@ -237,7 +237,6 @@
 	if (fd < 0)
 		i_fatal_status(EX_CONFIG, "open(%s) failed: %m", path);
 
-	t_push();
 	input = i_stream_create_fd(fd, 1024, TRUE);
 	while ((line = i_stream_read_next_line(input)) != NULL) {
 		/* @UNSAFE: line is modified */
@@ -373,7 +372,6 @@
 		}
 	}
 	i_stream_unref(&input);
-	t_pop();
 }
 
 static const struct var_expand_table *
@@ -756,7 +754,9 @@
 			"destination user parameter (-d user) not given");
 	}
 
-	config_file_init(config_path);
+	T_FRAME(
+		config_file_init(config_path);
+	);
 	open_logfile(user);
 
 	if (getenv("MAIL_DEBUG") != NULL)
--- a/src/dict/dict-server.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/dict/dict-server.c	Wed Dec 05 17:47:44 2007 +0200
@@ -77,7 +77,7 @@
 {
 	struct dict_iterate_context *ctx;
 	const char *const *args;
-	const char *reply, *key, *value;
+	const char *key, *value;
 	int ret;
 
 	args = t_strsplit(line, "\t");
@@ -92,10 +92,12 @@
 	while ((ret = dict_iterate(ctx, &key, &value)) > 0) {
 		/* FIXME: we don't want to keep blocking here. set a flush
 		   function and send the replies there when buffer gets full */
-		t_push();
-		reply = t_strdup_printf("%s\t%s\n", key, value);
-		o_stream_send_str(conn->output, reply);
-		t_pop();
+		T_FRAME(
+			const char *reply;
+
+			reply = t_strdup_printf("%s\t%s\n", key, value);
+			o_stream_send_str(conn->output, reply);
+		);
 	}
 	dict_iterate_deinit(ctx);
 
@@ -397,9 +399,9 @@
 		ret = 0;
 		for (i = 0; cmds[i].cmd != '\0'; i++) {
 			if (cmds[i].cmd == *line) {
-				t_push();
-				ret = cmds[i].func(conn, line + 1);
-				t_pop();
+				T_FRAME(
+					ret = cmds[i].func(conn, line + 1);
+				);
 				break;
 			}
 		}
--- a/src/imap/client.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/imap/client.c	Wed Dec 05 17:47:44 2007 +0200
@@ -629,9 +629,9 @@
 	o_stream_cork(client->output);
 	client->handling_input = TRUE;
 	do {
-		t_push();
-		ret = client_handle_next_command(client);
-		t_pop();
+		T_FRAME(
+			ret = client_handle_next_command(client);
+		);
 	} while (ret && !client->disconnected);
 	client->handling_input = FALSE;
 	o_stream_uncork(client->output);
--- a/src/imap/cmd-list.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/imap/cmd-list.c	Wed Dec 05 17:47:44 2007 +0200
@@ -299,7 +299,6 @@
 	const char *name;
 	int ret = 0;
 
-	t_push();
 	str = t_str_new(256);
 	name_str = t_str_new(256);
 	while ((info = mailbox_list_iter_next(ctx->list_iter)) != NULL) {
@@ -361,12 +360,14 @@
 		mailbox_childinfo2str(ctx, str, flags);
 
 		if (ctx->status_items != 0 &&
-		    (flags & (MAILBOX_NONEXISTENT | MAILBOX_NOSELECT)) == 0)
-			list_send_status(ctx, name);
+		    (flags & (MAILBOX_NONEXISTENT | MAILBOX_NOSELECT)) == 0) {
+			T_FRAME(
+				list_send_status(ctx, name);
+			);
+		}
 
 		if (client_send_line(ctx->cmd->client, str_c(str)) == 0) {
 			/* buffer is full, continue later */
-			t_pop();
 			return 0;
 		}
 	}
@@ -374,7 +375,6 @@
 	if (mailbox_list_iter_deinit(&ctx->list_iter) < 0)
 		ret = -1;
 
-	t_pop();
 	return ret < 0 ? -1 : 1;
 }
 
@@ -495,13 +495,11 @@
 	   that matches INBOX, the INBOX casing is on. */
 	ret = IMAP_MATCH_NO;
 	for (pat = ctx->patterns; *pat != NULL; pat++) {
-		t_push();
 		inbox_glob =
 			imap_match_init(pool_datastack_create(),
 					t_strconcat(ctx->ref, *pat, NULL),
 					TRUE, ctx->ns->sep);
 		match = imap_match(inbox_glob, "INBOX");
-		t_pop();
 
 		if (match == IMAP_MATCH_YES)
 			return IMAP_MATCH_YES;
@@ -673,14 +671,17 @@
 	}
 	for (; ctx->ns != NULL; ctx->ns = ctx->ns->next) {
 		if (ctx->list_iter == NULL) {
-			t_push();
-			list_namespace_init(ctx);
-			t_pop();
+			T_FRAME(
+				list_namespace_init(ctx);
+			);
 			if (ctx->list_iter == NULL)
 				continue;
 		}
 
-		if ((ret = list_namespace_mailboxes(ctx)) < 0) {
+		T_FRAME(
+			ret = list_namespace_mailboxes(ctx);
+		);
+		if (ret < 0) {
 			client_send_list_error(cmd, ctx->ns->list);
 			return TRUE;
 		}
--- a/src/imap/imap-fetch-body.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/imap/imap-fetch-body.c	Wed Dec 05 17:47:44 2007 +0200
@@ -623,17 +623,14 @@
 		return TRUE;
 	}
 
-	t_push();
-
 	for (arr = body->fields; *arr != NULL; arr++) {
 		char *hdr = p_strdup(ctx->cmd->pool, *arr);
 		buffer_append(ctx->all_headers_buf, &hdr, sizeof(hdr));
 	}
 
 	body->header_ctx = mailbox_header_lookup_init(ctx->box, body->fields);
-	imap_fetch_add_handler(ctx, FALSE, TRUE, name, "NIL",
+	imap_fetch_add_handler(ctx, FALSE, TRUE, name, "NIL",
 			       fetch_body_header_fields, body);
-	t_pop();
 	return TRUE;
 }
 
--- a/src/imap/imap-fetch.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/imap/imap-fetch.c	Wed Dec 05 17:47:44 2007 +0200
@@ -310,11 +310,13 @@
 					return -1;
 			}
 
-			t_push();
-			ret = handlers[ctx->cur_handler].
-				handler(ctx, ctx->cur_mail,
-					handlers[ctx->cur_handler].context);
-			t_pop();
+			T_FRAME(
+				const struct imap_fetch_context_handler *h =
+					&handlers[ctx->cur_handler];
+
+				ret = h->handler(ctx, ctx->cur_mail,
+						 h->context);
+			);
 
 			if (ret == 0) {
 				if (!ctx->line_partial) {
--- a/src/imap/imap-status.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/imap/imap-status.c	Wed Dec 05 17:47:44 2007 +0200
@@ -76,7 +76,6 @@
 {
 	string_t *str;
 
-	t_push();
 	str = t_str_new(128);
 	str_append(str, "* STATUS ");
         imap_quote_append_string(str, mailbox, FALSE);
@@ -98,5 +97,4 @@
 	str_append_c(str, ')');
 
 	client_send_line(client, str_c(str));
-	t_pop();
 }
--- a/src/imap/imap-sync.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/imap/imap-sync.c	Wed Dec 05 17:47:44 2007 +0200
@@ -73,8 +73,6 @@
 
 	ret = mailbox_transaction_commit(&ctx->t);
 
-	t_push();
-
 	if (status.uidvalidity != ctx->client->uidvalidity) {
 		/* most clients would get confused by this. disconnect them. */
 		client_disconnect_with_error(ctx->client,
@@ -95,7 +93,6 @@
 		}
 	}
 
-	t_pop();
 	i_free(ctx);
 	return ret;
 }
@@ -107,9 +104,7 @@
 	string_t *str;
 	int ret = 1;
 
-	t_push();
 	str = t_str_new(256);
-
 	for (;;) {
 		if (ctx->seq == 0) {
 			/* get next one */
@@ -187,7 +182,6 @@
 
 		ctx->seq = 0;
 	}
-	t_pop();
 	return ret;
 }
 
--- a/src/imap/imap-thread.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/imap/imap-thread.c	Wed Dec 05 17:47:44 2007 +0200
@@ -139,8 +139,11 @@
 	headers_ctx = mailbox_header_lookup_init(client->mailbox,
 						 wanted_headers);
 	mail = mail_alloc(ctx->t, MAIL_FETCH_DATE, headers_ctx);
-	while (mailbox_search_next(ctx->search_ctx, mail) > 0)
-		mail_thread_input(ctx, mail);
+	while (mailbox_search_next(ctx->search_ctx, mail) > 0) {
+		T_FRAME(
+			mail_thread_input(ctx, mail);
+		);
+	}
 
 	mail_free(&mail);
 
@@ -444,8 +447,6 @@
 	struct node *node;
 	time_t sent_date;
 
-	t_push();
-
 	if (mail_get_date(mail, &sent_date, NULL) < 0)
 		sent_date = 0;
 
@@ -473,8 +474,6 @@
 				unlink_child(ctx, node, TRUE);
 		}
 	}
-
-	t_pop();
 }
 
 static struct node *find_last_child(struct node *node)
@@ -698,11 +697,12 @@
 
 		if (seq != 0) {
 			mail_set_seq(ctx->mail, seq);
-			t_push();
 			if (mail_get_first_header(ctx->mail, "subject",
-						  &subject) > 0)
-				add_base_subject(ctx, subject, node);
-			t_pop();
+						  &subject) > 0) {
+				T_FRAME(
+					add_base_subject(ctx, subject, node);
+				);
+			}
 		}
 	}
 
@@ -971,7 +971,7 @@
 	merge_subject_threads(ctx);
 
 	/* (6) Sort and send replies */
-	t_push();
-	send_roots(ctx);
-	t_pop();
+	T_FRAME(
+		send_roots(ctx);
+	);
 }
--- a/src/imap/mail-storage-callbacks.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/imap/mail-storage-callbacks.c	Wed Dec 05 17:47:44 2007 +0200
@@ -9,32 +9,34 @@
 		      const char *text, void *context)
 {
 	struct client *client = context;
-	const char *str;
 
 	if (o_stream_get_buffer_used_size(client->output) != 0)
 		return;
 
-	t_push();
-	str = t_strconcat("* OK ", text, "\r\n", NULL);
-	o_stream_send_str(client->output, str);
-        o_stream_flush(client->output);
-        t_pop();
+	T_FRAME(
+		const char *str;
+
+		str = t_strconcat("* OK ", text, "\r\n", NULL);
+		o_stream_send_str(client->output, str);
+		o_stream_flush(client->output);
+	);
 }
 
 static void notify_no(struct mailbox *mailbox ATTR_UNUSED,
 		      const char *text, void *context)
 {
 	struct client *client = context;
-	const char *str;
 
 	if (o_stream_get_buffer_used_size(client->output) != 0)
 		return;
 
-	t_push();
-	str = t_strconcat("* NO ", text, "\r\n", NULL);
-	o_stream_send_str(client->output, str);
-        o_stream_flush(client->output);
-	t_pop();
+	T_FRAME(
+		const char *str;
+
+		str = t_strconcat("* NO ", text, "\r\n", NULL);
+		o_stream_send_str(client->output, str);
+		o_stream_flush(client->output);
+	);
 }
 
 struct mail_storage_callbacks mail_storage_callbacks = {
--- a/src/lib-auth/auth-server-connection.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-auth/auth-server-connection.c	Wed Dec 05 17:47:44 2007 +0200
@@ -129,6 +129,29 @@
 	return TRUE;
 }
 
+static bool
+auth_client_input_line(struct auth_server_connection *conn, const char *line)
+{
+	if (strncmp(line, "OK\t", 3) == 0)
+		return auth_client_input_ok(conn, line + 3);
+	else if (strncmp(line, "CONT\t", 5) == 0)
+		return auth_client_input_cont(conn, line + 5);
+	else if (strncmp(line, "FAIL\t", 5) == 0)
+		return auth_client_input_fail(conn, line + 5);
+	else if (strncmp(line, "MECH\t", 5) == 0)
+		return auth_client_input_mech(conn, line + 5);
+	else if (strncmp(line, "SPID\t", 5) == 0)
+		return auth_client_input_spid(conn, line + 5);
+	else if (strncmp(line, "CUID\t", 5) == 0)
+		return auth_client_input_cuid(conn, line + 5);
+	else if (strcmp(line, "DONE") == 0)
+		return auth_client_input_done(conn);
+	else {
+		/* ignore unknown command */
+		return TRUE;
+	}
+}
+
 static void auth_client_input(struct auth_server_connection *conn)
 {
 	const char *line;
@@ -168,26 +191,9 @@
 
 	conn->refcount++;
 	while ((line = i_stream_next_line(conn->input)) != NULL) {
-		t_push();
-		if (strncmp(line, "OK\t", 3) == 0)
-			ret = auth_client_input_ok(conn, line + 3);
-		else if (strncmp(line, "CONT\t", 5) == 0)
-			ret = auth_client_input_cont(conn, line + 5);
-        	else if (strncmp(line, "FAIL\t", 5) == 0)
-			ret = auth_client_input_fail(conn, line + 5);
-		else if (strncmp(line, "MECH\t", 5) == 0)
-			ret = auth_client_input_mech(conn, line + 5);
-		else if (strncmp(line, "SPID\t", 5) == 0)
-			ret = auth_client_input_spid(conn, line + 5);
-		else if (strncmp(line, "CUID\t", 5) == 0)
-			ret = auth_client_input_cuid(conn, line + 5);
-		else if (strcmp(line, "DONE") == 0)
-			ret = auth_client_input_done(conn);
-		else {
-			/* ignore unknown command */
-			ret = TRUE;
-		}
-		t_pop();
+		T_FRAME(
+			ret = auth_client_input_line(conn, line);
+		);
 
 		if (!ret) {
 			auth_server_connection_destroy(&conn, FALSE);
--- a/src/lib-auth/auth-server-request.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-auth/auth-server-request.c	Wed Dec 05 17:47:44 2007 +0200
@@ -89,9 +89,7 @@
 					const char **error_r)
 {
 	string_t *str;
-	ssize_t ret;
 
-	t_push();
 	str = t_str_new(512);
 
 	str_printfa(str, "AUTH\t%u\t%s\tservice=%s",
@@ -103,7 +101,6 @@
 
 	if (request->cert_username != NULL) {
 		if (!is_valid_string(request->cert_username)) {
-			t_pop();
 			*error_r = "Invalid username in SSL certificate";
 			return -1;
 		}
@@ -119,7 +116,6 @@
 		str_printfa(str, "\trport=%u", request->remote_port);
 	if (request->initial_resp_base64 != NULL) {
 		/*if (!is_valid_string(request->initial_resp_base64)) {
-			t_pop();
 			*error_r = "Invalid base64 data in initial response";
 			return -1;
 		}*/
@@ -127,10 +123,7 @@
 	}
 	str_append_c(str, '\n');
 
-	ret = o_stream_send(conn->output, str_data(str), str_len(str));
-	t_pop();
-
-	if (ret < 0) {
+	if (o_stream_send(conn->output, str_data(str), str_len(str)) < 0) {
 		errno = conn->output->stream_errno;
 		i_warning("Error sending request to auth server: %m");
 		auth_server_connection_destroy(&conn, TRUE);
@@ -276,8 +269,11 @@
 				    request);
 			request->next_conn = next;
 
-			(void)auth_server_send_new_request(next, request,
-							   &error);
+			T_FRAME(
+				(void)auth_server_send_new_request(next,
+								   request,
+								   &error);
+			);
 			return TRUE;
 		}
 	}
@@ -367,12 +363,15 @@
 	request->callback = callback;
 	request->context = context;
 
-	if (auth_server_send_new_request(conn, request, error_r) == 0)
-		hash_insert(conn->requests, POINTER_CAST(request->id), request);
-	else {
-		auth_client_request_free(request);
-		request = NULL;
-	}
+	T_FRAME(
+		if (auth_server_send_new_request(conn, request, error_r) == 0) {
+			hash_insert(conn->requests, POINTER_CAST(request->id),
+				    request);
+		} else {
+			auth_client_request_free(request);
+			request = NULL;
+		}
+	);
 	return request;
 }
 
--- a/src/lib-dict/dict-client.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-dict/dict-client.c	Wed Dec 05 17:47:44 2007 +0200
@@ -163,18 +163,20 @@
 client_dict_transaction_send_begin(struct client_dict_transaction_context *ctx)
 {
 	struct client_dict *dict = (struct client_dict *)ctx->ctx.dict;
-	const char *query;
 
 	if (ctx->failed)
 		return -1;
 
-	t_push();
-	query = t_strdup_printf("%c%u\n", DICT_PROTOCOL_CMD_BEGIN, ctx->id);
-	if (client_dict_send_query(dict, query) < 0)
-		ctx->failed = TRUE;
-	else
-		ctx->connect_counter = dict->connect_counter;
-	t_pop();
+	T_FRAME(
+		const char *query;
+
+		query = t_strdup_printf("%c%u\n", DICT_PROTOCOL_CMD_BEGIN,
+					ctx->id);
+		if (client_dict_send_query(dict, query) < 0)
+			ctx->failed = TRUE;
+		else
+			ctx->connect_counter = dict->connect_counter;
+	);
 
 	return ctx->failed ? -1 : 0;
 }
@@ -252,7 +254,6 @@
 	dict->output = o_stream_create_fd(dict->fd, 4096, FALSE);
 	dict->transaction_id_counter = 0;
 
-	t_push();
 	query = t_strdup_printf("%c%u\t%u\t%d\t%s\t%s\n",
 				DICT_PROTOCOL_CMD_HELLO,
 				DICT_CLIENT_PROTOCOL_MAJOR_VERSION,
@@ -260,10 +261,8 @@
 				dict->value_type, dict->username, dict->uri);
 	if (client_dict_send_query(dict, query) < 0) {
 		client_dict_disconnect(dict);
-		t_pop();
 		return -1;
 	}
-	t_pop();
 
 	dict->handshaked = TRUE;
 	return 0;
@@ -318,7 +317,9 @@
 	}
 	dict->uri = p_strdup(pool, dest_uri + 1);
 
-        (void)client_dict_connect(dict);
+	T_FRAME(
+		(void)client_dict_connect(dict);
+	);
 	return &dict->dict;
 }
 
@@ -335,18 +336,20 @@
 {
 	struct client_dict *dict = (struct client_dict *)_dict;
 	const char *line;
+	int ret;
 
 	if (dict->fd == -1)
 		return -1;
 
-	t_push();
-	line = t_strdup_printf("%c%s\n", DICT_PROTOCOL_CMD_LOOKUP,
-			       dict_client_escape(key));
-	if (client_dict_send_query(dict, line) < 0) {
-		t_pop();
+	T_FRAME(
+		const char *query;
+
+		query = t_strdup_printf("%c%s\n", DICT_PROTOCOL_CMD_LOOKUP,
+					dict_client_escape(key));
+		ret = client_dict_send_query(dict, query);
+	);
+	if (ret < 0)
 		return -1;
-	}
-	t_pop();
 
 	/* read reply */
 	line = client_dict_read_line(dict);
@@ -368,7 +371,6 @@
 {
 	struct client_dict *dict = (struct client_dict *)_dict;
         struct client_dict_iterate_context *ctx;
-	const char *query;
 
 	if (dict->in_iteration)
 		i_panic("dict-client: Only one iteration supported");
@@ -378,13 +380,14 @@
 	ctx->ctx.dict = _dict;
 	ctx->pool = pool_alloconly_create("client dict iteration", 512);
 
-	t_push();
-	query = t_strdup_printf("%c%d\t%s\n", DICT_PROTOCOL_CMD_ITERATE,
-				flags, dict_client_escape(path));
-	if (client_dict_send_query(dict, query) < 0)
-		ctx->failed = TRUE;
-	t_pop();
+	T_FRAME(
+		const char *query;
 
+		query = t_strdup_printf("%c%d\t%s\n", DICT_PROTOCOL_CMD_ITERATE,
+					flags, dict_client_escape(path));
+		if (client_dict_send_query(dict, query) < 0)
+			ctx->failed = TRUE;
+	);
 	return &ctx->ctx;
 }
 
@@ -454,11 +457,11 @@
 	struct client_dict_transaction_context *ctx =
 		(struct client_dict_transaction_context *)_ctx;
 	struct client_dict *dict = (struct client_dict *)_ctx->dict;
-	const char *query, *line;
 	int ret = ctx->failed ? -1 : 0;
 
-	if (ctx->sent_begin) {
-		t_push();
+	if (ctx->sent_begin) T_FRAME_BEGIN {
+		const char *query, *line;
+
 		query = t_strdup_printf("%c%u\n", !ctx->failed ?
 					DICT_PROTOCOL_CMD_COMMIT :
 					DICT_PROTOCOL_CMD_ROLLBACK, ctx->id);
@@ -470,8 +473,7 @@
 			if (line == NULL || *line != DICT_PROTOCOL_REPLY_OK)
 				ret = -1;
 		}
-		t_pop();
-	}
+	} T_FRAME_END;
 
 	i_free(ctx);
 	return ret;
@@ -482,15 +484,14 @@
 {
 	struct client_dict_transaction_context *ctx =
 		(struct client_dict_transaction_context *)_ctx;
-	const char *query;
 
-	if (ctx->sent_begin) {
-		t_push();
+	if (ctx->sent_begin) T_FRAME_BEGIN {
+		const char *query;
+
 		query = t_strdup_printf("%c%u\n", DICT_PROTOCOL_CMD_ROLLBACK,
 					ctx->id);
 		(void)client_dict_send_transaction_query(ctx, query);
-		t_pop();
-	}
+	} T_FRAME_END;
 
 	i_free(ctx);
 }
@@ -500,15 +501,16 @@
 {
 	struct client_dict_transaction_context *ctx =
 		(struct client_dict_transaction_context *)_ctx;
-	const char *query;
+
+	T_FRAME(
+		const char *query;
 
-	t_push();
-	query = t_strdup_printf("%c%u\t%s\t%s\n",
-				DICT_PROTOCOL_CMD_SET, ctx->id,
-				dict_client_escape(key),
-				dict_client_escape(value));
-	(void)client_dict_send_transaction_query(ctx, query);
-	t_pop();
+		query = t_strdup_printf("%c%u\t%s\t%s\n",
+					DICT_PROTOCOL_CMD_SET, ctx->id,
+					dict_client_escape(key),
+					dict_client_escape(value));
+		(void)client_dict_send_transaction_query(ctx, query);
+	);
 }
 
 static void client_dict_unset(struct dict_transaction_context *_ctx,
@@ -516,14 +518,15 @@
 {
 	struct client_dict_transaction_context *ctx =
 		(struct client_dict_transaction_context *)_ctx;
-	const char *query;
+
+	T_FRAME(
+		const char *query;
 
-	t_push();
-	query = t_strdup_printf("%c%u\t%s\n",
-				DICT_PROTOCOL_CMD_UNSET, ctx->id,
-				dict_client_escape(key));
-	(void)client_dict_send_transaction_query(ctx, query);
-	t_pop();
+		query = t_strdup_printf("%c%u\t%s\n",
+					DICT_PROTOCOL_CMD_UNSET, ctx->id,
+					dict_client_escape(key));
+		(void)client_dict_send_transaction_query(ctx, query);
+	);
 }
 
 static void client_dict_atomic_inc(struct dict_transaction_context *_ctx,
@@ -531,14 +534,14 @@
 {
 	struct client_dict_transaction_context *ctx =
 		(struct client_dict_transaction_context *)_ctx;
-	const char *query;
 
-	t_push();
-	query = t_strdup_printf("%c%u\t%s\t%lld\n",
-				DICT_PROTOCOL_CMD_ATOMIC_INC,
-				ctx->id, dict_client_escape(key), diff);
-	(void)client_dict_send_transaction_query(ctx, query);
-	t_pop();
+	T_FRAME(
+		const char *query;
+		query = t_strdup_printf("%c%u\t%s\t%lld\n",
+					DICT_PROTOCOL_CMD_ATOMIC_INC,
+					ctx->id, dict_client_escape(key), diff);
+		(void)client_dict_send_transaction_query(ctx, query);
+	);
 }
 
 struct dict dict_driver_client = {
--- a/src/lib-dict/dict-sql.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-dict/dict-sql.c	Wed Dec 05 17:47:44 2007 +0200
@@ -41,10 +41,36 @@
 
 static struct sql_pool *dict_sql_pool;
 
+static void sql_dict_config_parse_line(struct sql_dict *dict, const char *line)
+{
+	const char *p, *value;
+
+	while (*line == ' ') line++;
+	value = strchr(line, '=');
+	if (value == NULL)
+		return;
+
+	for (p = value; p[-1] == ' ' && p != line; p--) ;
+	line = t_strdup_until(line, p);
+	value++;
+	while (*value == ' ') value++;
+
+	if (strcmp(line, "connect") == 0)
+		dict->connect_string = p_strdup(dict->pool, value);
+	else if (strcmp(line, "table") == 0)
+		dict->table = p_strdup(dict->pool, value);
+	else if (strcmp(line, "select_field") == 0)
+		dict->select_field = p_strdup(dict->pool, value);
+	else if (strcmp(line, "where_field") == 0)
+		dict->where_field = p_strdup(dict->pool, value);
+	else if (strcmp(line, "username_field") == 0)
+		dict->username_field = p_strdup(dict->pool, value);
+}
+
 static int sql_dict_read_config(struct sql_dict *dict, const char *path)
 {
 	struct istream *input;
-	const char *line, *value, *p;
+	const char *line;
 	int fd;
 
 	fd = open(path, O_RDONLY);
@@ -55,29 +81,9 @@
 
 	input = i_stream_create_fd(fd, (size_t)-1, FALSE);
 	while ((line = i_stream_read_next_line(input)) != NULL) {
-		while (*line == ' ') line++;
-		value = strchr(line, '=');
-		if (value == NULL)
-			continue;
-
-		t_push();
-		for (p = value; p[-1] == ' ' && p != line; p--) ;
-		line = t_strdup_until(line, p);
-		value++;
-		while (*value == ' ') value++;
-
-		if (strcmp(line, "connect") == 0)
-			dict->connect_string = p_strdup(dict->pool, value);
-		else if (strcmp(line, "table") == 0)
-			dict->table = p_strdup(dict->pool, value);
-		else if (strcmp(line, "select_field") == 0)
-			dict->select_field = p_strdup(dict->pool, value);
-		else if (strcmp(line, "where_field") == 0)
-			dict->where_field = p_strdup(dict->pool, value);
-		else if (strcmp(line, "username_field") == 0)
-			dict->username_field = p_strdup(dict->pool, value);
-
-		t_pop();
+		T_FRAME(
+			sql_dict_config_parse_line(dict, line);
+		);
 	}
 	i_stream_destroy(&input);
 	(void)close(fd);
@@ -125,10 +131,8 @@
 		return NULL;
 	}
 
-	t_push();
 	dict->db = sql_pool_new(dict_sql_pool, driver->name,
 				dict->connect_string);
-	t_pop();
 	return &dict->dict;
 }
 
@@ -166,7 +170,6 @@
 {
 	struct sql_dict *dict = (struct sql_dict *)_dict;
 	struct sql_result *result;
-	string_t *query;
 	int ret;
 	bool priv;
 
@@ -175,18 +178,19 @@
 		return -1;
 	}
 
-	t_push();
-	query = t_str_new(256);
-	str_printfa(query, "SELECT %s FROM %s WHERE %s = '%s'",
-		    dict->select_field, dict->table,
-		    dict->where_field, sql_escape_string(dict->db, key));
-	if (priv) {
-		str_printfa(query, " AND %s = '%s'",
-			    dict->username_field,
-			    sql_escape_string(dict->db, dict->username));
-	}
-	result = sql_query_s(dict->db, str_c(query));
-	t_pop();
+	T_FRAME(
+		string_t *query = t_str_new(256);
+		str_printfa(query, "SELECT %s FROM %s WHERE %s = '%s'",
+			    dict->select_field, dict->table,
+			    dict->where_field,
+			    sql_escape_string(dict->db, key));
+		if (priv) {
+			str_printfa(query, " AND %s = '%s'",
+				    dict->username_field,
+				    sql_escape_string(dict->db, dict->username));
+		}
+		result = sql_query_s(dict->db, str_c(query));
+	);
 
 	ret = sql_result_next_row(result);
 	if (ret <= 0)
@@ -206,17 +210,17 @@
 {
 	struct sql_dict *dict = (struct sql_dict *)_dict;
         struct sql_dict_iterate_context *ctx;
-	string_t *query;
 	bool priv;
 
 	ctx = i_new(struct sql_dict_iterate_context, 1);
 	ctx->ctx.dict = _dict;
 
-	if (sql_path_fix(&path, &priv) < 0)
+	if (sql_path_fix(&path, &priv) < 0) {
 		ctx->result = NULL;
-	else {
-		t_push();
-		query = t_str_new(256);
+		return &ctx->ctx;
+	}
+	T_FRAME(
+		string_t *query = t_str_new(256);
 		str_printfa(query, "SELECT %s, %s FROM %s "
 			    "WHERE %s LIKE '%s/%%'",
 			    dict->where_field, dict->select_field,
@@ -238,8 +242,7 @@
 		else if ((flags & DICT_ITERATE_FLAG_SORT_BY_VALUE) != 0)
 			str_printfa(query, " ORDER BY %s", dict->select_field);
 		ctx->result = sql_query_s(dict->db, str_c(query));
-		t_pop();
-	}
+	);
 
 	return &ctx->ctx;
 }
@@ -316,24 +319,12 @@
 	i_free(ctx);
 }
 
-static void sql_dict_set(struct dict_transaction_context *_ctx,
-			 const char *key, const char *value)
+static const char *
+sql_dict_set_query(struct sql_dict *dict, const char *key, const char *value,
+		   bool priv)
 {
-	struct sql_dict_transaction_context *ctx =
-		(struct sql_dict_transaction_context *)_ctx;
-	struct sql_dict *dict = (struct sql_dict *)_ctx->dict;
-	const char *query;
-	bool priv;
-
-	if (sql_path_fix(&key, &priv) < 0) {
-		i_error("sql dict: Invalid key: %s", key);
-		ctx->failed = TRUE;
-		return;
-	}
-
-	t_push();
 	if (priv) {
-		query = t_strdup_printf(
+		return t_strdup_printf(
 			"INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s') "
 			"ON DUPLICATE KEY UPDATE %s = '%s'",
 			dict->table, dict->select_field, dict->where_field,
@@ -344,7 +335,7 @@
 			dict->select_field,
 			sql_escape_string(dict->db, value));
 	} else {
-		query = t_strdup_printf(
+		return t_strdup_printf(
 			"INSERT INTO %s (%s, %s) VALUES ('%s', '%s') "
 			"ON DUPLICATE KEY UPDATE %s = '%s'",
 			dict->table, dict->select_field, dict->where_field,
@@ -353,17 +344,14 @@
                         dict->select_field,
 			sql_escape_string(dict->db, value));
 	}
-	sql_update(ctx->sql_ctx, query);
-	t_pop();
 }
 
-static void sql_dict_unset(struct dict_transaction_context *_ctx,
-			   const char *key)
+static void sql_dict_set(struct dict_transaction_context *_ctx,
+			 const char *key, const char *value)
 {
 	struct sql_dict_transaction_context *ctx =
 		(struct sql_dict_transaction_context *)_ctx;
 	struct sql_dict *dict = (struct sql_dict *)_ctx->dict;
-	const char *query;
 	bool priv;
 
 	if (sql_path_fix(&key, &priv) < 0) {
@@ -372,22 +360,75 @@
 		return;
 	}
 
-	t_push();
+	T_FRAME(
+		const char *query;
+
+		query = sql_dict_set_query(dict, key, value, priv);
+		sql_update(ctx->sql_ctx, query);
+	);
+}
+
+static const char *
+sql_dict_unset_query(struct sql_dict *dict, const char *key, bool priv)
+{
 	if (priv) {
-		query = t_strdup_printf(
+		return t_strdup_printf(
 			"DELETE FROM %s WHERE %s = '%s' AND %s = '%s'",
 			dict->table, dict->where_field,
 			sql_escape_string(dict->db, key),
 			dict->username_field,
 			sql_escape_string(dict->db, dict->username));
 	} else {
-		query = t_strdup_printf(
+		return t_strdup_printf(
 			"DELETE FROM %s WHERE %s = '%s'",
 			dict->table, dict->where_field,
 			sql_escape_string(dict->db, key));
 	}
-	sql_update(ctx->sql_ctx, query);
-	t_pop();
+}
+
+static void sql_dict_unset(struct dict_transaction_context *_ctx,
+			   const char *key)
+{
+	struct sql_dict_transaction_context *ctx =
+		(struct sql_dict_transaction_context *)_ctx;
+	struct sql_dict *dict = (struct sql_dict *)_ctx->dict;
+	bool priv;
+
+	if (sql_path_fix(&key, &priv) < 0) {
+		i_error("sql dict: Invalid key: %s", key);
+		ctx->failed = TRUE;
+		return;
+	}
+
+	T_FRAME(
+		const char *query;
+
+		query = sql_dict_unset_query(dict, key, priv);
+		sql_update(ctx->sql_ctx, query);
+	);
+}
+
+static const char *
+sql_dict_atomic_inc_query(struct sql_dict *dict, const char *key,
+			  long long diff, bool priv)
+{
+	if (priv) {
+		return t_strdup_printf(
+			"INSERT INTO %s (%s, %s, %s) VALUES (%lld, '%s', '%s') "
+			"ON DUPLICATE KEY UPDATE %s = %s + %lld",
+			dict->table, dict->select_field, dict->where_field,
+			dict->username_field,
+                        diff, sql_escape_string(dict->db, key),
+			sql_escape_string(dict->db, dict->username),
+                        dict->select_field, dict->select_field, diff);
+	} else {
+		return t_strdup_printf(
+			"INSERT INTO %s (%s, %s) VALUES (%lld, '%s') "
+			"ON DUPLICATE KEY UPDATE %s = %s + %lld",
+			dict->table, dict->select_field, dict->where_field,
+                        diff, sql_escape_string(dict->db, key),
+                        dict->select_field, dict->select_field, diff);
+	}
 }
 
 static void sql_dict_atomic_inc(struct dict_transaction_context *_ctx,
@@ -396,7 +437,6 @@
 	struct sql_dict_transaction_context *ctx =
 		(struct sql_dict_transaction_context *)_ctx;
 	struct sql_dict *dict = (struct sql_dict *)_ctx->dict;
-	const char *query;
 	bool priv;
 
 	if (sql_path_fix(&key, &priv) < 0) {
@@ -405,26 +445,12 @@
 		return;
 	}
 
-	t_push();
-	if (priv) {
-		query = t_strdup_printf(
-			"INSERT INTO %s (%s, %s, %s) VALUES (%lld, '%s', '%s') "
-			"ON DUPLICATE KEY UPDATE %s = %s + %lld",
-			dict->table, dict->select_field, dict->where_field,
-			dict->username_field,
-                        diff, sql_escape_string(dict->db, key),
-			sql_escape_string(dict->db, dict->username),
-                        dict->select_field, dict->select_field, diff);
-	} else {
-		query = t_strdup_printf(
-			"INSERT INTO %s (%s, %s) VALUES (%lld, '%s') "
-			"ON DUPLICATE KEY UPDATE %s = %s + %lld",
-			dict->table, dict->select_field, dict->where_field,
-                        diff, sql_escape_string(dict->db, key),
-                        dict->select_field, dict->select_field, diff);
-	}
-	sql_update(ctx->sql_ctx, query);
-	t_pop();
+	T_FRAME(
+		const char *query;
+
+		query = sql_dict_atomic_inc_query(dict, key, diff, priv);
+		sql_update(ctx->sql_ctx, query);
+	);
 }
 
 static struct dict sql_dict = {
--- a/src/lib-dict/dict.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-dict/dict.c	Wed Dec 05 17:47:44 2007 +0200
@@ -63,17 +63,15 @@
 		return NULL;
 	}
 
-	t_push();
-	name = t_strdup_until(uri, p);
-	dict = dict_driver_lookup(name);
-	if (dict == NULL) {
-		i_error("Unknown dict module: %s", name);
-		t_pop();
-		return NULL;
-	}
-	t_pop();
+	T_FRAME(
+		name = t_strdup_until(uri, p);
+		dict = dict_driver_lookup(name);
+		if (dict == NULL)
+			i_error("Unknown dict module: %s", name);
+	);
 
-	return dict->v.init(dict, p+1, value_type, username);
+	return dict == NULL ? NULL :
+		dict->v.init(dict, p+1, value_type, username);
 }
 
 void dict_deinit(struct dict **_dict)
--- a/src/lib-imap/imap-bodystructure.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-imap/imap-bodystructure.c	Wed Dec 05 17:47:44 2007 +0200
@@ -94,13 +94,11 @@
 	rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
 	(void)rfc822_skip_lwsp(&parser);
 
-	t_push();
 	str = t_str_new(256);
 	if (rfc822_parse_mime_token(&parser, str) >= 0) {
 		data->content_transfer_encoding =
 			imap_quote(data->pool, str_data(str), str_len(str));
 	}
-	t_pop();
 }
 
 static void parse_content_disposition(struct message_part_body_data *data,
@@ -113,12 +111,9 @@
 	rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
 	(void)rfc822_skip_lwsp(&parser);
 
-	t_push();
 	str = t_str_new(256);
-	if (rfc822_parse_mime_token(&parser, str) < 0) {
-		t_pop();
+	if (rfc822_parse_mime_token(&parser, str) < 0)
 		return;
-	}
 	data->content_disposition =
 		imap_quote(data->pool, str_data(str), str_len(str));
 
@@ -134,7 +129,6 @@
 		data->content_disposition_params =
 			p_strdup(data->pool, str_c(str) + 1);
 	}
-	t_pop();
 }
 
 static void parse_content_language(const unsigned char *value, size_t value_len,
@@ -150,7 +144,6 @@
 
 	rfc822_parser_init(&parser, value, value_len, NULL);
 
-	t_push();
 	str = t_str_new(128);
 	str_append_c(str, '"');
 
@@ -168,22 +161,16 @@
 		str_truncate(str, str_len(str) - 2);
 		data->content_language = p_strdup(data->pool, str_c(str));
 	}
-
-	t_pop();
 }
 
 static void parse_content_header(struct message_part_body_data *d,
 				 struct message_header_line *hdr,
 				 pool_t pool)
 {
-	const char *name = hdr->name;
+	const char *name = hdr->name + strlen("Content-");
 	const unsigned char *value;
 	size_t value_len;
 
-	if (strncasecmp(name, "Content-", 8) != 0)
-		return;
-	name += 8;
-
 	if (hdr->continues) {
 		hdr->use_full_value = TRUE;
 		return;
@@ -207,11 +194,8 @@
 
 	case 't':
 	case 'T':
-		if (strcasecmp(name, "Type") == 0 && d->content_type == NULL) {
-			t_push();
+		if (strcasecmp(name, "Type") == 0 && d->content_type == NULL)
 			parse_content_type(d, hdr);
-			t_pop();
-		}
 		if (strcasecmp(name, "Transfer-Encoding") == 0 &&
 		    d->content_transfer_encoding == NULL)
 			parse_content_transfer_encoding(d, hdr);
@@ -232,8 +216,9 @@
 				imap_quote(pool, value, value_len);
 		}
 		if (strcasecmp(name, "Disposition") == 0 &&
-		    d->content_disposition_params == NULL)
+		    d->content_disposition_params == NULL) {
 			parse_content_disposition(d, hdr);
+		}
 		break;
 	}
 }
@@ -275,15 +260,16 @@
 	}
 	part_data = part->context;
 
-	t_push();
-
-	parse_content_header(part_data, hdr, pool);
+	if (strncasecmp(hdr->name, "Content-", 8) == 0) {
+		T_FRAME(
+			parse_content_header(part_data, hdr, pool);
+		);
+	}
 
 	if (parent_rfc822) {
 		/* message/rfc822, we need the envelope */
 		imap_envelope_parse_header(pool, &part_data->envelope, hdr);
 	}
-	t_pop();
 }
 
 static void part_write_body_multipart(const struct message_part *part,
--- a/src/lib-imap/imap-match.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-imap/imap-match.c	Wed Dec 05 17:47:44 2007 +0200
@@ -107,17 +107,14 @@
 	return TRUE;
 }
 
-struct imap_match_glob *
-imap_match_init_multiple(pool_t pool, const char *const *patterns,
-			 bool inboxcase, char separator)
+static struct imap_match_glob *
+imap_match_init_multiple_real(pool_t pool, const char *const *patterns,
+			      bool inboxcase, char separator)
 {
 	struct imap_match_glob *glob;
 	struct imap_match_pattern *match_patterns;
 	unsigned int i, len, pos, patterns_count, patterns_data_len = 0;
 
-	if (!pool->datastack_pool)
-		t_push();
-
 	patterns_count = str_array_length(patterns);
 	match_patterns = p_new(pool, struct imap_match_pattern,
 			       patterns_count + 1);
@@ -151,10 +148,23 @@
 		pos += len;
 	}
 	glob->patterns = match_patterns;
+	return glob;
+}
 
-	if (!pool->datastack_pool)
-		t_pop();
+struct imap_match_glob *
+imap_match_init_multiple(pool_t pool, const char *const *patterns,
+			 bool inboxcase, char separator)
+{
+	struct imap_match_glob *glob;
 
+	if (pool->datastack_pool) {
+		return imap_match_init_multiple_real(pool, patterns,
+						     inboxcase, separator);
+	}
+	T_FRAME(
+		glob = imap_match_init_multiple_real(pool, patterns,
+						     inboxcase, separator);
+	);
 	return glob;
 }
 
--- a/src/lib-imap/imap-quote.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-imap/imap-quote.c	Wed Dec 05 17:47:44 2007 +0200
@@ -89,17 +89,18 @@
 const char *imap_quote(pool_t pool, const unsigned char *value,
 		       size_t value_len)
 {
-	string_t *str;
 	char *ret;
 
 	if (value == NULL)
 		return "NIL";
 
-	t_push();
-	str = t_str_new(value_len + MAX_INT_STRLEN + 5);
-	imap_quote_append(str, value, value_len, TRUE);
-	ret = p_strndup(pool, str_data(str), str_len(str));
-	t_pop();
+	T_FRAME(
+		   string_t *str;
+
+		   str = t_str_new(value_len + MAX_INT_STRLEN + 5);
+		   imap_quote_append(str, value, value_len, TRUE);
+		   ret = p_strndup(pool, str_data(str), str_len(str));
+	);
 
 	return ret;
 }
--- a/src/lib-index/mail-cache-fields.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-cache-fields.c	Wed Dec 05 17:47:44 2007 +0200
@@ -439,7 +439,6 @@
 	    mail_cache_header_fields_get_offset(cache, &offset, FALSE) < 0)
 		return -1;
 
-	t_push();
 	buffer = buffer_create_dynamic(pool_datastack_create(), 256);
 
 	copy_to_buf(cache, buffer, FALSE,
@@ -461,11 +460,9 @@
 				cache->fields[i].decision_dirty = FALSE;
 		}
 	}
-	t_pop();
 
 	if (ret == 0)
 		cache->field_header_write_pending = FALSE;
-
 	return ret;
 }
 
@@ -473,13 +470,19 @@
 {
 	int ret;
 
-	if (cache->locked)
-		return mail_cache_header_fields_update_locked(cache);
+	if (cache->locked) {
+		T_FRAME(
+			ret = mail_cache_header_fields_update_locked(cache);
+		);
+		return ret;
+	}
 
 	if (mail_cache_lock(cache, NULL) <= 0)
 		return -1;
 
-	ret = mail_cache_header_fields_update_locked(cache);
+	T_FRAME(
+		ret = mail_cache_header_fields_update_locked(cache);
+	);
 	if (mail_cache_unlock(cache) < 0)
 		ret = -1;
 	return ret;
--- a/src/lib-index/mail-cache-lookup.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-cache-lookup.c	Wed Dec 05 17:47:44 2007 +0200
@@ -421,9 +421,10 @@
 	return (int)l1->line_num - (int)l2->line_num;
 }
 
-int mail_cache_lookup_headers(struct mail_cache_view *view, string_t *dest,
-			      uint32_t seq, unsigned int field_idxs[],
-			      unsigned int fields_count)
+static int
+mail_cache_lookup_headers_real(struct mail_cache_view *view, string_t *dest,
+			       uint32_t seq, unsigned int field_idxs[],
+			       unsigned int fields_count)
 {
 	struct mail_cache *cache = view->cache;
 	struct mail_cache_lookup_iterate_ctx iter;
@@ -444,15 +445,11 @@
 	if (!view->cache->opened)
 		(void)mail_cache_open_and_verify(view->cache);
 
-	t_push();
-
 	/* mark all the fields we want to find. */
 	buf = buffer_create_dynamic(pool_datastack_create(), 32);
 	for (i = 0; i < fields_count; i++) {
-		if (!mail_cache_file_has_field(cache, field_idxs[i])) {
-			t_pop();
+		if (!mail_cache_file_has_field(cache, field_idxs[i]))
 			return 0;
-		}
 
 		if (field_idxs[i] > max_field)
 			max_field = field_idxs[i];
@@ -477,17 +474,13 @@
 		}
 
 	}
-	if (ret < 0) {
-		t_pop();
+	if (ret < 0)
 		return -1;
-	}
 
 	/* check that all fields were found */
 	for (i = 0; i <= max_field; i++) {
-		if (field_state[i] == HDR_FIELD_STATE_WANT) {
-			t_pop();
+		if (field_state[i] == HDR_FIELD_STATE_WANT)
 			return 0;
-		}
 	}
 
 	for (i = 0; i < fields_count; i++)
@@ -519,7 +512,18 @@
 		lines[i].data->offset += hdr_size;
 		lines[i].data->data_size -= hdr_size;
 	}
-
-	t_pop();
 	return 1;
 }
+
+int mail_cache_lookup_headers(struct mail_cache_view *view, string_t *dest,
+			      uint32_t seq, unsigned int field_idxs[],
+			      unsigned int fields_count)
+{
+	int ret;
+
+	T_FRAME(
+		ret = mail_cache_lookup_headers_real(view, dest, seq,
+						     field_idxs, fields_count);
+	);
+	return ret;
+}
--- a/src/lib-index/mail-cache-transaction.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-cache-transaction.c	Wed Dec 05 17:47:44 2007 +0200
@@ -807,7 +807,6 @@
 {
 	struct mail_cache *cache = ctx->cache;
 	unsigned int i;
-	buffer_t *buffer;
 	int ret;
 
 	/* we want to avoid adding all the fields one by one to the cache file,
@@ -844,11 +843,13 @@
 		return 0;
 	}
 
-	t_push();
-	buffer = buffer_create_dynamic(pool_datastack_create(), 256);
-	mail_cache_header_fields_get(cache, buffer);
-	ret = mail_cache_header_fields_write(ctx, buffer);
-	t_pop();
+	T_FRAME(
+		buffer_t *buffer;
+
+		buffer = buffer_create_dynamic(pool_datastack_create(), 256);
+		mail_cache_header_fields_get(cache, buffer);
+		ret = mail_cache_header_fields_write(ctx, buffer);
+	);
 
 	if (ret == 0) {
 		/* we wrote all the headers, so there are no pending changes */
@@ -1033,11 +1034,10 @@
 	return 0;
 }
 
-int mail_cache_delete(struct mail_cache *cache, uint32_t offset)
+static int mail_cache_delete_real(struct mail_cache *cache, uint32_t offset)
 {
 	const struct mail_cache_record *rec;
 	ARRAY_TYPE(uint32_t) looping_offsets;
-	int ret = -1;
 
 	i_assert(cache->locked);
 
@@ -1046,7 +1046,6 @@
 	   the data. also it's actually useful as some index views are still
 	   able to ask cached data from messages that have already been
 	   expunged. */
-	t_push();
 	t_array_init(&looping_offsets, 8);
 	array_append(&looping_offsets, &offset, 1);
 	while (mail_cache_get_record(cache, offset, &rec) == 0) {
@@ -1055,18 +1054,25 @@
 
 		if (offset == 0) {
 			/* successfully got to the end of the list */
-			ret = 0;
-			break;
+			return 0;
 		}
 
 		if (mail_cache_track_loops(&looping_offsets, offset)) {
 			mail_cache_set_corrupted(cache,
 						 "record list is circular");
-			break;
+			return -1;
 		}
 	}
-	t_pop();
+	return -1;
+}
 
+int mail_cache_delete(struct mail_cache *cache, uint32_t offset)
+{
+	int ret;
+
+	T_FRAME(
+		ret = mail_cache_delete_real(cache, offset);
+	);
 	cache->hdr_modified = TRUE;
 	return ret;
 }
--- a/src/lib-index/mail-cache.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-cache.c	Wed Dec 05 17:47:44 2007 +0200
@@ -37,10 +37,12 @@
 	cache->hdr = NULL;
 
 	va_start(va, fmt);
-	t_push();
-	mail_index_set_error(cache->index, "Corrupted index cache file %s: %s",
-			     cache->filepath, t_strdup_vprintf(fmt, va));
-	t_pop();
+	T_FRAME(
+		mail_index_set_error(cache->index,
+				     "Corrupted index cache file %s: %s",
+				     cache->filepath,
+				     t_strdup_vprintf(fmt, va));
+	);
 	va_end(va);
 }
 
--- a/src/lib-index/mail-index-fsck.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-index-fsck.c	Wed Dec 05 17:47:44 2007 +0200
@@ -156,7 +156,6 @@
 		name_size = ext_hdr->hdr_size - name_pos;
 	}
 
-	t_push();
 	/* create keyword name array. invalid keywords are added as
 	   empty strings */
 	t_array_init(&names, keywords_count);
@@ -191,7 +190,6 @@
 
 	if (!changed) {
 		/* nothing was broken */
-		t_pop();
 		return;
 	}
 
@@ -246,7 +244,6 @@
 	index->inconsistency_id++;
 
 	buffer_free(&dest);
-	t_pop();
 }
 
 static void
@@ -258,7 +255,6 @@
 	const char *name, *error;
 	unsigned int offset, ext_offset, i;
 
-	t_push();
 	t_array_init(&names, 64);
 	offset = MAIL_INDEX_HEADER_SIZE_ALIGN(hdr->base_header_size);
 	for (i = 0; offset < hdr->header_size; i++) {
@@ -301,7 +297,6 @@
 		map->hdr_base = map->hdr_copy_buf->data;
 		offset = ext_offset;
 	}
-	t_pop();
 }
 
 static void
@@ -435,7 +430,9 @@
 	mail_index_unmap(&index->map);
 	index->map = map;
 
-	mail_index_fsck_map(index, map);
+	T_FRAME(
+		mail_index_fsck_map(index, map);
+	);
 
 	map->write_base_header = TRUE;
 	map->write_atomic = TRUE;
--- a/src/lib-index/mail-index-map.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-index-map.c	Wed Dec 05 17:47:44 2007 +0200
@@ -213,13 +213,11 @@
 	for (i = 0; offset < map->hdr.header_size; i++) {
 		ext_offset = offset;
 
-		t_push();
 		if (mail_index_map_ext_get_next(map, &offset,
 						&ext_hdr, &name) < 0) {
 			mail_index_set_error(index, "Corrupted index file %s: "
 				"Header extension #%d (%s) goes outside header",
 				index->filepath, i, name);
-			t_pop();
 			return -1;
 		}
 
@@ -228,19 +226,16 @@
 			mail_index_set_error(index, "Corrupted index file %s: "
 					     "Broken extension #%d (%s): %s",
 					     index->filepath, i, name, error);
-			t_pop();
 			return -1;
 		}
 		if (mail_index_map_lookup_ext(map, name, NULL)) {
 			mail_index_set_error(index, "Corrupted index file %s: "
 				"Duplicate header extension %s",
 				index->filepath, name);
-			t_pop();
 			return -1;
 		}
 
 		mail_index_map_register_ext(map, name, ext_offset, ext_hdr);
-		t_pop();
 	}
 	return 0;
 }
@@ -838,12 +833,12 @@
 	for (try = 0; ret > 0; try++) {
 		/* make sure the header is ok before using this mapping */
 		ret = mail_index_map_check_header(new_map);
-		if (ret > 0) {
+		if (ret > 0) T_FRAME_BEGIN {
 			if (mail_index_map_parse_extensions(new_map) < 0)
 				ret = 0;
 			else if (mail_index_map_parse_keywords(new_map) < 0)
 				ret = 0;
-		}
+		} T_FRAME_END;
 		if (ret != 0 || try == 2)
 			break;
 
--- a/src/lib-index/mail-index-sync-ext.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-index-sync-ext.c	Wed Dec 05 17:47:44 2007 +0200
@@ -154,7 +154,6 @@
 
 	i_assert(MAIL_INDEX_MAP_IS_IN_MEMORY(map) && map->refcount == 1);
 
-	t_push();
 	ext = array_get_modifiable(&map->extensions, &count);
 	i_assert(ext_map_idx < count);
 
@@ -256,8 +255,6 @@
                 ext_hdr = get_ext_header(map, &ext[i]);
 		ext_hdr->record_offset = ext[i].record_offset;
 	}
-
-	t_pop();
 }
 
 static void
@@ -382,7 +379,6 @@
 		return -1;
 	}
 
-	t_push();
 	if (u->ext_id != (uint32_t)-1) {
 		name = NULL;
 		ext_map_idx = u->ext_id;
@@ -402,7 +398,6 @@
 		   assert-crashes later, so prevent them immediately. */
 		mail_index_sync_set_corrupted(ctx,
 			"Extension introduction for keywords");
-		t_pop();
 		return -1;
 	}
 
@@ -417,7 +412,6 @@
 			   yet seen it. ignore this update. */
 			ctx->cur_ext_ignore = TRUE;
 		}
-		t_pop();
 
 		ctx->cur_ext_map_idx = ext_map_idx;
 		return 1;
@@ -449,7 +443,6 @@
 					 name, &error) < 0) {
 		mail_index_sync_set_corrupted(ctx,
 			"Broken extension introduction: %s", error);
-		t_pop();
 		return -1;
 	}
 
@@ -473,8 +466,6 @@
 	map->hdr.header_size = hdr_buf->used;
 	map->hdr_base = hdr_buf->data;
 
-	t_pop();
-
         mail_index_sync_init_handlers(ctx);
 	sync_ext_reorder(map, ext_map_idx, 0);
 
--- a/src/lib-index/mail-index-sync-update.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-index-sync-update.c	Wed Dec 05 17:47:44 2007 +0200
@@ -419,7 +419,6 @@
 {
 	int ret = 0;
 
-	t_push();
 	switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
 	case MAIL_TRANSACTION_APPEND: {
 		const struct mail_index_record *rec, *end;
@@ -603,7 +602,6 @@
 		ret = -1;
 		break;
 	}
-	t_pop();
 	return ret;
 }
 
@@ -789,7 +787,10 @@
 		}
 
 		/* we'll just skip over broken entries */
-		(void)mail_index_sync_record(&sync_map_ctx, thdr, tdata);
+		T_FRAME(
+			(void)mail_index_sync_record(&sync_map_ctx,
+						     thdr, tdata);
+		);
 	}
 	map = view->map;
 
--- a/src/lib-index/mail-index-sync.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-index-sync.c	Wed Dec 05 17:47:44 2007 +0200
@@ -76,7 +76,6 @@
 		uidset_offset += 4 - (uidset_offset % 4);
 	uids = CONST_PTR_OFFSET(u, uidset_offset);
 
-	t_push();
 	keyword_names[0] = t_strndup(u + 1, u->name_size);
 	keyword_names[1] = NULL;
 	keywords = mail_index_keywords_create(ctx->index, keyword_names);
@@ -91,7 +90,6 @@
 	}
 
 	mail_index_keywords_free(&keywords);
-	t_pop();
 }
 
 static void mail_index_sync_add_keyword_reset(struct mail_index_sync_ctx *ctx)
@@ -205,8 +203,10 @@
 		if ((ctx->hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
 			continue;
 
-		if (mail_index_sync_add_transaction(ctx))
-			mail_index_sync_update_mailbox_pos(ctx);
+		T_FRAME(
+			if (mail_index_sync_add_transaction(ctx))
+				mail_index_sync_update_mailbox_pos(ctx);
+		);
 	}
 
 	/* create an array containing all expunge, flag and keyword update
@@ -832,12 +832,12 @@
 	}
 
 	va_start(va, fmt);
-	t_push();
-	mail_index_set_error(ctx->view->index,
-			     "Log synchronization error at "
-			     "seq=%u,offset=%"PRIuUOFF_T" for %s: %s",
-			     seq, offset, ctx->view->index->filepath,
-			     t_strdup_vprintf(fmt, va));
-	t_pop();
+	T_FRAME(
+		mail_index_set_error(ctx->view->index,
+				     "Log synchronization error at "
+				     "seq=%u,offset=%"PRIuUOFF_T" for %s: %s",
+				     seq, offset, ctx->view->index->filepath,
+				     t_strdup_vprintf(fmt, va));
+	);
 	va_end(va);
 }
--- a/src/lib-index/mail-index-view-sync.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-index-view-sync.c	Wed Dec 05 17:47:44 2007 +0200
@@ -483,8 +483,11 @@
 			i_assert((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0 ||
 				 (hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0);
 
-			if (mail_index_sync_record(&ctx->sync_map_ctx,
-						   hdr, ctx->data) < 0)
+			T_FRAME(
+				ret = mail_index_sync_record(&ctx->sync_map_ctx,
+							     hdr, ctx->data);
+			);
+			if (ret < 0)
 				return -1;
 		}
 
--- a/src/lib-index/mail-transaction-log-append.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-transaction-log-append.c	Wed Dec 05 17:47:44 2007 +0200
@@ -238,7 +238,6 @@
 	buffer_t *buf;
 	unsigned int hdr_size;
 
-	t_push();
 	hdr_size = sizeof(*trans_hdr) + hdr->size;
 	buf = buffer_create_static_hard(pool_datastack_create(), hdr_size);
 	trans_hdr = buffer_append_space_unsafe(buf, sizeof(*trans_hdr));
@@ -246,7 +245,6 @@
 	trans_hdr->size = hdr->size;
 	buffer_append(buf, hdr + 1, hdr->size);
 	log_append_buffer(ctx, buf, NULL, MAIL_TRANSACTION_EXT_HDR_UPDATE);
-	t_pop();
 }
 
 static void
@@ -331,8 +329,11 @@
 			log_append_buffer(ctx, buf, NULL,
 					  MAIL_TRANSACTION_EXT_RESET);
 		}
-		if (ext_id < hdrs_count && hdrs[ext_id] != NULL)
-			log_append_ext_hdr_update(ctx, hdrs[ext_id]);
+		if (ext_id < hdrs_count && hdrs[ext_id] != NULL) {
+			T_FRAME(
+				log_append_ext_hdr_update(ctx, hdrs[ext_id]);
+			);
+		}
 	}
 }
 
--- a/src/lib-index/mail-transaction-log-file.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-transaction-log-file.c	Wed Dec 05 17:47:44 2007 +0200
@@ -34,11 +34,11 @@
 	}
 
 	va_start(va, fmt);
-	t_push();
-	mail_index_set_error(file->log->index,
-			     "Corrupted transaction log file %s: %s",
-			     file->filepath, t_strdup_vprintf(fmt, va));
-	t_pop();
+	T_FRAME(
+		mail_index_set_error(file->log->index,
+				     "Corrupted transaction log file %s: %s",
+				     file->filepath, t_strdup_vprintf(fmt, va));
+	);
 	va_end(va);
 }
 
--- a/src/lib-index/mail-transaction-log-view.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mail-transaction-log-view.c	Wed Dec 05 17:47:44 2007 +0200
@@ -372,10 +372,10 @@
 	view->broken = TRUE;
 
 	va_start(va, fmt);
-	t_push();
-	mail_transaction_log_file_set_corrupted(view->log->head, "%s",
-						t_strdup_vprintf(fmt, va));
-	t_pop();
+	T_FRAME(
+		mail_transaction_log_file_set_corrupted(view->log->head, "%s",
+			t_strdup_vprintf(fmt, va));
+	);
 	va_end(va);
 }
 
@@ -419,7 +419,6 @@
 	   checked here so that we don't have to implement the same validation
 	   multiple times. other records are checked internally by
 	   mail_index_sync_record(). */
-	t_push();
 	switch (rec_type) {
 	case MAIL_TRANSACTION_APPEND:
 		if ((rec_size % sizeof(struct mail_index_record)) != 0) {
@@ -505,7 +504,6 @@
 			}
 		}
 	}
-	t_pop();
 	return ret;
 }
 
@@ -520,6 +518,7 @@
 	enum mail_transaction_type rec_type;
 	uint32_t full_size;
 	size_t file_size;
+	int ret;
 
 	if (view->cur == NULL)
 		return 0;
@@ -575,13 +574,15 @@
 		return -1;
 	}
 
-	if (!log_view_is_record_valid(file, hdr, data))
-		return -1;
-
-	*hdr_r = hdr;
-	*data_r = data;
-	view->cur_offset += full_size;
-	return 1;
+	T_FRAME(
+		ret = log_view_is_record_valid(file, hdr, data) ? 1 : -1;
+	);
+	if (ret > 0) {
+		*hdr_r = hdr;
+		*data_r = data;
+		view->cur_offset += full_size;
+	}
+	return ret;
 }
 
 int mail_transaction_log_view_next(struct mail_transaction_log_view *view,
--- a/src/lib-index/mailbox-list-index-sync.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mailbox-list-index-sync.c	Wed Dec 05 17:47:44 2007 +0200
@@ -235,7 +235,6 @@
 	dir = ctx->sync_root;
 	rec_flags = MAILBOX_LIST_INDEX_FLAG_CHILDREN;
 
-	t_push();
 	for (;;) {
 		p = strchr(name, ctx->index->separator);
 		hier_name = p == NULL ? name : t_strdup_until(name, p);
@@ -321,7 +320,6 @@
 		name = p + 1;
 		dir = rec->dir;
 	}
-	t_pop();
 
 	i_assert(dir != NULL);
 	*dir_r = dir;
@@ -331,6 +329,7 @@
 static int mailbox_list_index_get_root(struct mailbox_list_index_sync_ctx *ctx)
 {
 	uint32_t seq;
+	int ret;
 
 	i_assert(ctx->index->mmap_size > 0);
 
@@ -352,8 +351,11 @@
 			return -1;
 	}
 
-	return mailbox_list_index_sync_int(ctx, ctx->sync_path,
-					   &ctx->sync_root, &seq);
+	T_FRAME(
+		ret = mailbox_list_index_sync_int(ctx, ctx->sync_path,
+						  &ctx->sync_root, &seq);
+	);
+	return ret;
 }
 
 static int sync_mail_sync_init(struct mailbox_list_index_sync_ctx *ctx)
@@ -461,8 +463,12 @@
 				 const char *name, uint32_t *seq_r)
 {
 	struct mailbox_list_sync_dir *dir;
+	int ret;
 
-	return mailbox_list_index_sync_int(ctx, name, &dir, seq_r);
+	T_FRAME(
+		ret = mailbox_list_index_sync_int(ctx, name, &dir, seq_r);
+	);
+	return ret;
 }
 
 static int
@@ -699,7 +705,6 @@
 	else {
 		/* @UNSAFE: copy the records into a temporary buffer that
 		   we modify and then write back to disk */
-		t_push();
 		recs = t_new(struct mailbox_list_record, dir->count);
 		memcpy(recs, MAILBOX_LIST_RECORDS(dir),
 		       sizeof(struct mailbox_list_record) * dir->count);
@@ -741,7 +746,6 @@
 		o_stream_seek(ctx->output, offset);
 		o_stream_send(ctx->output, recs, size);
 		o_stream_seek(ctx->output, old_offset);
-		t_pop();
 	}
 	ctx->changed = TRUE;
 	return 0;
@@ -757,6 +761,7 @@
 	const struct mailbox_list_sync_record *sync_recs;
 	uint32_t child_offset_pos;
 	unsigned int i, j, count;
+	int ret;
 
 	if (!ctx->seen_sync_root && ctx->sync_root == sync_dir) {
 		i_assert(partial);
@@ -780,7 +785,10 @@
 	} else if (sync_dir->seen_records_count !=
 		   array_count(&sync_dir->records) && !partial) {
 		/* just mark the records deleted */
-		if (mailbox_list_index_sync_update_dir(ctx, sync_dir) < 0)
+		T_FRAME(
+			ret = mailbox_list_index_sync_update_dir(ctx, sync_dir);
+		);
+		if (ret < 0)
 			return -1;
 	}
 
--- a/src/lib-index/mailbox-list-index.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-index/mailbox-list-index.c	Wed Dec 05 17:47:44 2007 +0200
@@ -405,7 +405,6 @@
 {
 	const struct mailbox_list_index_lookup_key *key = _key;
 	const struct mailbox_list_record *rec = _rec;
-	const char *name;
 	int ret;
 
 	if (key->name_hash < rec->name_hash)
@@ -413,15 +412,17 @@
 	if (key->name_hash > rec->name_hash)
 		return 1;
 
-	t_push();
-	if (mailbox_list_get_name(key->index, unsafe_data_stack_pool,
-				  rec, &name) < 0) {
-		*key->failed = TRUE;
-		ret = -1;
-	} else {
-		ret = strcmp(key->name, name);
-	}
-	t_pop();
+	T_FRAME(
+		const char *name;
+
+		if (mailbox_list_get_name(key->index, unsafe_data_stack_pool,
+					  rec, &name) < 0) {
+			*key->failed = TRUE;
+			ret = -1;
+		} else {
+			ret = strcmp(key->name, name);
+		}
+	);
 	return ret;
 }
 
@@ -671,7 +672,6 @@
 {
 	const struct mailbox_list_iter_path *cur;
 	const struct mailbox_list_record *recs;
-	const char *name;
 	uint32_t dir_offset;
 	unsigned int count;
 
@@ -709,18 +709,24 @@
 		}
 	}
 
-	t_push();
-	if (mailbox_list_get_name(ctx->view->index, unsafe_data_stack_pool,
-				  recs, &name) < 0) {
-		ctx->failed = TRUE;
-		t_pop();
+	T_FRAME(
+		const char *name;
+
+		if (mailbox_list_get_name(ctx->view->index,
+					  unsafe_data_stack_pool,
+					  recs, &name) < 0)
+			ctx->failed = TRUE;
+		else {
+			str_truncate(ctx->name_path, ctx->cur.name_path_len);
+			if (ctx->cur.name_path_len > 0) {
+				str_append_c(ctx->name_path,
+					     ctx->view->index->separator);
+			}
+			str_append(ctx->name_path, name);
+		}
+	);
+	if (ctx->failed)
 		return -1;
-	}
-	str_truncate(ctx->name_path, ctx->cur.name_path_len);
-	if (ctx->cur.name_path_len > 0)
-		str_append_c(ctx->name_path, ctx->view->index->separator);
-	str_append(ctx->name_path, name);
-	t_pop();
 
 	info_r->name = str_c(ctx->name_path);
 	info_r->uid = recs->uid;
--- a/src/lib-mail/message-address.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-mail/message-address.c	Wed Dec 05 17:47:44 2007 +0200
@@ -277,14 +277,12 @@
 	}
 }
 
-struct message_address *
-message_address_parse(pool_t pool, const unsigned char *data, size_t size,
-		      unsigned int max_addresses, bool fill_missing)
+static struct message_address *
+message_address_parse_real(pool_t pool, const unsigned char *data, size_t size,
+			   unsigned int max_addresses, bool fill_missing)
 {
 	struct message_address_parser_context ctx;
 
-	if (!pool->datastack_pool)
-		t_push();
 	memset(&ctx, 0, sizeof(ctx));
 
 	rfc822_parser_init(&ctx.parser, data, size, t_str_new(128));
@@ -295,11 +293,26 @@
 	rfc822_skip_lwsp(&ctx.parser);
 
 	(void)parse_address_list(&ctx, max_addresses);
-	if (!pool->datastack_pool)
-		t_pop();
 	return ctx.first_addr;
 }
 
+struct message_address *
+message_address_parse(pool_t pool, const unsigned char *data, size_t size,
+		      unsigned int max_addresses, bool fill_missing)
+{
+	struct message_address *addr;
+
+	if (pool->datastack_pool) {
+		return message_address_parse_real(pool, data, size,
+						  max_addresses, fill_missing);
+	}
+	T_FRAME(
+		addr = message_address_parse_real(pool, data, size,
+						  max_addresses, fill_missing);
+	);
+	return addr;
+}
+
 void message_address_write(string_t *str, const struct message_address *addr)
 {
 	bool first = TRUE, in_group = FALSE;
--- a/src/lib-mail/message-date.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-mail/message-date.c	Wed Dec 05 17:47:44 2007 +0200
@@ -231,14 +231,16 @@
 bool message_date_parse(const unsigned char *data, size_t size,
 		       time_t *time, int *timezone_offset)
 {
-	struct message_date_parser_context ctx;
 	bool success;
 
-	t_push();
-	rfc822_parser_init(&ctx.parser, data, size, NULL);
-	ctx.str = t_str_new(128);
-	success = message_date_parser_tokens(&ctx, time, timezone_offset);
-	t_pop();
+	T_FRAME(
+		struct message_date_parser_context ctx;
+
+		rfc822_parser_init(&ctx.parser, data, size, NULL);
+		ctx.str = t_str_new(128);
+		success = message_date_parser_tokens(&ctx, time,
+						     timezone_offset);
+	);
 
 	return success;
 }
--- a/src/lib-mail/message-decoder.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-mail/message-decoder.c	Wed Dec 05 17:47:44 2007 +0200
@@ -81,7 +81,6 @@
 	struct rfc822_parser_context parser;
 	string_t *value;
 
-	t_push();
 	value = t_str_new(64);
 	rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
 
@@ -105,7 +104,6 @@
 			ctx->content_type = CONTENT_TYPE_QP;
 		break;
 	}
-	t_pop();
 }
 
 static void
@@ -121,12 +119,9 @@
 
 	rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
 	(void)rfc822_skip_lwsp(&parser);
-	t_push();
 	str = t_str_new(64);
-	if (rfc822_parse_content_type(&parser, str) <= 0) {
-		t_pop();
+	if (rfc822_parse_content_type(&parser, str) <= 0)
 		return;
-	}
 
 	while (rfc822_parse_content_param(&parser, &key, &value) > 0) {
 		if (strcasecmp(key, "charset") == 0) {
@@ -135,7 +130,6 @@
 			break;
 		}
 	}
-	t_pop();
 }
 
 static bool message_decode_header(struct message_decoder_context *ctx,
@@ -149,12 +143,14 @@
 		return FALSE;
 	}
 
-	if (hdr->name_len == 12 &&
-	    strcasecmp(hdr->name, "Content-Type") == 0)
-		parse_content_type(ctx, hdr);
-	if (hdr->name_len == 25 &&
-	    strcasecmp(hdr->name, "Content-Transfer-Encoding") == 0)
-		parse_content_transfer_encoding(ctx, hdr);
+	T_FRAME(
+		if (hdr->name_len == 12 &&
+		    strcasecmp(hdr->name, "Content-Type") == 0)
+			parse_content_type(ctx, hdr);
+		if (hdr->name_len == 25 &&
+		    strcasecmp(hdr->name, "Content-Transfer-Encoding") == 0)
+			parse_content_transfer_encoding(ctx, hdr);
+	);
 
 	buffer_set_used_size(ctx->buf, 0);
 	message_header_decode_utf8(hdr->full_value, hdr->full_value_len,
--- a/src/lib-mail/message-parser.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-mail/message-parser.c	Wed Dec 05 17:47:44 2007 +0200
@@ -483,9 +483,9 @@
 			if (hdr->continues)
 				hdr->use_full_value = TRUE;
 			else {
-				t_push();
-				parse_content_type(ctx, hdr);
-				t_pop();
+				T_FRAME(
+					parse_content_type(ctx, hdr);
+				);
 			}
 		}
 
--- a/src/lib-mail/message-search.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-mail/message-search.c	Wed Dec 05 17:47:44 2007 +0200
@@ -26,16 +26,16 @@
 	unsigned int content_type_text:1; /* text/any or message/any */
 };
 
-int message_search_init(pool_t pool, const char *key, const char *charset,
-			enum message_search_flags flags,
-			struct message_search_context **ctx_r)
+static int
+message_search_init_real(pool_t pool, const char *key, const char *charset,
+			 enum message_search_flags flags,
+			 struct message_search_context **ctx_r)
 {
 	struct message_search_context *ctx;
 	string_t *key_utf8;
 	enum charset_result result;
 	int ret;
 
-	t_push();
 	key_utf8 = t_str_new(128);
 	if (charset_to_utf8_str(charset, CHARSET_FLAG_DECOMP_TITLECASE,
 				key, key_utf8, &result) < 0)
@@ -53,7 +53,19 @@
 		ctx->str_find_ctx = str_find_init(pool, ctx->key);
 		ret = 1;
 	}
-	t_pop();
+	return ret;
+}
+
+int message_search_init(pool_t pool, const char *key, const char *charset,
+			enum message_search_flags flags,
+			struct message_search_context **ctx_r)
+{
+	int ret;
+
+	T_FRAME(
+		ret = message_search_init_real(pool, key, charset, flags,
+					       ctx_r);
+	);
 	return ret;
 }
 
@@ -75,7 +87,6 @@
 	struct rfc822_parser_context parser;
 	string_t *content_type;
 
-	t_push();
 	rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
 	(void)rfc822_skip_lwsp(&parser);
 
@@ -85,7 +96,6 @@
 			strncasecmp(str_c(content_type), "text/", 5) == 0 ||
 			strncasecmp(str_c(content_type), "message/", 8) == 0;
 	}
-	t_pop();
 }
 
 static void handle_header(struct message_search_context *ctx,
@@ -97,7 +107,9 @@
 			hdr->use_full_value = TRUE;
 			return;
 		}
-		parse_content_type(ctx, hdr);
+		T_FRAME(
+			parse_content_type(ctx, hdr);
+		);
 	}
 }
 
@@ -194,8 +206,9 @@
 	message_decoder_decode_reset(ctx->decoder);
 }
 
-int message_search_msg(struct message_search_context *ctx,
-		       struct istream *input, const struct message_part *parts)
+static int
+message_search_msg_real(struct message_search_context *ctx,
+			struct istream *input, const struct message_part *parts)
 {
 	const enum message_header_parser_flags hdr_parser_flags =
 		MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
@@ -203,7 +216,6 @@
 	struct message_block raw_block;
 	int ret = 0;
 
-	t_push();
 	message_search_reset(ctx);
 
 	if (parts != NULL) {
@@ -224,7 +236,16 @@
 	if (ret < 0 && input->stream_errno == 0)
 		ret = 0;
 	(void)message_parser_deinit(&parser_ctx);
-	t_pop();
-
 	return ret;
 }
+
+int message_search_msg(struct message_search_context *ctx,
+		       struct istream *input, const struct message_part *parts)
+{
+	int ret;
+
+	T_FRAME(
+		ret = message_search_msg_real(ctx, input, parts);
+	);
+	return ret;
+}
--- a/src/lib-settings/settings.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-settings/settings.c	Wed Dec 05 17:47:44 2007 +0200
@@ -64,8 +64,8 @@
 
 #define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
 
-#undef settings_read
-bool settings_read(const char *path, const char *section,
+static bool
+settings_read_real(const char *path, const char *section,
 		   settings_callback_t *callback,
 		   settings_section_callback_t *sect_callback, void *context)
 {
@@ -82,8 +82,6 @@
 		return FALSE;
 	}
 
-	t_push();
-
 	if (section == NULL) {
 		skip = 0;
                 next_section = NULL;
@@ -265,7 +263,19 @@
 	}
 
 	i_stream_destroy(&input);
-	t_pop();
-
 	return errormsg == NULL;
 }
+
+#undef settings_read
+bool settings_read(const char *path, const char *section,
+		   settings_callback_t *callback,
+		   settings_section_callback_t *sect_callback, void *context)
+{
+	bool ret;
+
+	T_FRAME(
+		ret = settings_read_real(path, section, callback,
+					 sect_callback, context);
+	);
+	return ret;
+}
--- a/src/lib-sql/driver-mysql.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-sql/driver-mysql.c	Wed Dec 05 17:47:44 2007 +0200
@@ -195,7 +195,6 @@
 
 	db->ssl_cipher = "HIGH";
 
-	t_push();
 	args = t_strsplit_spaces(connect_string, " ");
 	for (; *args != NULL; args++) {
 		value = strchr(*args, '=');
@@ -236,7 +235,6 @@
 		if (field != NULL)
 			*field = p_strdup(db->pool, value);
 	}
-	t_pop();
 
 	if (array_count(&db->connections) == 0)
 		i_fatal("mysql: No hosts given in connect string");
@@ -253,7 +251,9 @@
 	db->api = driver_mysql_db;
 	p_array_init(&db->connections, db->pool, 6);
 
-	driver_mysql_parse_connect_string(db, connect_string);
+	T_FRAME(
+		driver_mysql_parse_connect_string(db, connect_string);
+	);
 	return &db->api;
 }
 
--- a/src/lib-sql/driver-pgsql.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-sql/driver-pgsql.c	Wed Dec 05 17:47:44 2007 +0200
@@ -289,9 +289,9 @@
 
 	if (result->callback != NULL) {
 		result->api.callback = TRUE;
-		t_push();
-		result->callback(&result->api, result->context);
-		t_pop();
+		T_FRAME(
+			result->callback(&result->api, result->context);
+		);
 		result->api.callback = FALSE;
 		free_result = db->sync_result != &result->api;
 	}
--- a/src/lib-sql/sql-pool.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-sql/sql-pool.c	Wed Dec 05 17:47:44 2007 +0200
@@ -87,10 +87,9 @@
 {
 	struct sql_pool_context *ctx;
 	struct sql_db *db;
-	const char *key;
+	char *key;
 
-	t_push();
-	key = t_strdup_printf("%s\t%s", db_driver, connect_string);
+	key = i_strdup_printf("%s\t%s", db_driver, connect_string);
 	db = hash_lookup(pool->dbs, key);
 	if (db != NULL) {
 		ctx = SQL_POOL_CONTEXT(db);
@@ -98,12 +97,13 @@
 			sql_pool_unlink(ctx);
 			ctx->prev = ctx->next = NULL;
 		}
+		i_free(key);
 	} else {
 		sql_pool_drop_oldest(pool);
 
 		ctx = i_new(struct sql_pool_context, 1);
 		ctx->pool = pool;
-		ctx->key = i_strdup(key);
+		ctx->key = key;
 
 		db = sql_init(db_driver, connect_string);
 		ctx->orig_deinit = db->v.deinit;
@@ -112,7 +112,6 @@
 		MODULE_CONTEXT_SET(db, sql_pool_module, ctx);
 		hash_insert(pool->dbs, ctx->key, db);
 	}
-	t_pop();
 
 	ctx->refcount++;
 	return db;
--- a/src/lib-storage/index/cydir/cydir-save.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/cydir/cydir-save.c	Wed Dec 05 17:47:44 2007 +0200
@@ -70,7 +70,6 @@
 	struct cydir_save_context *ctx = t->save_ctx;
 	enum mail_flags save_flags;
 	struct istream *crlf_input;
-	const char *path;
 
 	i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
 
@@ -82,20 +81,23 @@
 		ctx->tmp_basename = cydir_generate_tmp_filename();
 	}
 
-	t_push();
-	path = cydir_get_save_path(ctx, ctx->mail_count);
-	ctx->fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0660);
-	if (ctx->fd != -1) {
-		ctx->output = o_stream_create_fd_file(ctx->fd, 0, FALSE);
-		o_stream_cork(ctx->output);
-	} else {
-		mail_storage_set_critical(_t->box->storage,
-					  "open(%s) failed: %m", path);
-		ctx->failed = TRUE;
-		t_pop();
+	T_FRAME(
+		const char *path;
+
+		path = cydir_get_save_path(ctx, ctx->mail_count);
+		ctx->fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0660);
+		if (ctx->fd != -1) {
+			ctx->output =
+				o_stream_create_fd_file(ctx->fd, 0, FALSE);
+			o_stream_cork(ctx->output);
+		} else {
+			mail_storage_set_critical(_t->box->storage,
+						  "open(%s) failed: %m", path);
+			ctx->failed = TRUE;
+		}
+	);
+	if (ctx->failed)
 		return -1;
-	}
-	t_pop();
 
 	/* add to index */
 	save_flags = flags & ~MAIL_RECENT;
--- a/src/lib-storage/index/cydir/cydir-storage.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Wed Dec 05 17:47:44 2007 +0200
@@ -350,9 +350,7 @@
 	}
 
 	/* need to stat() then */
-	t_push();
 	mail_path = t_strconcat(dir, "/", fname, NULL);
-
 	if (stat(mail_path, &st) == 0) {
 		if (!S_ISDIR(st.st_mode)) {
 			/* non-directory */
@@ -379,8 +377,6 @@
 		   destination not found. don't bother logging errors. */
 		*flags |= MAILBOX_NOSELECT;
 	}
-	t_pop();
-
 	return ret;
 }
 
--- a/src/lib-storage/index/dbox/dbox-file.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/dbox/dbox-file.c	Wed Dec 05 17:47:44 2007 +0200
@@ -328,7 +328,6 @@
 	file->append_offset = 0;
 	file->msg_header_size = 0;
 
-	t_push();
 	for (tmp = t_strsplit(line, " "); *tmp != NULL; tmp++) {
 		key = **tmp;
 		value = *tmp + 1;
@@ -348,7 +347,6 @@
 		}
 		pos += strlen(value) + 2;
 	}
-	t_pop();
 
 	if (file->msg_header_size == 0) {
 		dbox_file_set_corrupted(file, "Missing message header size");
@@ -363,6 +361,7 @@
 static int dbox_file_read_header(struct dbox_file *file)
 {
 	const char *line;
+	int ret;
 
 	i_stream_seek(file->input, 0);
 	line = i_stream_read_next_line(file->input);
@@ -374,7 +373,10 @@
 		return -1;
 	}
 	file->file_header_size = file->input->v_offset;
-	return dbox_file_parse_header(file, line) < 0 ? 0 : 1;
+	T_FRAME(
+		ret = dbox_file_parse_header(file, line) < 0 ? 0 : 1;
+	);
+	return ret;
 }
 
 static int dbox_file_open_fd(struct dbox_file *file)
@@ -989,7 +991,7 @@
 	return ret;
 }
 
-int dbox_file_metadata_write(struct dbox_file *file)
+static int dbox_file_metadata_write_real(struct dbox_file *file)
 {
 	const char *const *metadata, *const *changes;
 	unsigned int i, j, count, changes_count, space_needed, skip_pos;
@@ -1022,7 +1024,6 @@
 		skip_pos += strlen(metadata[i]) + 1;
 	}
 
-	t_push();
 	str = t_str_new(512);
 	last_change_len = orig_len = 0;
 	/* overwrite existing metadata fields */
@@ -1058,10 +1059,8 @@
 	str_truncate(str, last_change_len);
 	if (skip_pos + str_len(str) >= file->metadata_len) {
 		if ((ret = dbox_file_grow_metadata(file, skip_pos +
-						   str_len(str))) <= 0) {
-			t_pop();
+						   str_len(str))) <= 0)
 			return ret;
-		}
 	}
 
 	memset(space, DBOX_METADATA_SPACE, sizeof(space));
@@ -1074,10 +1073,21 @@
 
 	ret = pwrite_full(file->fd, str_data(str), str_len(str),
 			  offset + skip_pos);
-	if (ret < 0)
+	if (ret < 0) {
 		dbox_file_set_syscall_error(file, "pwrite");
-	t_pop();
-	return ret < 0 ? -1 : 1;
+		return -1;
+	}
+	return 1;
+}
+
+int dbox_file_metadata_write(struct dbox_file *file)
+{
+	int ret;
+
+	T_FRAME(
+		ret = dbox_file_metadata_write_real(file);
+	);
+	return ret;
 }
 
 int dbox_file_metadata_write_to(struct dbox_file *file, struct ostream *output)
--- a/src/lib-storage/index/dbox/dbox-index.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/dbox/dbox-index.c	Wed Dec 05 17:47:44 2007 +0200
@@ -261,7 +261,10 @@
 		if (index->fd != -1)
 			dbox_index_close(index);
 
-		if (dbox_index_recreate(index, FALSE) < 0)
+		T_FRAME(
+			ret = dbox_index_recreate(index, FALSE);
+		);
+		if (ret < 0)
 			return -1;
 	}
 
@@ -552,15 +555,12 @@
 	unsigned int i, count;
 	int fd, ret = 0;
 
-	t_push();
 	temp_path = t_str_new(256);
 	str_append(temp_path, index->path);
 
 	fd = dbox_index_create_fd(index->mbox, temp_path, locked);
-	if (fd == -1) {
-		t_pop();
+	if (fd == -1)
 		return -1;
-	}
 
 	str = t_str_new(256);
 	output = o_stream_create_fd_file(fd, 0, FALSE);
@@ -626,7 +626,6 @@
 		if (unlink(str_c(temp_path)) < 0)
 			i_error("unlink(%s) failed: %m", str_c(temp_path));
 	}
-	t_pop();
 	return ret;
 }
 
@@ -877,12 +876,10 @@
 	for (i = 0; i < count; i++) {
 		file = files[i];
 
-		if (file->file_id == 0) {
-			t_push();
+		if (file->file_id == 0) T_FRAME_BEGIN {
 			if (dbox_index_append_commit_new(ctx, file, str) < 0)
 				ret = -1;
-			t_pop();
-		}
+		} T_FRAME_END;
 	}
 
 	if (ret == 0 && str_len(str) > 0) {
--- a/src/lib-storage/index/dbox/dbox-storage.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/dbox/dbox-storage.c	Wed Dec 05 17:47:44 2007 +0200
@@ -429,9 +429,7 @@
 	}
 
 	/* need to stat() then */
-	t_push();
 	mail_path = t_strconcat(dir, "/", fname, NULL);
-
 	if (stat(mail_path, &st) == 0) {
 		if (!S_ISDIR(st.st_mode)) {
 			/* non-directory */
@@ -458,8 +456,6 @@
 		   destination not found. don't bother logging errors. */
 		*flags |= MAILBOX_NOSELECT;
 	}
-	t_pop();
-
 	return ret;
 }
 
--- a/src/lib-storage/index/dbox/dbox-sync-file.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/dbox/dbox-sync-file.c	Wed Dec 05 17:47:44 2007 +0200
@@ -50,7 +50,6 @@
 	string_t *value;
 	const char *old_value;
 
-	t_push();
 	value = t_str_new(256);
 
 	/* flags */
@@ -82,7 +81,6 @@
 		dbox_file_metadata_set(file, DBOX_METADATA_EXPUNGED, "1");
 		mail_index_expunge(ctx->trans, seq);
 	}
-	t_pop();
 }
 
 static int
@@ -153,7 +151,9 @@
 		/* write metadata */
 		(void)dbox_file_metadata_seek_mail_offset(file, offset,
 							  &expunged);
-		dbox_sync_update_metadata(ctx, file, entry, seq);
+		T_FRAME(
+			dbox_sync_update_metadata(ctx, file, entry, seq);
+		);
 		if ((ret = dbox_file_metadata_write_to(file, output)) < 0)
 			break;
 
@@ -228,7 +228,9 @@
 	}
 	append_offset = output->offset;
 	dbox_msg_header_fill(&dbox_msg_hdr, uid, size);
-	dbox_sync_update_metadata(ctx, out_file, NULL, seq);
+	T_FRAME(
+		dbox_sync_update_metadata(ctx, out_file, NULL, seq);
+	);
 
 	/* copy the message */
 	out_path = dbox_file_get_path(out_file);
@@ -291,7 +293,9 @@
 		return 1;
 	}
 
-	dbox_sync_update_metadata(ctx, file, entry, seq);
+	T_FRAME(
+		dbox_sync_update_metadata(ctx, file, entry, seq);
+	);
 	ret = dbox_file_metadata_write(file);
 	if (ret <= 0) {
 		return ret < 0 ? -1 :
--- a/src/lib-storage/index/dbox/dbox-sync-rebuild.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/dbox/dbox-sync-rebuild.c	Wed Dec 05 17:47:44 2007 +0200
@@ -129,15 +129,13 @@
 	}
 
 	value = dbox_file_metadata_get(file, DBOX_METADATA_KEYWORDS);
-	if (value != NULL) {
-		t_push();
+	if (value != NULL) T_FRAME_BEGIN {
 		keywords = mail_index_keywords_create(ctx->mbox->ibox.index,
 						t_strsplit_spaces(value, " "));
 		mail_index_update_keywords(ctx->trans, seq, MODIFY_REPLACE,
 					   keywords);
 		mail_index_keywords_free(&keywords);
-		t_pop();
-	}
+	} T_FRAME_END;
 }
 
 static int dbox_sync_index_file_next(struct dbox_sync_rebuild_context *ctx,
@@ -261,6 +259,23 @@
 	return ret < 0 ? -1 : 0;
 }
 
+static int
+dbox_sync_index_file(struct dbox_sync_rebuild_context *ctx,
+		     const char *path, const char *fname, bool primary)
+{
+	if (strncmp(fname, DBOX_MAIL_FILE_UID_PREFIX,
+		    sizeof(DBOX_MAIL_FILE_UID_PREFIX)-1) == 0)
+		return dbox_sync_index_uid_file(ctx, path, fname);
+
+	if (strncmp(fname, DBOX_MAIL_FILE_MULTI_PREFIX,
+		    sizeof(DBOX_MAIL_FILE_MULTI_PREFIX)-1) == 0)
+		return dbox_sync_index_multi_file(ctx, path, fname);
+
+	if (primary && strstr(fname, ":2,") != NULL)
+		return dbox_sync_index_maildir_file(ctx, fname);
+	return 0;
+}
+
 static int dbox_sync_index_rebuild_dir(struct dbox_sync_rebuild_context *ctx,
 				       const char *path, bool primary)
 {
@@ -279,18 +294,15 @@
 			"opendir(%s) failed: %m", path);
 		return -1;
 	}
-	errno = 0;
-	for (; ret == 0 && (d = readdir(dir)) != NULL; errno = 0) {
-		t_push();
-		if (strncmp(d->d_name, DBOX_MAIL_FILE_UID_PREFIX,
-			    sizeof(DBOX_MAIL_FILE_UID_PREFIX)-1) == 0)
-			ret = dbox_sync_index_uid_file(ctx, path, d->d_name);
-		else if (strncmp(d->d_name, DBOX_MAIL_FILE_MULTI_PREFIX,
-				 sizeof(DBOX_MAIL_FILE_MULTI_PREFIX)-1) == 0)
-			ret = dbox_sync_index_multi_file(ctx, path, d->d_name);
-		else if (primary && strstr(d->d_name, ":2,") != NULL)
-			ret = dbox_sync_index_maildir_file(ctx, d->d_name);
-		t_pop();
+	for (;;) {
+		errno = 0;
+		if ((d = readdir(dir)) == NULL)
+			break;
+
+		T_FRAME(
+			ret = dbox_sync_index_file(ctx, path, d->d_name,
+						   primary);
+		);
 	}
 	if (errno != 0) {
 		mail_storage_set_critical(storage,
@@ -336,9 +348,9 @@
 	mail_index_view_close(&trans_view);
 
 	for (i = 0; i < count && ret == 0; i++) {
-		t_push();
-		ret = dbox_sync_index_maildir_file(ctx, fnames[i]);
-		t_pop();
+		T_FRAME(
+			ret = dbox_sync_index_maildir_file(ctx, fnames[i]);
+		);
 	}
 	return ret;
 }
--- a/src/lib-storage/index/index-mail-headers.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/index-mail-headers.c	Wed Dec 05 17:47:44 2007 +0200
@@ -52,8 +52,6 @@
 	unsigned int i, j, count, match_idx, match_count;
 	bool noncontiguous;
 
-	t_push();
-
 	lines = array_get_modifiable(&mail->header_lines, &count);
 
 	/* sort it first so fields are grouped together and ordered by
@@ -144,7 +142,6 @@
 			index_mail_cache_add_idx(mail, match_idx, NULL, 0);
 		}
 	}
-	t_pop();
 }
 
 static unsigned int
@@ -155,10 +152,10 @@
 		MAIL_CACHE_DECISION_TEMP
 	};
 
-	t_push();
-	header_field.name = t_strconcat("hdr.", field, NULL);
-	mail_cache_register_fields(ibox->cache, &header_field, 1);
-	t_pop();
+	T_FRAME(
+		header_field.name = t_strconcat("hdr.", field, NULL);
+		mail_cache_register_fields(ibox->cache, &header_field, 1);
+	);
 	return header_field.idx;
 }
 
@@ -174,13 +171,32 @@
 	return FALSE;
 }
 
+static void index_mail_parse_header_register_all_wanted(struct index_mail *mail)
+{
+	const struct mail_cache_field *all_cache_fields;
+	unsigned int i, count;
+
+	all_cache_fields =
+		mail_cache_register_get_list(mail->ibox->cache,
+					     pool_datastack_create(), &count);
+	for (i = 0; i < count; i++) {
+		if (strncasecmp(all_cache_fields[i].name, "hdr.", 4) != 0)
+			continue;
+		if (!mail_cache_field_want_add(mail->trans->cache_trans,
+					       mail->data.seq, i))
+			continue;
+
+		array_idx_set(&mail->header_match, all_cache_fields[i].idx,
+			      &mail->header_match_value);
+	}
+}
+
 void index_mail_parse_header_init(struct index_mail *mail,
 				  struct mailbox_header_lookup_ctx *_headers)
 {
 	struct index_header_lookup_ctx *headers =
 		(struct index_header_lookup_ctx *)_headers;
-	const struct mail_cache_field *all_cache_fields;
-	unsigned int i, count;
+	unsigned int i;
 
 	mail->header_seq = mail->data.seq;
 	if (mail->header_data == NULL) {
@@ -226,21 +242,9 @@
 	}
 
 	/* register also all the other headers that exist in cache file */
-	t_push();
-	all_cache_fields =
-		mail_cache_register_get_list(mail->ibox->cache,
-					     pool_datastack_create(), &count);
-	for (i = 0; i < count; i++) {
-		if (strncasecmp(all_cache_fields[i].name, "hdr.", 4) != 0)
-			continue;
-		if (!mail_cache_field_want_add(mail->trans->cache_trans,
-					       mail->data.seq, i))
-			continue;
-
-		array_idx_set(&mail->header_match, all_cache_fields[i].idx,
-			      &mail->header_match_value);
-	}
-	t_pop();
+	T_FRAME(
+		index_mail_parse_header_register_all_wanted(mail);
+	);
 }
 
 static void index_mail_parse_finish_imap_envelope(struct index_mail *mail)
@@ -265,7 +269,6 @@
 			     struct index_mail *mail)
 {
 	struct index_mail_data *data = &mail->data;
-	const char *cache_field_name;
 	unsigned int field_idx, count;
 	uint8_t *match;
 
@@ -288,18 +291,21 @@
 		/* end of headers */
 		if (mail->data.save_sent_date)
 			mail->data.sent_date_parsed = TRUE;
-		index_mail_parse_header_finish(mail);
+		T_FRAME(
+			index_mail_parse_header_finish(mail);
+		);
                 data->save_bodystructure_header = FALSE;
 		return;
 	}
 
 	if (!hdr->continued) {
-		t_push();
-		cache_field_name = t_strconcat("hdr.", hdr->name, NULL);
-		data->parse_line.field_idx =
-			mail_cache_register_lookup(mail->ibox->cache,
-						   cache_field_name);
-		t_pop();
+		T_FRAME(
+			const char *cache_field_name =
+				t_strconcat("hdr.", hdr->name, NULL);
+			data->parse_line.field_idx =
+				mail_cache_register_lookup(mail->ibox->cache,
+							   cache_field_name);
+		);
 	}
 	field_idx = data->parse_line.field_idx;
 	match = array_get_modifiable(&mail->header_match, &count);
@@ -642,7 +648,6 @@
 		count = max_count;
 	decoded_list = p_new(mail->data_pool, const char *, count + 1);
 
-	t_push();
 	buf = buffer_create_dynamic(pool_datastack_create(), 512);
 
 	for (i = 0; i < count; i++) {
@@ -655,7 +660,6 @@
 						    buf->data, buf->used);
 		}
 	}
-	t_pop();
 	return decoded_list;
 }
 
@@ -669,7 +673,9 @@
 	if (!decode_to_utf8 || **value_r == NULL)
 		return 0;
 
-	*value_r = index_mail_headers_decode(mail, *value_r, (unsigned int)-1);
+	T_FRAME(
+		*value_r = index_mail_headers_decode(mail, *value_r, -1U);
+	);
 	return 0;
 }
 
@@ -681,8 +687,11 @@
 
 	if (index_mail_get_raw_headers(mail, field, &list) < 0)
 		return -1;
-	if (decode_to_utf8 && list[0] != NULL)
-		list = index_mail_headers_decode(mail, list, 1);
+	if (decode_to_utf8 && list[0] != NULL) {
+		T_FRAME(
+			list = index_mail_headers_decode(mail, list, 1);
+		);
+	}
 	*value_r = list[0];
 	return list[0] != NULL ? 1 : 0;
 }
@@ -744,8 +753,8 @@
 	return 0;
 }
 
-struct mailbox_header_lookup_ctx *
-index_header_lookup_init(struct mailbox *box, const char *const headers[])
+static struct mailbox_header_lookup_ctx *
+index_header_lookup_init_real(struct mailbox *box, const char *const headers[])
 {
 	struct index_mailbox *ibox = (struct index_mailbox *)box;
 	struct mail_cache_field *fields, header_field = {
@@ -763,8 +772,6 @@
 	for (count = 0, name = headers; *name != NULL; name++)
 		count++;
 
-	t_push();
-
 	/* @UNSAFE: headers need to be sorted for filter stream. */
 	sorted_headers = t_new(const char *, count);
 	memcpy(sorted_headers, headers, count * sizeof(*sorted_headers));
@@ -793,9 +800,18 @@
 		ctx->idx[i] = fields[i].idx;
 		ctx->name[i] = p_strdup(pool, headers[i]);
 	}
+	return &ctx->ctx;
+}
 
-	t_pop();
-	return &ctx->ctx;
+struct mailbox_header_lookup_ctx *
+index_header_lookup_init(struct mailbox *box, const char *const headers[])
+{
+	struct mailbox_header_lookup_ctx *ctx;
+
+	T_FRAME(
+		ctx = index_header_lookup_init_real(box, headers);
+	);
+	return ctx;
 }
 
 void index_header_lookup_deinit(struct mailbox_header_lookup_ctx *_ctx)
--- a/src/lib-storage/index/index-mail.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/index-mail.c	Wed Dec 05 17:47:44 2007 +0200
@@ -37,31 +37,39 @@
 static int index_mail_parse_body(struct index_mail *mail,
 				 enum index_cache_field field);
 
-static bool get_cached_parts(struct index_mail *mail)
+static struct message_part *get_unserialized_parts(struct index_mail *mail)
 {
-	struct mail_cache_field *cache_fields = mail->ibox->cache_fields;
-	struct message_part *part;
+	unsigned int field_idx =
+		mail->ibox->cache_fields[MAIL_CACHE_MESSAGE_PARTS].idx;
+	struct message_part *parts;
 	buffer_t *part_buf;
 	const char *error;
+	int ret;
 
-	t_push();
 	part_buf = buffer_create_dynamic(pool_datastack_create(), 128);
-	if (mail_cache_lookup_field(mail->trans->cache_view, part_buf,
-			mail->data.seq,
-			cache_fields[MAIL_CACHE_MESSAGE_PARTS].idx) <= 0) {
-		t_pop();
-		return FALSE;
-	}
+	ret = mail_cache_lookup_field(mail->trans->cache_view, part_buf,
+				      mail->data.seq, field_idx);
+	if (ret <= 0)
+		return NULL;
 
-	part = message_part_deserialize(mail->data_pool,
-					part_buf->data, part_buf->used, &error);
-	t_pop();
-
-	if (part == NULL) {
+	parts = message_part_deserialize(mail->data_pool, part_buf->data,
+					 part_buf->used, &error);
+	if (parts == NULL) {
 		mail_cache_set_corrupted(mail->ibox->cache,
 			"Corrupted cached message_part data (%s)", error);
+	}
+	return parts;
+}
+
+static bool get_cached_parts(struct index_mail *mail)
+{
+	struct message_part *part;
+
+	T_FRAME(
+		part = get_unserialized_parts(mail);
+	);
+	if (part == NULL)
 		return FALSE;
-	}
 
 	/* we know the NULs now, update them */
 	if ((part->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) {
@@ -80,21 +88,23 @@
 				       enum index_cache_field field,
 				       void *data, size_t data_size)
 {
-	buffer_t *buf;
+	unsigned int field_idx = mail->ibox->cache_fields[field].idx;
 	int ret;
 
-	t_push();
-	buf = buffer_create_data(pool_datastack_create(), data, data_size);
-	if (mail_cache_lookup_field(mail->trans->cache_view, buf,
-				    mail->data.seq,
-				    mail->ibox->cache_fields[field].idx) <= 0) {
-		ret = FALSE;
-	} else {
-		i_assert(buf->used == data_size);
-		ret = TRUE;
-	}
-	t_pop();
+	T_FRAME(
+		buffer_t *buf;
+
+		buf = buffer_create_data(pool_datastack_create(),
+					 data, data_size);
 
+		if (mail_cache_lookup_field(mail->trans->cache_view, buf,
+					    mail->data.seq, field_idx) <= 0)
+			ret = FALSE;
+		else {
+			i_assert(buf->used == data_size);
+			ret = TRUE;
+		}
+	);
 	return ret;
 }
 
@@ -117,10 +127,10 @@
 	return data->flags;
 }
 
-const char *const *index_mail_get_keywords(struct mail *_mail)
+static const char *const *
+index_mail_get_keywords_real(struct index_mail *mail)
 {
 	static const char *const no_keywords[] = { NULL };
-	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	ARRAY_TYPE(keyword_indexes) keyword_indexes_arr;
 	const char *const *names;
@@ -130,16 +140,13 @@
 	if (array_is_created(&data->keywords))
 		return array_idx(&data->keywords, 0);
 
-	t_push();
 	t_array_init(&keyword_indexes_arr, 128);
 	mail_index_lookup_keywords(mail->ibox->view, mail->data.seq,
 				   &keyword_indexes_arr);
 
 	keyword_indexes = array_get(&keyword_indexes_arr, &count);
-	if (count == 0) {
-		t_pop();
+	if (count == 0)
 		return no_keywords;
-	}
 
 	names = array_get(mail->ibox->keyword_names, &names_count);
 	p_array_init(&data->keywords, mail->data_pool, count);
@@ -153,9 +160,18 @@
 
 	/* end with NULL */
 	(void)array_append_space(&data->keywords);
+	return array_idx(&data->keywords, 0);
+}
 
-	t_pop();
-	return array_idx(&data->keywords, 0);
+const char *const *index_mail_get_keywords(struct mail *_mail)
+{
+	struct index_mail *mail = (struct index_mail *)_mail;
+	const char *const *ret;
+
+	T_FRAME(
+		ret = index_mail_get_keywords_real(mail);
+	);
+	return ret;
 }
 
 int index_mail_get_parts(struct mail *_mail,
@@ -494,11 +510,12 @@
 		return;
 	}
 
-	t_push();
-	buffer = buffer_create_dynamic(pool_datastack_create(), 1024);
-	message_part_serialize(mail->data.parts, buffer);
-	index_mail_cache_add_idx(mail, cache_field, buffer->data, buffer->used);
-	t_pop();
+	T_FRAME(
+		buffer = buffer_create_dynamic(pool_datastack_create(), 1024);
+		message_part_serialize(mail->data.parts, buffer);
+		index_mail_cache_add_idx(mail, cache_field,
+					 buffer->data, buffer->used);
+	);
 
 	data->messageparts_saved_to_cache = TRUE;
 }
--- a/src/lib-storage/index/index-search.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/index-search.c	Wed Dec 05 17:47:44 2007 +0200
@@ -372,22 +372,22 @@
 		ret = 0;
 	else if (arg->type == SEARCH_HEADER_ADDRESS) {
 		/* we have to match against normalized address */
-		struct message_address *addr;
-		string_t *str;
+		T_FRAME(
+			struct message_address *addr;
+			string_t *str;
 
-		t_push();
-		addr = message_address_parse(pool_datastack_create(),
-					     ctx->hdr->full_value,
-					     ctx->hdr->full_value_len,
-					     (unsigned int)-1, TRUE);
-		str = t_str_new(ctx->hdr->value_len);
-		message_address_write(str, addr);
-		hdr = *ctx->hdr;
-		hdr.value = hdr.full_value = str_data(str);
-		hdr.value_len = hdr.full_value_len = str_len(str);
-		block.hdr = &hdr;
-		ret = message_search_more(msg_search_ctx, &block);
-		t_pop();
+			addr = message_address_parse(pool_datastack_create(),
+						     ctx->hdr->full_value,
+						     ctx->hdr->full_value_len,
+						     (unsigned int)-1, TRUE);
+			str = t_str_new(ctx->hdr->value_len);
+			message_address_write(str, addr);
+			hdr = *ctx->hdr;
+			hdr.value = hdr.full_value = str_data(str);
+			hdr.value_len = hdr.full_value_len = str_len(str);
+			block.hdr = &hdr;
+			ret = message_search_more(msg_search_ctx, &block);
+		);
 	} else {
 		block.hdr = ctx->hdr;
 		ret = message_search_more(msg_search_ctx, &block);
@@ -944,7 +944,6 @@
 					struct index_search_context *ctx)
 {
 	const struct mail_index_header *hdr;
-	const char *text;
 	float percentage;
 	unsigned int msecs, secs;
 
@@ -962,13 +961,16 @@
 			 ctx->search_start_time.tv_usec) / 1000;
 		secs = (msecs / (percentage / 100.0) - msecs) / 1000;
 
-		t_push();
-		text = t_strdup_printf("Searched %d%% of the mailbox, "
-				       "ETA %d:%02d", (int)percentage,
-				       secs/60, secs%60);
-		box->storage->callbacks->
-			notify_ok(box, text, box->storage->callback_context);
-		t_pop();
+		T_FRAME(
+			const char *text;
+
+			text = t_strdup_printf("Searched %d%% of the mailbox, "
+					       "ETA %d:%02d", (int)percentage,
+					       secs/60, secs%60);
+			box->storage->callbacks->
+				notify_ok(box, text,
+					  box->storage->callback_context);
+		);
 	}
 	ctx->last_notify = ioloop_timeval;
 }
@@ -1001,9 +1003,9 @@
 	while ((ret = box->v.search_next_update_seq(_ctx)) > 0) {
 		mail_set_seq(mail, _ctx->seq);
 
-		t_push();
-		ret = search_match_next(ctx) ? 1 : 0;
-		t_pop();
+		T_FRAME(
+			ret = search_match_next(ctx) ? 1 : 0;
+		);
 
 		mail_search_args_reset(ctx->mail_ctx.args, FALSE);
 
--- a/src/lib-storage/index/index-sort.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/index-sort.c	Wed Dec 05 17:47:44 2007 +0200
@@ -249,7 +249,6 @@
 			      const struct mail_sort_node *n2)
 {
 	enum mail_sort_type sort_type;
-	const char *str1, *str2;
 	uint32_t time1, time2, size1, size2;
 	int ret = 0;
 
@@ -259,14 +258,16 @@
 	case MAIL_SORT_FROM:
 	case MAIL_SORT_TO:
 	case MAIL_SORT_SUBJECT:
-		t_push();
-		str1 = n1->seq == ctx->cache_seq &&
-			ctx->cache_type == sort_type ? ctx->cache_str :
-			sort_header_get(sort_type, ctx->mail, n1->seq);
-		str2 = sort_header_get(sort_type, ctx->mail, n2->seq);
+		T_FRAME_BEGIN {
+			const char *str1, *str2;
 
-		ret = strcmp(str1, str2);
-		t_pop();
+			str1 = n1->seq == ctx->cache_seq &&
+				ctx->cache_type == sort_type ? ctx->cache_str :
+				sort_header_get(sort_type, ctx->mail, n1->seq);
+			str2 = sort_header_get(sort_type, ctx->mail, n2->seq);
+
+			ret = strcmp(str1, str2);
+		} T_FRAME_END;
 		break;
 	case MAIL_SORT_ARRIVAL:
 		if (n1->seq == ctx->cache_seq && ctx->cache_type == sort_type)
@@ -367,7 +368,7 @@
 	}
 }
 
-static int
+static bool
 index_sort_add_ids_range(struct mail_search_sort_program *program,
 			 struct mail *mail, unsigned int idx1,
 			 unsigned int idx2)
@@ -379,9 +380,7 @@
 	string_t *prev_str;
 	const char *str;
 	unsigned int skip;
-	int ret = 1;
 
-	t_push();
 	nodes = array_get_modifiable(&program->all_nodes, &count);
 	if (nodes[idx2].sort_id != 0) {
 		i_assert(idx1 != idx2);
@@ -421,8 +420,7 @@
 			if (nodes[i].sort_id == last_id) {
 				/* we ran out of ID space. have to renumber
 				   the IDs. */
-				ret = 0;
-				break;
+				return FALSE;
 			}
 
 			prev_id = nodes[i].sort_id;
@@ -430,8 +428,7 @@
 			str_append(prev_str, str);
 		}
 	}
-	t_pop();
-	return ret;
+	return TRUE;
 }
 
 static void
@@ -494,19 +491,24 @@
 {
 	const struct mail_sort_node *nodes;
 	unsigned int i, j, count;
+	bool ret;
 
 	nodes = array_get(&program->all_nodes, &count);
 	for (i = 0; i < count; i++) {
-		if (nodes[i].sort_id == 0) {
-			for (j = i + 1; j < count; j++) {
-				if (nodes[j].sort_id != 0)
-					break;
-			}
-			if (index_sort_add_ids_range(program, mail,
-						     i == 0 ? 0 : i-1,
-						     I_MIN(j, count-1)) == 0)
-				index_sort_renumber_ids(program, i-1);
+		if (nodes[i].sort_id != 0)
+			continue;
+
+		for (j = i + 1; j < count; j++) {
+			if (nodes[j].sort_id != 0)
+				break;
 		}
+		T_FRAME(
+			ret = index_sort_add_ids_range(program, mail,
+						       I_MAX(i, 1)-1,
+						       I_MIN(j, count-1));
+		);
+		if (!ret)
+			index_sort_renumber_ids(program, i-1);
 	}
 }
 
--- a/src/lib-storage/index/index-storage.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/index-storage.c	Wed Dec 05 17:47:44 2007 +0200
@@ -513,19 +513,15 @@
 			   const char *const keywords[])
 {
 	ARRAY_DEFINE(valid_keywords, const char *);
-	struct mail_keywords *kw;
 	const char *error;
 
-	t_push();
 	t_array_init(&valid_keywords, 32);
 	for (; *keywords != NULL; keywords++) {
 		if (index_mailbox_keyword_is_valid(ibox, *keywords, &error))
 			array_append(&valid_keywords, keywords, 1);
 	}
 	(void)array_append_space(&valid_keywords); /* NULL-terminate */
-	kw = mail_index_keywords_create(ibox->index, keywords);
-	t_pop();
-	return kw;
+	return mail_index_keywords_create(ibox->index, keywords);
 }
 
 int index_keywords_create(struct mailbox *_box, const char *const keywords[],
@@ -539,15 +535,18 @@
 		if (index_mailbox_keyword_is_valid(ibox, keywords[i], &error))
 			continue;
 
-		if (skip_invalid) {
-			/* found invalid keywords, do this the slow
-			   way */
-			*keywords_r =
-				index_keywords_create_skip(ibox, keywords);
-			return 0;
+		if (!skip_invalid) {
+			mail_storage_set_error(_box->storage,
+					       MAIL_ERROR_PARAMS, error);
+			return -1;
 		}
-		mail_storage_set_error(_box->storage, MAIL_ERROR_PARAMS, error);
-		return -1;
+
+		/* found invalid keywords, do this the slow way */
+		T_FRAME(
+			*keywords_r = index_keywords_create_skip(ibox,
+								 keywords);
+		);
+		return 0;
 	}
 
 	*keywords_r = mail_index_keywords_create(ibox->index, keywords);
--- a/src/lib-storage/index/maildir/maildir-copy.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Wed Dec 05 17:47:44 2007 +0200
@@ -225,10 +225,10 @@
 	if (mbox->storage->copy_with_hardlinks &&
 	    mail->box->storage == mbox->ibox.box.storage &&
 	    maildir_compatible_file_modes(&mbox->ibox.box, mail->box)) {
-		t_push();
-		ret = maildir_copy_hardlink(t, mail, flags,
-					    keywords, dest_mail);
-		t_pop();
+		T_FRAME(
+			ret = maildir_copy_hardlink(t, mail, flags,
+						    keywords, dest_mail);
+		);
 
 		if (ret > 0)
 			return 0;
--- a/src/lib-storage/index/maildir/maildir-keywords.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-keywords.c	Wed Dec 05 17:47:44 2007 +0200
@@ -412,9 +412,9 @@
 
 	*_ctx = NULL;
 
-	t_push();
-	(void)maildir_keywords_commit(ctx->mk);
-	t_pop();
+	T_FRAME(
+		(void)maildir_keywords_commit(ctx->mk);
+	);
 
 	array_free(&ctx->idx_to_chr);
 	i_free(ctx);
--- a/src/lib-storage/index/maildir/maildir-save.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-save.c	Wed Dec 05 17:47:44 2007 +0200
@@ -72,8 +72,6 @@
 	const char *tmp_path, *new_path;
 	int ret;
 
-	t_push();
-
 	/* if we have flags, we'll move it to cur/ directly, because files in
 	   new/ directory can't have flags. alternative would be to write it
 	   in new/ and set the flags dirty in index file, but in that case
@@ -106,7 +104,6 @@
 				tmp_path, new_path);
 		}
 	}
-	t_pop();
 	return ret;
 }
 
@@ -359,39 +356,40 @@
 		(struct maildir_transaction_context *)_t;
 	struct maildir_save_context *ctx;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->ictx.ibox;
-	const char *fname;
 
 	i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
 
-	t_push();
-
 	if (t->save_ctx == NULL)
 		t->save_ctx = maildir_save_transaction_init(t);
 	ctx = t->save_ctx;
 
-	/* create a new file in tmp/ directory */
-	ctx->fd = maildir_create_tmp(mbox, ctx->tmpdir, &fname);
-	if (ctx->fd == -1) {
-		ctx->failed = TRUE;
-		t_pop();
+	flags &= ~MAIL_RECENT;
+	if (mbox->ibox.keep_recent)
+		flags |= MAIL_RECENT;
+
+	T_FRAME(
+		/* create a new file in tmp/ directory */
+		const char *fname;
+
+		ctx->fd = maildir_create_tmp(mbox, ctx->tmpdir, &fname);
+		if (ctx->fd == -1)
+			ctx->failed = TRUE;
+		else {
+			ctx->received_date = received_date;
+			ctx->input = (ctx->mbox->storage->storage.flags &
+				      MAIL_STORAGE_FLAG_SAVE_CRLF) != 0 ?
+				i_stream_create_crlf(input) :
+				i_stream_create_lf(input);
+
+			maildir_save_add(t, fname, flags, keywords, dest_mail);
+		}
+	);
+	if (ctx->failed)
 		return -1;
-	}
-
-	ctx->received_date = received_date;
-	ctx->input = (ctx->mbox->storage->storage.flags &
-		      MAIL_STORAGE_FLAG_SAVE_CRLF) != 0 ?
-		i_stream_create_crlf(input) : i_stream_create_lf(input);
 
 	ctx->output = o_stream_create_fd_file(ctx->fd, 0, FALSE);
 	o_stream_cork(ctx->output);
 
-	flags &= ~MAIL_RECENT;
-	if (mbox->ibox.keep_recent)
-		flags |= MAIL_RECENT;
-
-	maildir_save_add(t, fname, flags, keywords, dest_mail);
-
-	t_pop();
 	*ctx_r = &ctx->ctx;
 	return ctx->failed ? -1 : 0;
 }
@@ -425,7 +423,7 @@
 	return 0;
 }
 
-int maildir_save_finish(struct mail_save_context *_ctx)
+static int maildir_save_finish_real(struct mail_save_context *_ctx)
 {
 	struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
 	struct mail_storage *storage = &ctx->mbox->storage->storage;
@@ -440,9 +438,7 @@
 		return -1;
 	}
 
-	t_push();
 	path = t_strconcat(ctx->tmpdir, "/", ctx->file_last->basename, NULL);
-
 	if (o_stream_flush(ctx->output) < 0) {
 		mail_storage_set_critical(storage,
 			"o_stream_flush(%s) failed: %m", path);
@@ -533,16 +529,23 @@
 		ctx->files_tail = fm;
 		ctx->file_last = NULL;
 		ctx->files_count--;
-
-		t_pop();
 		return -1;
 	}
-	t_pop();
 
 	ctx->file_last = NULL;
 	return 0;
 }
 
+int maildir_save_finish(struct mail_save_context *ctx)
+{
+	int ret;
+
+	T_FRAME(
+		ret = maildir_save_finish_real(ctx);
+	);
+	return ret;
+}
+
 void maildir_save_cancel(struct mail_save_context *_ctx)
 {
 	struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
@@ -559,12 +562,11 @@
 
 	/* try to unlink the mails already moved */
 	for (mf = ctx->files; mf != pos; mf = mf->next) {
-		if ((mf->flags & MAILDIR_SAVE_FLAG_DELETED) != 0)
-			continue;
-
-		t_push();
-		(void)unlink(maildir_mf_get_path(ctx, mf));
-		t_pop();
+		if ((mf->flags & MAILDIR_SAVE_FLAG_DELETED) == 0) {
+			T_FRAME(
+				(void)unlink(maildir_mf_get_path(ctx, mf));
+			);
+		}
 	}
 	ctx->files = pos;
 }
@@ -576,7 +578,6 @@
 	struct maildir_filename *mf;
 	uint32_t seq, first_uid, next_uid;
 	enum maildir_uidlist_rec_flag flags;
-	const char *dest;
 	bool newdir, sync_commit = FALSE;
 	int ret;
 
@@ -645,26 +646,33 @@
 	/* move them into new/ and/or cur/ */
 	ret = 0;
 	ctx->moving = TRUE;
-	for (mf = ctx->files; mf != NULL && ret == 0; mf = mf->next) {
-		t_push();
-		newdir = maildir_get_updated_filename(ctx, mf, &dest);
+	for (mf = ctx->files; mf != NULL; mf = mf->next) {
+		T_FRAME(
+			const char *dest;
+
+			newdir = maildir_get_updated_filename(ctx, mf, &dest);
 
-		/* if hardlink-flag is set, the file is already in destination.
-		   if the hardlinked mail contained keywords, it was linked
-		   into tmp/ and it doesn't have the hardlink-flag set, so it's
-		   treated as any other saved mail. */
-		if ((mf->flags & MAILDIR_SAVE_FLAG_HARDLINK) == 0) {
-			ret = maildir_file_move(ctx, mf->basename,
-						dest, newdir);
-		}
-		t_pop();
+			/* if hardlink-flag is set, the file is already in
+			   destination. if the hardlinked mail contained
+			   keywords, it was linked into tmp/ and it doesn't
+			   have the hardlink-flag set, so it's treated as any
+			   other saved mail. */
+			if ((mf->flags & MAILDIR_SAVE_FLAG_HARDLINK) != 0)
+				ret = 0;
+			else {
+				ret = maildir_file_move(ctx, mf->basename,
+							dest, newdir);
+			}
+		);
+		if (ret < 0)
+			break;
 	}
 
 	if (ret == 0 && ctx->uidlist_sync_ctx != NULL) {
 		/* everything was moved successfully. update our internal
 		   state. */
-		for (mf = ctx->files; mf != NULL; mf = mf->next) {
-			t_push();
+		for (mf = ctx->files; mf != NULL; mf = mf->next) T_FRAME_BEGIN {
+			const char *dest;
 			newdir = maildir_get_updated_filename(ctx, mf, &dest);
 
 			flags = MAILDIR_UIDLIST_REC_FLAG_RECENT;
@@ -673,8 +681,7 @@
 			ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
 							dest, flags);
 			i_assert(ret > 0);
-			t_pop();
-		}
+		} T_FRAME_END;
 	}
 
 	if (ctx->uidlist_sync_ctx != NULL) {
@@ -723,7 +730,8 @@
 	pool_unref(&ctx->pool);
 }
 
-void maildir_transaction_save_rollback(struct maildir_save_context *ctx)
+static void
+maildir_transaction_save_rollback_real(struct maildir_save_context *ctx)
 {
 	struct maildir_filename *mf;
 	string_t *str;
@@ -735,9 +743,7 @@
 	if (!ctx->finished)
 		maildir_save_cancel(&ctx->ctx);
 
-	t_push();
 	str = t_str_new(1024);
-
 	str_append(str, ctx->tmpdir);
 	str_append_c(str, '/');
         dir_len = str_len(str);
@@ -764,9 +770,14 @@
 	if (ctx->sync_ctx != NULL)
 		(void)maildir_sync_index_finish(&ctx->sync_ctx, TRUE, FALSE);
 
-	t_pop();
-
 	if (ctx->mail != NULL)
 		mail_free(&ctx->mail);
 	pool_unref(&ctx->pool);
 }
+
+void maildir_transaction_save_rollback(struct maildir_save_context *ctx)
+{
+	T_FRAME(
+		maildir_transaction_save_rollback_real(ctx);
+	);
+}
--- a/src/lib-storage/index/maildir/maildir-storage.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Wed Dec 05 17:47:44 2007 +0200
@@ -150,21 +150,22 @@
 						 const char *name)
 {
 	struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(list);
-	const char *const *tmp;
 	bool ret = TRUE;
 
 	if (!storage->list_module_ctx.super.is_valid_create_name(list, name))
 		return FALSE;
 
 	/* Don't allow creating mailboxes under cur/new/tmp */
-	t_push();
-	for (tmp = t_strsplit(name, "/"); *tmp != NULL; tmp++) {
-		if (maildir_is_internal_name(*tmp)) {
-			ret = FALSE;
-			break;
+	T_FRAME(
+		const char *const *tmp;
+
+		for (tmp = t_strsplit(name, "/"); *tmp != NULL; tmp++) {
+			if (maildir_is_internal_name(*tmp)) {
+				ret = FALSE;
+				break;
+			}
 		}
-	}
-	t_pop();
+	);
 	return ret;
 }
 
@@ -384,7 +385,6 @@
 	struct stat st;
 	pool_t pool;
 
-	t_push();
 	path = mailbox_list_get_path(storage->storage.list, name,
 				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
 	control_dir = mailbox_list_get_path(storage->storage.list, name,
@@ -432,7 +432,6 @@
 			struct mailbox *box = &mbox->ibox.box;
 
 			mailbox_close(&box);
-			t_pop();
 			return NULL;
 		}
 		mbox->keep_lock_to = timeout_add(MAILDIR_LOCK_TOUCH_SECS * 1000,
@@ -445,7 +444,6 @@
 		mbox->ibox.readonly = TRUE;
 
 	mbox->keywords = maildir_keywords_init(mbox);
-	t_pop();
 	return &mbox->ibox.box;
 }
 
@@ -837,7 +835,6 @@
 {
 	struct stat st;
 	const char *path;
-	int ret;
 
 	if (maildir_is_internal_name(fname)) {
 		*flags_r = MAILBOX_NONEXISTENT;
@@ -857,29 +854,26 @@
 		break;
 	}
 
-	t_push();
 	path = t_strdup_printf("%s/%s", dir, fname);
 	if (stat(path, &st) == 0) {
 		if (S_ISDIR(st.st_mode))
-			ret = 1;
+			return 1;
 		else if (strncmp(fname, ".nfs", 4) == 0) {
 			/* temporary NFS file */
 			*flags_r = MAILBOX_NONEXISTENT;
-			ret = 0;
+			return 0;
 		} else {
 			*flags_r = MAILBOX_NOSELECT;
-			ret = 0;
+			return 0;
 		}
 	} else if (errno == ENOENT) {
 		/* this was a directory. maybe it has children. */
 		*flags_r = MAILBOX_NOSELECT;
-		ret = 1;
+		return 1;
 	} else {
 		*flags_r = MAILBOX_NOSELECT;
-		ret = 0;
+		return 0;
 	}
-	t_pop();
-	return ret;
 }
 
 static int
@@ -901,12 +895,10 @@
 		   or the process trying to delete it had died.
 		   delete it ourself if it's been there longer than
 		   one hour. */
-		t_push();
 		path = t_strdup_printf("%s/%s", dir, fname);
 		if (stat(path, &st) == 0 &&
 		    st.st_mtime < ioloop_time - 3600)
 			(void)unlink_directory(path, TRUE);
-		t_pop();
 
 		*flags_r = MAILBOX_NONEXISTENT;
 		return 0;
@@ -936,7 +928,6 @@
 		const char *path;
 		struct stat st;
 
-		t_push();
 		/* if fname="", we're checking if a base maildir has INBOX */
 		path = *fname == '\0' ? t_strdup_printf("%s/cur", dir) :
 			t_strdup_printf("%s/%s", dir, fname);
@@ -958,7 +949,6 @@
 			*flags_r = MAILBOX_NOSELECT;
 			ret = 0;
 		}
-		t_pop();
 	} else {
 		ret = 1;
 	}
--- a/src/lib-storage/index/maildir/maildir-sync.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Wed Dec 05 17:47:44 2007 +0200
@@ -278,21 +278,17 @@
 	const char *fname1, *path1, *path2;
 	const char *new_fname, *new_path;
 	struct stat st1, st2;
-	int ret = 0;
 
 	fname1 = maildir_uidlist_sync_get_full_filename(ctx->uidlist_sync_ctx,
 							fname2);
 	i_assert(fname1 != NULL);
 
-	t_push();
-
 	path1 = t_strconcat(dir, "/", fname1, NULL);
 	path2 = t_strconcat(dir, "/", fname2, NULL);
 
 	if (stat(path1, &st1) < 0 || stat(path2, &st2) < 0) {
 		/* most likely the files just don't exist anymore.
 		   don't really care about other errors much. */
-		t_pop();
 		return 0;
 	}
 	if (st1.st_ino == st2.st_ino &&
@@ -320,7 +316,6 @@
 					"unlink(%s) failed: %m", path2);
 			}
 		}
-		t_pop();
 		return 0;
 	}
 
@@ -333,11 +328,9 @@
 		mail_storage_set_critical(&ctx->mbox->storage->storage,
 			"Couldn't fix a duplicate: rename(%s, %s) failed: %m",
 			path2, new_path);
-		ret = -1;
+		return -1;
 	}
-	t_pop();
-
-	return ret;
+	return 0;
 }
 
 static int
@@ -425,7 +418,6 @@
 #endif
 	}
 
-	t_push();
 	src = t_str_new(1024);
 	dest = t_str_new(1024);
 
@@ -488,10 +480,12 @@
 				break;
 
 			/* possibly duplicate - try fixing it */
-			if (maildir_fix_duplicate(ctx, path, dp->d_name) < 0) {
-				ret = -1;
+			T_FRAME(
+				ret = maildir_fix_duplicate(ctx, path,
+							    dp->d_name);
+			);
+			if (ret < 0)
 				break;
-			}
 		}
 	}
 
@@ -514,7 +508,6 @@
 			ctx->mbox->maildir_hdr.cur_mtime = now;
 	}
 
-	t_pop();
 	return ret < 0 ? -1 :
 		(move_count <= MAILDIR_RENAME_RESCAN_COUNT ? 0 : 1);
 }
@@ -846,19 +839,20 @@
 	bool lost_files;
 	int ret;
 
-	t_push();
-	ctx = maildir_sync_context_new(mbox, MAILBOX_SYNC_FLAG_FAST);
-	ret = maildir_sync_context(ctx, TRUE, &uid, &lost_files);
-	maildir_sync_deinit(ctx);
-	t_pop();
+	T_FRAME(
+		ctx = maildir_sync_context_new(mbox, MAILBOX_SYNC_FLAG_FAST);
+		ret = maildir_sync_context(ctx, TRUE, &uid, &lost_files);
+		maildir_sync_deinit(ctx);
+	);
 
 	if (uid != 0) {
 		/* maybe it's expunged. check again. */
-		t_push();
-		ctx = maildir_sync_context_new(mbox, 0);
-		ret = maildir_sync_context(ctx, TRUE, NULL, &lost_files);
-		maildir_sync_deinit(ctx);
-		t_pop();
+		T_FRAME(
+			ctx = maildir_sync_context_new(mbox, 0);
+			ret = maildir_sync_context(ctx, TRUE, NULL,
+						   &lost_files);
+			maildir_sync_deinit(ctx);
+		);
 	}
 	return ret;
 }
@@ -879,11 +873,12 @@
 	    ioloop_time) {
 		mbox->ibox.sync_last_check = ioloop_time;
 
-		t_push();
-		ctx = maildir_sync_context_new(mbox, flags);
-		ret = maildir_sync_context(ctx, FALSE, NULL, &lost_files);
-		maildir_sync_deinit(ctx);
-		t_pop();
+		T_FRAME(
+			ctx = maildir_sync_context_new(mbox, flags);
+			ret = maildir_sync_context(ctx, FALSE, NULL,
+						   &lost_files);
+			maildir_sync_deinit(ctx);
+		);
 
 		i_assert(!maildir_uidlist_is_locked(mbox->uidlist) ||
 			 mbox->ibox.keep_locked);
@@ -899,16 +894,17 @@
 
 int maildir_sync_is_synced(struct maildir_mailbox *mbox)
 {
-	const char *new_dir, *cur_dir;
 	bool new_changed, cur_changed;
 	int ret;
 
-	t_push();
-	new_dir = t_strconcat(mbox->path, "/new", NULL);
-	cur_dir = t_strconcat(mbox->path, "/cur", NULL);
+	T_FRAME_BEGIN {
+		const char *new_dir, *cur_dir;
 
-	ret = maildir_sync_quick_check(mbox, new_dir, cur_dir,
-				       &new_changed, &cur_changed);
-	t_pop();
+		new_dir = t_strconcat(mbox->path, "/new", NULL);
+		cur_dir = t_strconcat(mbox->path, "/cur", NULL);
+
+		ret = maildir_sync_quick_check(mbox, new_dir, cur_dir,
+					       &new_changed, &cur_changed);
+	} T_FRAME_END;
 	return ret < 0 ? -1 : (!new_changed && !cur_changed);
 }
--- a/src/lib-storage/index/maildir/maildir-uidlist.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Wed Dec 05 17:47:44 2007 +0200
@@ -313,7 +313,6 @@
 	const char *start, *line = *line_p;
 	buffer_t *buf;
 
-	t_push();
 	buf = buffer_create_dynamic(pool_datastack_create(), 128);
 	while (*line != '\0' && *line != ':') {
 		/* skip over an extension field */
@@ -330,7 +329,6 @@
 		rec->extensions = p_malloc(uidlist->record_pool, buf->used);
 		memcpy(rec->extensions, buf->data, buf->used);
 	}
-	t_pop();
 
 	if (*line == ':')
 		line++;
@@ -389,7 +387,13 @@
 
 	if (uidlist->version == 3) {
 		/* read extended fields */
-		if (!maildir_uidlist_read_extended(uidlist, &line, rec)) {
+		bool ret;
+
+		T_FRAME(
+			ret = maildir_uidlist_read_extended(uidlist, &line,
+							    rec);
+		);
+		if (!ret) {
 			mail_storage_set_critical(storage,
 				"Invalid data in file %s", uidlist->path);
 			return 0;
@@ -421,7 +425,7 @@
 	struct mail_storage *storage = uidlist->ibox->box.storage;
 	unsigned int uid_validity, next_uid;
 	string_t *ext_hdr;
-	const char *line, *value;
+	const char *line;
 	char key;
 
 	line = i_stream_read_next_line(input);
@@ -459,8 +463,9 @@
 	case 3:
 		ext_hdr = uidlist->hdr_extensions;
 		str_truncate(ext_hdr, 0);
-		while (*line != '\0') {
-			t_push();
+		while (*line != '\0') T_FRAME_BEGIN {
+			const char *value;
+
 			key = *line;
 			value = ++line;
 			while (*line != '\0' && *line != ' ') line++;
@@ -481,8 +486,7 @@
 			}
 
 			while (*line == ' ') line++;
-			t_pop();
-		}
+		} T_FRAME_END;
 		break;
 	default:
 		mail_storage_set_critical(storage, "%s: Unsupported version %u",
@@ -821,7 +825,8 @@
 		uidlist->next_uid = next_uid;
 }
 
-void maildir_uidlist_set_ext(struct maildir_uidlist *uidlist, uint32_t uid,
+static void
+maildir_uidlist_set_ext_real(struct maildir_uidlist *uidlist, uint32_t uid,
 			     enum maildir_uidlist_rec_ext_key key,
 			     const char *value)
 {
@@ -834,7 +839,6 @@
 	rec = maildir_uidlist_lookup_rec(uidlist, uid, &idx);
 	i_assert(rec != NULL);
 
-	t_push();
 	buf = buffer_create_dynamic(pool_datastack_create(), 128);
 
 	/* copy existing extensions, except for the one we're updating */
@@ -856,7 +860,15 @@
 	memcpy(rec->extensions, buf->data, buf->used);
 
 	uidlist->recreate = TRUE;
-	t_pop();
+}
+
+void maildir_uidlist_set_ext(struct maildir_uidlist *uidlist, uint32_t uid,
+			     enum maildir_uidlist_rec_ext_key key,
+			     const char *value)
+{
+	T_FRAME(
+		maildir_uidlist_set_ext_real(uidlist, uid, key, value);
+	);
 }
 
 static int maildir_uidlist_write_fd(struct maildir_uidlist *uidlist, int fd,
@@ -1379,9 +1391,9 @@
 		maildir_uidlist_mark_all(ctx->uidlist, FALSE);
 
 	if ((ctx->changed || ctx->uidlist->recreate) && !ctx->failed) {
-		t_push();
-		ret = maildir_uidlist_sync_update(ctx);
-		t_pop();
+		T_FRAME(
+			ret = maildir_uidlist_sync_update(ctx);
+		);
 	}
 
 	if (ctx->locked)
--- a/src/lib-storage/index/maildir/maildir-util.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-util.c	Wed Dec 05 17:47:44 2007 +0200
@@ -19,7 +19,7 @@
 static int maildir_file_do_try(struct maildir_mailbox *mbox, uint32_t uid,
 			       maildir_file_do_func *callback, void *context)
 {
-	const char *fname, *path;
+	const char *fname;
         enum maildir_uidlist_rec_flag flags;
 	int ret;
 
@@ -27,20 +27,24 @@
 	if (fname == NULL)
 		return -2; /* expunged */
 
-	t_push();
 	if ((flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
 		/* probably in new/ dir */
-		path = t_strconcat(mbox->path, "/new/", fname, NULL);
-		ret = callback(mbox, path, context);
-		if (ret != 0) {
-			t_pop();
+		T_FRAME(
+			const char *path;
+
+			path = t_strconcat(mbox->path, "/new/", fname, NULL);
+			ret = callback(mbox, path, context);
+		);
+		if (ret != 0)
 			return ret;
-		}
 	}
 
-	path = t_strconcat(mbox->path, "/cur/", fname, NULL);
-	ret = callback(mbox, path, context);
-	t_pop();
+	T_FRAME(
+		const char *path;
+
+		path = t_strconcat(mbox->path, "/cur/", fname, NULL);
+		ret = callback(mbox, path, context);
+	);
 	return ret;
 }
 
@@ -84,7 +88,8 @@
 	return ret == -2 ? 0 : ret;
 }
 
-void maildir_tmp_cleanup(struct mail_storage *storage, const char *dir)
+static void
+maildir_tmp_cleanup_real(struct mail_storage *storage, const char *dir)
 {
 	DIR *dirp;
 	struct dirent *d;
@@ -101,7 +106,6 @@
 		return;
 	}
 
-	t_push();
 	path = t_str_new(256);
 	str_printfa(path, "%s/", dir);
 	dir_len = str_len(path);
@@ -129,7 +133,6 @@
 			}
 		}
 	}
-	t_pop();
 
 #ifdef HAVE_DIRFD
 	if (fstat(dirfd(dirp), &st) < 0) {
@@ -156,6 +159,13 @@
 	}
 }
 
+void maildir_tmp_cleanup(struct mail_storage *storage, const char *dir)
+{
+	T_FRAME(
+		maildir_tmp_cleanup_real(storage, dir);
+	);
+}
+
 static int maildir_create_subdirs(struct maildir_mailbox *mbox)
 {
 	static const char *subdirs[] = { "cur", "new", "tmp" };
@@ -165,7 +175,6 @@
 	const char *path;
 	unsigned int i;
 
-	t_push();
 	/* @UNSAFE: get a list of directories we want to create */
 	for (i = 0; i < N_ELEMENTS(subdirs); i++)
 		dirs[i] = t_strconcat(mbox->path, "/", subdirs[i], NULL);
@@ -196,7 +205,6 @@
 			break;
 		}
 	}
-	t_pop();
 	return i == N_ELEMENTS(dirs) ? 0 : -1;
 }
 
@@ -204,6 +212,7 @@
 {
 	struct mailbox *box = &mbox->ibox.box;
 	struct stat st;
+	int ret;
 
 	if (stat(mbox->path, &st) < 0) {
 		if (errno == ENOENT)
@@ -216,5 +225,8 @@
 	}
 	/* maildir itself exists. create all of its subdirectories in case
 	   they got lost. */
-	return maildir_create_subdirs(mbox) < 0 ? TRUE : FALSE;
+	T_FRAME(
+		ret = maildir_create_subdirs(mbox);
+	);
+	return ret < 0 ? TRUE : FALSE;
 }
--- a/src/lib-storage/index/mbox/mbox-save.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/mbox/mbox-save.c	Wed Dec 05 17:47:44 2007 +0200
@@ -115,7 +115,7 @@
 static int write_from_line(struct mbox_save_context *ctx, time_t received_date,
 			   const char *from_envelope)
 {
-	const char *line, *name;
+	const char *name;
 	int ret;
 
 	if (*my_hostdomain == '\0') {
@@ -132,19 +132,21 @@
 		i_strocpy(my_hostdomain, name, sizeof(my_hostdomain));
 	}
 
-	t_push();
-	if (from_envelope == NULL) {
-		from_envelope =
-			t_strconcat(ctx->mbox->storage->storage.user,
-				    "@", my_hostdomain, NULL);
-	}
+	T_FRAME(
+		const char *line;
 
-	/* save in local timezone, no matter what it was given with */
-	line = mbox_from_create(from_envelope, received_date);
+		if (from_envelope == NULL) {
+			from_envelope =
+				t_strconcat(ctx->mbox->storage->storage.user,
+					    "@", my_hostdomain, NULL);
+		}
 
-	if ((ret = o_stream_send_str(ctx->output, line)) < 0)
-		write_error(ctx);
-	t_pop();
+		/* save in local timezone, no matter what it was given with */
+		line = mbox_from_create(from_envelope, received_date);
+
+		if ((ret = o_stream_send_str(ctx->output, line)) < 0)
+			write_error(ctx);
+	);
 
 	return ret;
 }
@@ -355,7 +357,6 @@
 	string_t *str;
 	void *randbuf;
 
-	t_push();
 	buf = buffer_create_dynamic(pool_datastack_create(), 256);
 	buffer_append(buf, &ioloop_time, sizeof(ioloop_time));
 	buffer_append(buf, &ioloop_timeval.tv_usec,
@@ -372,7 +373,6 @@
 	str_append_c(str, '\n');
 
 	ctx->x_delivery_id_header = i_strdup(str_c(str));
-	t_pop();
 }
 
 static struct istream *
@@ -395,7 +395,9 @@
 		   our own X-Delivery-ID header. */
 		const char *hdr;
 
-		mbox_save_x_delivery_id(ctx);
+		T_FRAME(
+			mbox_save_x_delivery_id(ctx);
+		);
 		hdr = ctx->x_delivery_id_header;
 
 		streams[0] = i_stream_create_from_data(hdr, strlen(hdr));
@@ -655,11 +657,11 @@
 
 	ctx->finished = TRUE;
 	if (!ctx->failed) {
-		t_push();
-		if (mbox_write_content_length(ctx) < 0 ||
-		    mbox_append_lf(ctx) < 0)
-			ctx->failed = TRUE;
-		t_pop();
+		T_FRAME(
+			if (mbox_write_content_length(ctx) < 0 ||
+			    mbox_append_lf(ctx) < 0)
+				ctx->failed = TRUE;
+		);
 	}
 
 	if (ctx->mail != NULL)
--- a/src/lib-storage/index/mbox/mbox-storage.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Wed Dec 05 17:47:44 2007 +0200
@@ -757,7 +757,6 @@
 	const char *path, *root_dir;
 	size_t len;
 	struct stat st;
-	int ret = 1;
 
 	if (strcmp(fname, MBOX_INDEX_DIR_NAME) == 0) {
 		*flags_r = MAILBOX_NOSELECT;
@@ -792,7 +791,6 @@
 	}
 
 	/* need to stat() then */
-	t_push();
 	path = t_strconcat(dir, "/", fname, NULL);
 	if (stat(path, &st) == 0) {
 		if (S_ISDIR(st.st_mode))
@@ -807,18 +805,17 @@
 				*flags_r &= ~MAILBOX_NOINFERIORS;
 			}
 		}
-	} else if (errno == EACCES || errno == ELOOP)
+		return 1;
+	} else if (errno == EACCES || errno == ELOOP) {
 		*flags_r = MAILBOX_NOSELECT;
-	else if (ENOTFOUND(errno)) {
+		return 1;
+	} else if (ENOTFOUND(errno)) {
 		*flags_r = MAILBOX_NONEXISTENT;
-		ret = 0;
+		return 0;
 	} else {
 		mail_storage_set_critical(storage, "stat(%s) failed: %m", path);
-		ret = -1;
+		return -1;
 	}
-	t_pop();
-
-	return ret;
 }
 
 static int mbox_list_delete_mailbox(struct mailbox_list *list,
--- a/src/lib-storage/index/mbox/mbox-sync-parse.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/mbox/mbox-sync-parse.c	Wed Dec 05 17:47:44 2007 +0200
@@ -132,7 +132,6 @@
 		}
 
 		/* add it to index's keyword list if it's not there already */
-		t_push();
 		keyword = t_strndup(hdr->full_value + keyword_start,
 				    pos - keyword_start);
 		if (index_mailbox_keyword_is_valid(&ctx->sync_ctx->mbox->ibox,
@@ -140,8 +139,6 @@
 			mail_index_keyword_lookup_or_create(
 				ctx->sync_ctx->mbox->ibox.index, keyword, &idx);
 		}
-		t_pop();
-
 		count++;
 	}
 
@@ -227,7 +224,9 @@
 	ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] = str_len(ctx->header);
 	ctx->seen_imapbase = TRUE;
 
-	parse_imap_keywords_list(ctx, hdr, i);
+	T_FRAME(
+		parse_imap_keywords_list(ctx, hdr, i);
+	);
 	parse_trailing_whitespace(ctx, hdr);
 	return TRUE;
 }
@@ -244,8 +243,8 @@
 	return TRUE;
 }
 
-static bool parse_x_keywords(struct mbox_sync_mail_context *ctx,
-			     struct message_header_line *hdr)
+static bool parse_x_keywords_real(struct mbox_sync_mail_context *ctx,
+				  struct message_header_line *hdr)
 {
 	ARRAY_TYPE(keyword_indexes) keyword_list;
 	const unsigned int *list;
@@ -258,7 +257,6 @@
 		return FALSE; /* duplicate header, delete */
 
 	/* read keyword indexes to temporary array first */
-	t_push();
 	keyword = t_str_new(128);
 	t_array_init(&keyword_list, 16);
 
@@ -282,7 +280,6 @@
 					       str_c(keyword), &idx)) {
 			/* keyword wasn't found. that means the sent mail
 			   originally contained X-Keywords header. Delete it. */
-			t_pop();
 			return FALSE;
 		}
 
@@ -309,9 +306,18 @@
 
 	ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] = str_len(ctx->header);
 	parse_trailing_whitespace(ctx, hdr);
+	return TRUE;
+}
 
-	t_pop();
-	return TRUE;
+static bool parse_x_keywords(struct mbox_sync_mail_context *ctx,
+			     struct message_header_line *hdr)
+{
+	bool ret;
+
+	T_FRAME(
+		ret = parse_x_keywords_real(ctx, hdr);
+	);
+	return ret;
 }
 
 static bool parse_x_uid(struct mbox_sync_mail_context *ctx,
--- a/src/lib-storage/index/mbox/mbox-sync-update.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/mbox/mbox-sync-update.c	Wed Dec 05 17:47:44 2007 +0200
@@ -322,12 +322,10 @@
 	if (ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] == (size_t)-1)
 		return;
 
-	t_push();
 	str = t_str_new(256);
 	keywords_append(ctx->sync_ctx, str, &ctx->mail.keywords);
 	str_append_c(str, '\n');
 	mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_KEYWORDS], str);
-	t_pop();
 }
 
 static void mbox_sync_update_x_imap_base(struct mbox_sync_mail_context *ctx)
@@ -348,8 +346,6 @@
 	}
 
 	/* a) keyword list changed, b) uid-last didn't use 10 digits */
-	t_push();
-
 	str = t_str_new(200);
 	str_printfa(str, "%u ", sync_ctx->base_uid_validity);
 
@@ -362,7 +358,6 @@
 	str_append_c(str, '\n');
 
         mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_IMAPBASE], str);
-	t_pop();
 }
 
 static void mbox_sync_update_x_uid(struct mbox_sync_mail_context *ctx)
@@ -373,14 +368,12 @@
 	    ctx->mail.uid == ctx->parsed_uid)
 		return;
 
-	t_push();
 	str = t_str_new(64);
 	str_printfa(str, "%u\n", ctx->mail.uid);
 	mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_UID], str);
-	t_pop();
 }
 
-void mbox_sync_update_header(struct mbox_sync_mail_context *ctx)
+static void mbox_sync_update_header_real(struct mbox_sync_mail_context *ctx)
 {
 	uint8_t old_flags;
 	enum mailbox_sync_type sync_type;
@@ -413,7 +406,15 @@
 	ctx->updated = TRUE;
 }
 
-void mbox_sync_update_header_from(struct mbox_sync_mail_context *ctx,
+void mbox_sync_update_header(struct mbox_sync_mail_context *ctx)
+{
+	T_FRAME(
+		mbox_sync_update_header_real(ctx);
+	);
+}
+
+static void
+mbox_sync_update_header_from_real(struct mbox_sync_mail_context *ctx,
 				  const struct mbox_sync_mail *mail)
 {
 	if ((ctx->mail.flags & STATUS_FLAGS_MASK) !=
@@ -461,3 +462,11 @@
 	mbox_sync_update_x_uid(ctx);
 	mbox_sync_add_missing_headers(ctx);
 }
+
+void mbox_sync_update_header_from(struct mbox_sync_mail_context *ctx,
+				  const struct mbox_sync_mail *mail)
+{
+	T_FRAME(
+		mbox_sync_update_header_from_real(ctx, mail);
+	);
+}
--- a/src/lib-storage/index/mbox/mbox-sync.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Wed Dec 05 17:47:44 2007 +0200
@@ -353,7 +353,6 @@
 		idx_mail.flags = rec->flags & ~MAIL_RECENT;
 
 		/* get old keywords */
-		t_push();
 		t_array_init(&idx_mail.keywords, 32);
 		mail_index_lookup_keywords(sync_ctx->sync_view,
 					   sync_ctx->idx_seq,
@@ -398,7 +397,6 @@
 		    !index_keyword_array_cmp(&idx_mail.keywords,
 					     &mail_ctx->mail.keywords))
 			mbox_sync_update_index_keywords(mail_ctx);
-		t_pop();
 
 		/* see if we need to update md5 sum. */
 		if (sync_ctx->mbox->mbox_save_md5 != 0)
@@ -1064,8 +1062,11 @@
 		}
 
 		if (!mail_ctx->mail.pseudo) {
-			if (!expunged)
-				mbox_sync_update_index(mail_ctx, rec);
+			if (!expunged) {
+				T_FRAME(
+					mbox_sync_update_index(mail_ctx, rec);
+				);
+			}
 			sync_ctx->idx_seq++;
 		}
 
--- a/src/lib-storage/index/raw/raw-storage.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/index/raw/raw-storage.c	Wed Dec 05 17:47:44 2007 +0200
@@ -206,7 +206,6 @@
 	struct mail_storage *storage = RAW_LIST_CONTEXT(ctx->list);
 	const char *path;
 	struct stat st;
-	int ret = 1;
 
 	/* try to avoid stat() with these checks */
 	if (type == MAILBOX_LIST_FILE_TYPE_DIR) {
@@ -221,25 +220,23 @@
 	}
 
 	/* need to stat() then */
-	t_push();
 	path = t_strconcat(dir, "/", fname, NULL);
 	if (stat(path, &st) == 0) {
 		if (S_ISDIR(st.st_mode))
 			*flags_r = MAILBOX_NOSELECT | MAILBOX_CHILDREN;
 		else
 			*flags_r = MAILBOX_NOINFERIORS;
-	} else if (errno == EACCES || errno == ELOOP)
+		return 1;
+	} else if (errno == EACCES || errno == ELOOP) {
 		*flags_r = MAILBOX_NOSELECT;
-	else if (ENOTFOUND(errno)) {
+		return 1;
+	} else if (ENOTFOUND(errno)) {
 		*flags_r = MAILBOX_NONEXISTENT;
-		ret = 0;
+		return 0;
 	} else {
 		mail_storage_set_critical(storage, "stat(%s) failed: %m", path);
-		ret = -1;
+		return -1;
 	}
-	t_pop();
-
-	return ret;
 }
 
 static void raw_class_init(void)
--- a/src/lib-storage/list/index-mailbox-list-sync.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/list/index-mailbox-list-sync.c	Wed Dec 05 17:47:44 2007 +0200
@@ -115,9 +115,9 @@
 		return 0;
 	}
 
-	t_push();
-	ret = box->v.list_index_has_changed(box, view, seq);
-	t_pop();
+	T_FRAME(
+		ret = box->v.list_index_has_changed(box, view, seq);
+	);
 	if (ret != 0) {
 		/* error / mailbox has changed. we'll need to sync it. */
 		mail_index_view_close(&view);
--- a/src/lib-storage/list/mailbox-list-fs-iter.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/list/mailbox-list-fs-iter.c	Wed Dec 05 17:47:44 2007 +0200
@@ -134,13 +134,14 @@
 	/* if no patterns have wildcards at this point of the path, we don't
 	   have to readdir() the files. instead we can just go through the
 	   mailboxes listed in patterns. */
-	t_push();
-	patterns = array_idx(&ctx->valid_patterns, 0);
-	for (i = 0; patterns[i] != NULL; i++) {
-		if (pattern_has_wildcard_at(ctx, patterns[i], list_path))
-			break;
-	}
-	t_pop();
+	T_FRAME(
+		patterns = array_idx(&ctx->valid_patterns, 0);
+		for (i = 0; patterns[i] != NULL; i++) {
+			if (pattern_has_wildcard_at(ctx, patterns[i],
+						    list_path))
+				break;
+		}
+	);
 	if (patterns[i] == NULL) {
 		*dirp = NULL;
 		return 1;
@@ -288,11 +289,15 @@
 {
 	struct fs_list_iterate_context *ctx =
 		(struct fs_list_iterate_context *)_ctx;
+	const struct mailbox_info *info;
 
 	if (ctx->ctx.failed)
 		return NULL;
 
-	return ctx->next(ctx);
+	T_FRAME(
+		info = ctx->next(ctx);
+	);
+	return info;
 }
 
 static void
@@ -333,7 +338,6 @@
 	ctx->info.flags = 0;
 	ctx->info.name = "INBOX";
 
-	t_push();
 	inbox_path = mailbox_list_get_path(ctx->ctx.list, "INBOX",
 					   MAILBOX_LIST_PATH_TYPE_DIR);
 	path_split(inbox_path, &dir, &fname);
@@ -341,7 +345,6 @@
 					     MAILBOX_LIST_FILE_TYPE_UNKNOWN,
 					     &ctx->info.flags) < 0)
 		ctx->ctx.failed = TRUE;
-	t_pop();
 
 	ctx->info.flags |= fs_list_get_subscription_flags(ctx, "INBOX");
 	return &ctx->info;
@@ -535,7 +538,6 @@
 		return &ctx->info;
 	}
 
-	t_push();
 	path = mailbox_list_get_path(ctx->ctx.list, ctx->info.name,
 				     MAILBOX_LIST_PATH_TYPE_DIR);
 	path_split(path, &dir, &fname);
@@ -543,7 +545,6 @@
 					     MAILBOX_LIST_FILE_TYPE_UNKNOWN,
 					     &ctx->info.flags) < 0)
 		ctx->ctx.failed = TRUE;
-	t_pop();
 
 	ctx->info.flags |= flags;
 	return &ctx->info;
@@ -568,13 +569,10 @@
 		return readdir(dir->dirp);
 	}
 
-	t_push();
 	for (;;) {
 		patterns = array_idx(&ctx->valid_patterns, 0);
-		if (patterns[dir->pattern_pos] == NULL) {
-			t_pop();
+		if (patterns[dir->pattern_pos] == NULL)
 			return NULL;
-		}
 
 		patterns += dir->pattern_pos;
 		dir->pattern_pos++;
@@ -616,8 +614,6 @@
 		break;
 	}
 
-	t_pop();
-
 	return &dir->dirent;
 }
 
@@ -634,9 +630,9 @@
 	while (ctx->dir != NULL) {
 		/* NOTE: list_file() may change ctx->dir */
 		while ((d = fs_list_dir_next(ctx)) != NULL) {
-			t_push();
-			ret = list_file(ctx, d);
-			t_pop();
+			T_FRAME(
+				ret = list_file(ctx, d);
+			);
 
 			if (ret > 0)
 				return &ctx->info;
--- a/src/lib-storage/list/mailbox-list-maildir-iter.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/list/mailbox-list-maildir-iter.c	Wed Dec 05 17:47:44 2007 +0200
@@ -56,7 +56,6 @@
 		prefix_len = 0;
 	}
 
-	t_push();
 	mailbox_c = str_c(mailbox);
 	while ((p = strrchr(mailbox_c, hierarchy_sep)) != NULL) {
 		str_truncate(mailbox, (size_t) (p-mailbox_c));
@@ -88,7 +87,6 @@
 			node_fix_parents(node);
 		}
 	}
-	t_pop();
 }
 
 static int
@@ -122,7 +120,6 @@
 		strcmp(ctx->ctx.list->name, MAILBOX_LIST_NAME_IMAPDIR) != 0 ?
 		ctx->ctx.list->hierarchy_sep : '\0';
 
-	t_push();
 	mailbox = t_str_new(PATH_MAX);
 	while ((d = readdir(dirp)) != NULL) {
 		const char *fname = d->d_name;
@@ -156,15 +153,16 @@
 
 		/* check if this is an actual mailbox */
 		flags = 0;
-		ret = ctx->ctx.list->v.
-			iter_is_mailbox(&ctx->ctx, ctx->dir, fname,
+		T_FRAME(
+			ret = ctx->ctx.list->v.
+				iter_is_mailbox(&ctx->ctx, ctx->dir, fname,
 					mailbox_list_get_file_type(d), &flags);
-		if (ret < 0) {
-			t_pop();
-			return -1;
+		);
+		if (ret <= 0) {
+			if (ret < 0)
+				return -1;
+			continue;
 		}
-		if (ret == 0)
-			continue;
 
 		/* we know the children flags ourself, so ignore if any of
 		   them were set. */
@@ -172,8 +170,10 @@
 			   MAILBOX_CHILDREN | MAILBOX_NOCHILDREN);
 
 		if ((match & IMAP_MATCH_PARENT) != 0) {
-			maildir_fill_parents(ctx, glob, update_only,
-					     mailbox, flags);
+			T_FRAME(
+				maildir_fill_parents(ctx, glob, update_only,
+						     mailbox, flags);
+			);
 		} else {
 			created = FALSE;
 			node = update_only ?
@@ -194,7 +194,6 @@
 			}
 		}
 	}
-	t_pop();
 
 	if (closedir(dirp) < 0) {
 		mailbox_list_set_critical(ctx->ctx.list,
@@ -241,6 +240,7 @@
         struct imap_match_glob *glob;
 	char sep;
 	pool_t pool;
+	int ret;
 
 	sep = (flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0 ?
 		_list->ns->sep : _list->ns->real_sep;
@@ -272,7 +272,10 @@
 		bool update_only =
 			(flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0;
 
-		if (maildir_fill_readdir(ctx, glob, update_only) < 0) {
+		T_FRAME(
+			ret = maildir_fill_readdir(ctx, glob, update_only);
+		);
+		if (ret < 0) {
 			ctx->ctx.failed = TRUE;
 			return &ctx->ctx;
 		}
--- a/src/lib-storage/list/mailbox-list-maildir.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/list/mailbox-list-maildir.c	Wed Dec 05 17:47:44 2007 +0200
@@ -337,13 +337,10 @@
 	}
 
 	for (i = 0; i < count; i++) {
-		t_push();
-
 		old_listname = t_strconcat(oldname, names[i], NULL);
 		if (strcmp(old_listname, newname) == 0) {
 			/* When doing RENAME "a" "a.b" we see "a.b" here.
 			   We don't want to rename it anymore to "a.b.b". */
-			t_pop();
 			continue;
 		}
 
@@ -367,7 +364,6 @@
 			mailbox_list_set_critical(list,
 				"rename(%s, %s) failed: %m", oldpath, newpath);
 			ret = -1;
-			t_pop();
 			break;
 		}
 
@@ -375,7 +371,6 @@
 				 old_listname, new_listname);
 		(void)rename_dir(list, MAILBOX_LIST_PATH_TYPE_INDEX,
 				 old_listname, new_listname);
-		t_pop();
 	}
 	array_free(&names_arr);
 	pool_unref(&pool);
@@ -412,7 +407,9 @@
 				 oldname, newname);
 
 		found = ret == 0;
-		ret = rename_children(list, oldname, newname);
+		T_FRAME(
+			ret = rename_children(list, oldname, newname);
+		);
 		if (ret < 0)
 			return -1;
 		if (!found && ret == 0) {
--- a/src/lib-storage/list/mailbox-list-subscriptions.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/list/mailbox-list-subscriptions.c	Wed Dec 05 17:47:44 2007 +0200
@@ -6,10 +6,11 @@
 #include "mailbox-list-private.h"
 #include "mailbox-list-subscriptions.h"
 
-int mailbox_list_subscriptions_fill(struct mailbox_list_iterate_context *ctx,
-				    struct mailbox_tree_context *tree_ctx,
-				    struct imap_match_glob *glob,
-				    bool update_only)
+static int
+mailbox_list_subscriptions_fill_real(struct mailbox_list_iterate_context *ctx,
+				     struct mailbox_tree_context *tree_ctx,
+				     struct imap_match_glob *glob,
+				     bool update_only)
 {
 	struct mail_namespace *ns = ctx->list->ns;
 	struct subsfile_list_context *subsfile_ctx;
@@ -17,7 +18,6 @@
 	string_t *vname;
 	bool match_parents;
 
-	t_push();
 	vname = t_str_new(256);
 	path = t_strconcat(ctx->list->set.control_dir != NULL ?
 			   ctx->list->set.control_dir :
@@ -33,7 +33,19 @@
 		mailbox_list_iter_update(ctx, tree_ctx, glob, update_only,
 					 match_parents, name);
 	}
-	t_pop();
-
 	return subsfile_list_deinit(subsfile_ctx);
 }
+
+int mailbox_list_subscriptions_fill(struct mailbox_list_iterate_context *ctx,
+				    struct mailbox_tree_context *tree_ctx,
+				    struct imap_match_glob *glob,
+				    bool update_only)
+{
+	int ret;
+
+	T_FRAME(
+		ret = mailbox_list_subscriptions_fill_real(ctx, tree_ctx, glob,
+							   update_only);
+	);
+	return ret;
+}
--- a/src/lib-storage/mail-namespace.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/mail-namespace.c	Wed Dec 05 17:47:44 2007 +0200
@@ -192,17 +192,17 @@
 
 	/* first try NAMESPACE_* environments */
 	for (i = 1; ; i++) {
-		t_push();
-		data = getenv(t_strdup_printf("NAMESPACE_%u", i));
-		t_pop();
+		T_FRAME(
+			data = getenv(t_strdup_printf("NAMESPACE_%u", i));
+		);
 
 		if (data == NULL)
 			break;
 
-		t_push();
-		*ns_p = namespace_add_env(pool, data, i, user, flags,
-					  lock_method);
-		t_pop();
+		T_FRAME(
+			*ns_p = namespace_add_env(pool, data, i, user, flags,
+						  lock_method);
+		);
 
 		if (*ns_p == NULL)
 			return -1;
@@ -216,8 +216,11 @@
 		namespaces = namespaces_sort(namespaces);
 		*namespaces_r = namespaces;
 
-		if (hook_mail_namespaces_created != NULL)
-			hook_mail_namespaces_created(namespaces);
+		if (hook_mail_namespaces_created != NULL) {
+			T_FRAME(
+				hook_mail_namespaces_created(namespaces);
+			);
+		}
 		return 0;
 	}
 
@@ -250,8 +253,11 @@
 	namespace_init_storage(ns);
 	*namespaces_r = ns;
 
-	if (hook_mail_namespaces_created != NULL)
-		hook_mail_namespaces_created(ns);
+	if (hook_mail_namespaces_created != NULL) {
+		T_FRAME(
+			hook_mail_namespaces_created(ns);
+		);
+	}
 	return 0;
 }
 
--- a/src/lib-storage/mail-storage.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/mail-storage.c	Wed Dec 05 17:47:44 2007 +0200
@@ -247,8 +247,11 @@
 	storage->keyword_max_len = value != NULL ?
 		atoi(value) : DEFAULT_MAX_KEYWORD_LENGTH;
 	
-	if (hook_mail_storage_created != NULL)
-		hook_mail_storage_created(storage);
+	if (hook_mail_storage_created != NULL) {
+		T_FRAME(
+			hook_mail_storage_created(storage);
+		);
+	}
 
 	ns->storage = storage;
 	return 0;
@@ -453,11 +456,11 @@
 		return NULL;
 	}
 
-	t_push();
-	box = storage->v.mailbox_open(storage, name, input, flags);
-	if (hook_mailbox_opened != NULL && box != NULL)
-		hook_mailbox_opened(box);
-	t_pop();
+	T_FRAME(
+		box = storage->v.mailbox_open(storage, name, input, flags);
+		if (hook_mailbox_opened != NULL && box != NULL)
+			hook_mailbox_opened(box);
+	);
 	return box;
 }
 
--- a/src/lib-storage/mailbox-list.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/mailbox-list.c	Wed Dec 05 17:47:44 2007 +0200
@@ -464,7 +464,8 @@
 	}
 }
 
-void mailbox_list_iter_update(struct mailbox_list_iterate_context *ctx,
+static void
+mailbox_list_iter_update_real(struct mailbox_list_iterate_context *ctx,
 			      struct mailbox_tree_context *tree_ctx,
 			      struct imap_match_glob *glob, bool update_only,
 			      bool match_parents, const char *name)
@@ -482,7 +483,6 @@
 	always_flags = MAILBOX_SUBSCRIBED;
 	add_matched = TRUE;
 
-	t_push();
 	for (;;) {
 		created = FALSE;
 		match = imap_match(glob, name);
@@ -524,7 +524,17 @@
 		create_flags &= ~MAILBOX_NOCHILDREN;
 		always_flags = MAILBOX_CHILDREN | MAILBOX_CHILD_SUBSCRIBED;
 	}
-	t_pop();
+}
+
+void mailbox_list_iter_update(struct mailbox_list_iterate_context *ctx,
+			      struct mailbox_tree_context *tree_ctx,
+			      struct imap_match_glob *glob, bool update_only,
+			      bool match_parents, const char *name)
+{
+	T_FRAME(
+		mailbox_list_iter_update_real(ctx, tree_ctx, glob, update_only,
+					      match_parents, name);
+	);
 }
 
 bool mailbox_list_name_is_too_large(const char *name, char sep)
--- a/src/lib-storage/mailbox-tree.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib-storage/mailbox-tree.c	Wed Dec 05 17:47:44 2007 +0200
@@ -59,8 +59,6 @@
 	if (path == NULL)
 		return tree->nodes;
 
-	t_push();
-
 	if (strncasecmp(path, "INBOX", 5) == 0 &&
 	    (path[5] == '\0' || path[5] == tree->separator))
 		path = t_strdup_printf("INBOX%s", path+5);
@@ -106,7 +104,6 @@
 		parent = *node;
 		node = &(*node)->children;
 	}
-	t_pop();
 
 	return *node;
 }
@@ -115,13 +112,23 @@
 mailbox_tree_get(struct mailbox_tree_context *tree, const char *path,
 		 bool *created)
 {
-	return mailbox_tree_traverse(tree, path, TRUE, created);
+	struct mailbox_node *node;
+
+	T_FRAME(
+		node = mailbox_tree_traverse(tree, path, TRUE, created);
+	);
+	return node;
 }
 
 struct mailbox_node *
 mailbox_tree_lookup(struct mailbox_tree_context *tree, const char *path)
 {
-	return mailbox_tree_traverse(tree, path, FALSE, NULL);
+	struct mailbox_node *node;
+
+	T_FRAME(
+		node = mailbox_tree_traverse(tree, path, FALSE, NULL);
+	);
+	return node;
 }
 
 struct mailbox_tree_iterate_context *
--- a/src/lib/compat.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/compat.c	Wed Dec 05 17:47:44 2007 +0200
@@ -60,9 +60,9 @@
 #ifndef HAVE_VSYSLOG
 void my_vsyslog(int priority, const char *format, va_list args)
 {
-	t_push();
-	syslog(priority, "%s", t_strdup_vprintf(format, args));
-	t_pop();
+	DSTACK_FRAME(
+		syslog(priority, "%s", t_strdup_vprintf(format, args));
+	);
 }
 #endif
 
--- a/src/lib/failures.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/failures.c	Wed Dec 05 17:47:44 2007 +0200
@@ -118,7 +118,6 @@
 default_handler(const char *prefix, int fd, const char *format, va_list args)
 {
 	static int recursed = 0;
-	string_t *str;
 	int ret, old_errno = errno;
 
 	if (recursed >= 2) {
@@ -129,17 +128,17 @@
 
 	recursed++;
 
-	t_push();
-	str = t_str_new(256);
-	log_prefix_add(str);
-	str_append(str, prefix);
+	T_FRAME(
+		string_t *str = t_str_new(256);
+		log_prefix_add(str);
+		str_append(str, prefix);
 
-	/* make sure there's no %n in there and fix %m */
-	str_vprintfa(str, printf_format_fix(format), args);
-	str_append_c(str, '\n');
+		/* make sure there's no %n in there and fix %m */
+		str_vprintfa(str, printf_format_fix(format), args);
+		str_append_c(str, '\n');
 
-	ret = log_fd_write(fd, str_data(str), str_len(str));
-	t_pop();
+		ret = log_fd_write(fd, str_data(str), str_len(str));
+	);
 
 	errno = old_errno;
 	recursed--;
@@ -393,17 +392,18 @@
 static int ATTR_FORMAT(2, 0)
 internal_handler(char log_type, const char *format, va_list args)
 {
-	string_t *str;
 	int ret;
 
-	t_push();
-	str = t_str_new(512);
-	str_append_c(str, 1);
-	str_append_c(str, log_type);
-	str_vprintfa(str, format, args);
-	str_append_c(str, '\n');
-	ret = write_full(2, str_data(str), str_len(str));
-	t_pop();
+	T_FRAME(
+		string_t *str;
+
+		str = t_str_new(512);
+		str_append_c(str, 1);
+		str_append_c(str, log_type);
+		str_vprintfa(str, format, args);
+		str_append_c(str, '\n');
+		ret = write_full(2, str_data(str), str_len(str));
+	);
 
 	return ret;
 }
--- a/src/lib/file-copy.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/file-copy.c	Wed Dec 05 17:47:44 2007 +0200
@@ -93,22 +93,23 @@
 
 int file_copy(const char *srcpath, const char *destpath, bool try_hardlink)
 {
-	const char *tmppath;
 	int ret;
 
-	t_push();
-	tmppath = t_strconcat(destpath, ".tmp", NULL);
+	T_FRAME(
+		const char *tmppath;
+
+		tmppath = t_strconcat(destpath, ".tmp", NULL);
 
-	ret = file_copy_to_tmp(srcpath, tmppath, try_hardlink);
-	if (ret > 0) {
-		if (rename(tmppath, destpath) < 0) {
-			i_error("rename(%s, %s) failed: %m", tmppath, destpath);
-			ret = -1;
+		ret = file_copy_to_tmp(srcpath, tmppath, try_hardlink);
+		if (ret > 0) {
+			if (rename(tmppath, destpath) < 0) {
+				i_error("rename(%s, %s) failed: %m",
+					tmppath, destpath);
+				ret = -1;
+			}
 		}
-	}
-	if (ret < 0)
-		(void)unlink(tmppath);
-
-	t_pop();
+		if (ret < 0)
+			(void)unlink(tmppath);
+	);
 	return ret;
 }
--- a/src/lib/file-dotlock.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/file-dotlock.c	Wed Dec 05 17:47:44 2007 +0200
@@ -619,9 +619,9 @@
 	int ret;
 
 	dotlock = file_dotlock_alloc(set);
-	t_push();
-	ret = file_dotlock_create_real(dotlock, path, flags);
-	t_pop();
+	T_FRAME(
+		ret = file_dotlock_create_real(dotlock, path, flags);
+	);
 	if (ret <= 0 || (flags & DOTLOCK_CREATE_FLAG_CHECKONLY) != 0)
 		file_dotlock_free(&dotlock);
 
@@ -694,13 +694,15 @@
 		      struct dotlock **dotlock_r)
 {
 	struct dotlock *dotlock;
-	const char *lock_path;
 	int ret;
 
 	dotlock = file_dotlock_alloc(set);
-	t_push();
-	ret = dotlock_create(path, dotlock, flags, FALSE, &lock_path);
-	t_pop();
+	T_FRAME(
+		const char *lock_path;
+
+		ret = dotlock_create(path, dotlock, flags, FALSE, &lock_path);
+	);
+
 	if (ret <= 0) {
 		file_dotlock_free(&dotlock);
 		*dotlock_r = NULL;
@@ -764,7 +766,6 @@
 {
 	time_t now = time(NULL);
 	struct utimbuf buf;
-	const char *lock_path;
 	int ret = 0;
 
 	if (dotlock->mtime == now)
@@ -773,13 +774,13 @@
 	dotlock->mtime = now;
 	buf.actime = buf.modtime = now;
 
-	t_push();
-	lock_path = file_dotlock_get_lock_path(dotlock);
-	if (utime(lock_path, &buf) < 0) {
-		i_error("utime(%s) failed: %m", lock_path);
-		ret = -1;
-	}
-	t_pop();
+	T_FRAME(
+		const char *lock_path = file_dotlock_get_lock_path(dotlock);
+		if (utime(lock_path, &buf) < 0) {
+			i_error("utime(%s) failed: %m", lock_path);
+			ret = -1;
+		}
+	);
 	return ret;
 }
 
--- a/src/lib/imem.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/imem.c	Wed Dec 05 17:47:44 2007 +0200
@@ -53,22 +53,22 @@
 char *i_strconcat(const char *str1, ...)
 {
 	va_list args;
-        const char *temp;
 	char *ret;
         size_t len;
 
 	va_start(args, str1);
 
-	t_push();
-	temp = vstrconcat(str1, args, &len);
-	if (temp == NULL)
-		ret = NULL;
-	else {
-		t_buffer_alloc(len);
-		ret = p_malloc(default_pool, len);
-		memcpy(ret, temp, len);
-	}
-	t_pop();
+	T_FRAME(
+		const char *temp = vstrconcat(str1, args, &len);
+	
+		if (temp == NULL)
+			ret = NULL;
+		else {
+			t_buffer_alloc(len);
+			ret = p_malloc(default_pool, len);
+			memcpy(ret, temp, len);
+		}
+	);
 
 	va_end(args);
         return ret;
--- a/src/lib/mkdir-parents.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/mkdir-parents.c	Wed Dec 05 17:47:44 2007 +0200
@@ -8,6 +8,7 @@
 int mkdir_parents(const char *path, mode_t mode)
 {
 	const char *p;
+	int ret;
 
 	/* EISDIR check is for BSD/OS which returns it if path contains '/'
 	   at the end and it exists.
@@ -23,12 +24,11 @@
 		if (p == NULL || p == path)
 			return -1; /* shouldn't happen */
 
-		t_push();
-		if (mkdir_parents(t_strdup_until(path, p), mode) < 0) {
-			t_pop();
+		T_FRAME(
+			ret = mkdir_parents(t_strdup_until(path, p), mode);
+		);
+		if (ret < 0)
 			return -1;
-		}
-		t_pop();
 
 		/* should work now */
 		if (mkdir(path, mode) < 0 && errno != EEXIST && errno != EISDIR)
--- a/src/lib/module-dir.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/module-dir.c	Wed Dec 05 17:47:44 2007 +0200
@@ -172,7 +172,6 @@
 	const char *const *names_p, *base_name, *tmp;
 	unsigned int i, count;
 
-	t_push();
 	base_name = module_file_get_name(name);
 	names_p = array_get(names, &count);
 	for (i = 0; i < count; i++) {
@@ -182,15 +181,15 @@
 			i_fatal("Multiple files for module %s: %s/%s, %s/%s",
 				base_name, dir, name, dir, names_p[i]);
 	}
-	t_pop();
 }
 
-struct module *module_dir_load(const char *dir, const char *module_names,
-			       bool require_init_funcs, const char *version)
+static struct module *
+module_dir_load_real(const char *dir, const char *module_names,
+		     bool require_init_funcs, const char *version)
 {
 	DIR *dirp;
 	struct dirent *d;
-	const char *name, *path, *p, *stripped_name, **names_p;
+	const char *name, *p, **names_p;
 	const char **module_names_arr;
 	struct module *modules, *module, **module_pos;
 	unsigned int i, count;
@@ -226,7 +225,9 @@
 		if (p == NULL || strlen(p) != 3)
 			continue;
 
-		check_duplicates(&names, name, dir);
+		T_FRAME(
+			check_duplicates(&names, name, dir);
+		);
 
 		name = p_strdup(pool, d->d_name);
 		array_append(&names, &name, 1);
@@ -235,7 +236,6 @@
 	names_p = array_get_modifiable(&names, &count);
 	qsort(names_p, count, sizeof(const char *), module_name_cmp);
 
-	t_push();
 	if (module_names == NULL)
 		module_names_arr = NULL;
 	else {
@@ -249,10 +249,10 @@
 	}
 
 	module_pos = &modules;
-	for (i = 0; i < count; i++) {
+	for (i = 0; i < count; i++) T_FRAME_BEGIN {
 		const char *name = names_p[i];
+		const char *path, *stripped_name;
 
-		t_push();
 		stripped_name = module_file_get_name(name);
 		if (!module_want_load(module_names_arr, stripped_name))
 			module = NULL;
@@ -263,13 +263,13 @@
 			if (module == NULL && module_names_arr != NULL)
 				i_fatal("Couldn't load required plugins");
 		}
-		t_pop();
 
 		if (module != NULL) {
 			*module_pos = module;
 			module_pos = &module->next;
 		}
-	}
+	} T_FRAME_END;
+
 	if (module_names_arr != NULL) {
 		/* make sure all modules were found */
 		for (; *module_names_arr != NULL; module_names_arr++) {
@@ -279,7 +279,6 @@
 			}
 		}
 	}
-	t_pop();
 	pool_unref(&pool);
 
 	if (closedir(dirp) < 0)
@@ -288,13 +287,28 @@
 	return modules;
 }
 
+struct module *module_dir_load(const char *dir, const char *module_names,
+			       bool require_init_funcs, const char *version)
+{
+	struct module *modules;
+
+	T_FRAME(
+		modules = module_dir_load_real(dir, module_names,
+					       require_init_funcs, version);
+	);
+	return modules;
+}
+
 void module_dir_init(struct module *modules)
 {
 	struct module *module;
 
 	for (module = modules; module != NULL; module = module->next) {
-		if (module->init != NULL)
-			module->init();
+		if (module->init != NULL) {
+			T_FRAME(
+				module->init();
+			);
+		}
 	}
 }
 
@@ -310,20 +324,22 @@
 		return;
 
 	/* @UNSAFE: deinitialize in reverse order */
-	t_push();
-	rev = t_new(struct module *, count);
-	for (i = 0, module = modules; i < count; i++, module = module->next)
-		rev[count-i-1] = module;
+	T_FRAME(
+		rev = t_new(struct module *, count);
+		for (i = 0, module = modules; i < count; i++) {
+			rev[count-i-1] = module;
+			module = module->next;
+		}
 
-	for (i = 0; i < count; i++) {
-		module = rev[i];
+		for (i = 0; i < count; i++) {
+			module = rev[i];
 
-		if (module->deinit != NULL) {
-			module->deinit();
-			module->deinit = NULL;
+			if (module->deinit != NULL) {
+				module->deinit();
+				module->deinit = NULL;
+			}
 		}
-	}
-	t_pop();
+	);
 }
 
 void module_dir_unload(struct module **modules)
--- a/src/lib/nfs-workarounds.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/nfs-workarounds.c	Wed Dec 05 17:47:44 2007 +0200
@@ -50,7 +50,6 @@
         unsigned int i;
 	int ret;
 
-        t_push();
         for (i = 1;; i++) {
 		ret = callback(path, context);
                 if (ret == 0 || errno != ESTALE || i == NFS_ESTALE_RETRY_COUNT)
@@ -61,7 +60,6 @@
 		   file handle and try again */
 		nfs_flush_file_handle_cache(path);
         }
-        t_pop();
         return ret;
 }
 
@@ -314,11 +312,9 @@
 	p = strrchr(path, '/');
 	if (p == NULL)
 		nfs_flush_file_handle_cache_dir(".");
-	else {
-		t_push();
+	else T_FRAME(
 		nfs_flush_file_handle_cache_dir(t_strdup_until(path, p));
-		t_pop();
-	}
+	);
 }
 
 void nfs_flush_file_handle_cache(const char *path)
--- a/src/lib/restrict-access.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/restrict-access.c	Wed Dec 05 17:47:44 2007 +0200
@@ -68,7 +68,6 @@
 	if (first_valid_gid == 0 && last_valid_gid == 0)
 		return;
 
-	t_push();
 	gid_list = get_groups_list(&gid_count);
 
 	for (i = 0, used = 0; i < gid_count; i++) {
@@ -87,7 +86,6 @@
 				"setgroups() failed: %m");
 		}
 	}
-	t_pop();
 }
 
 static gid_t get_group_id(const char *name)
@@ -109,7 +107,6 @@
 	gid_t *gid_list;
 	int gid_count;
 
-	t_push();
 	tmp = t_strsplit(groups, ", ");
 	gid_list = get_groups_list(&gid_count);
 	for (; *tmp != NULL; tmp++) {
@@ -125,8 +122,6 @@
 		i_fatal("Couldn't set mail_extra_groups: "
 			"setgroups(%s) failed: %m", groups);
 	}
-
-	t_pop();
 }
 
 void restrict_access_by_env(bool disallow_root)
@@ -162,14 +157,19 @@
 					env, dec2str(gid));
 			}
 
-                        drop_restricted_groups(&have_root_group);
+			T_FRAME(
+				drop_restricted_groups(&have_root_group);
+			);
 		}
 	}
 
 	/* grant additional groups to process */
 	env = getenv("RESTRICT_SETEXTRAGROUPS");
-	if (env != NULL && *env != '\0')
-		grant_extra_groups(env);
+	if (env != NULL && *env != '\0') {
+		T_FRAME(
+			grant_extra_groups(env);
+		);
+	}
 
 	/* chrooting */
 	env = getenv("RESTRICT_CHROOT");
--- a/src/lib/strfuncs.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/strfuncs.c	Wed Dec 05 17:47:44 2007 +0200
@@ -191,25 +191,23 @@
 
 	va_start(args, str1);
 
-	if (!pool->datastack_pool)
-		t_push();
-
-	temp = vstrconcat(str1, args, &len);
-	if (temp == NULL)
-		ret = NULL;
-	else {
-		t_buffer_alloc(len);
-		if (pool->datastack_pool)
-			ret = temp;
-		else {
-			ret = p_malloc(pool, len);
-			memcpy(ret, temp, len);
-		}
+	if (pool->datastack_pool) {
+		ret = vstrconcat(str1, args, &len);
+		if (ret != NULL)
+			t_buffer_alloc(len);
+	} else {
+		T_FRAME(
+			temp = vstrconcat(str1, args, &len);
+			if (temp == NULL)
+				ret = NULL;
+			else {
+				t_buffer_alloc(len);
+				ret = p_malloc(pool, len);
+				memcpy(ret, temp, len);
+			}
+		);
 	}
 
-	if (!pool->datastack_pool)
-		t_pop();
-
 	va_end(args);
         return ret;
 }
--- a/src/lib/unlink-lockfiles.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/lib/unlink-lockfiles.c	Wed Dec 05 17:47:44 2007 +0200
@@ -10,22 +10,16 @@
 #include <dirent.h>
 #include <sys/stat.h>
 
-int unlink_lockfiles(const char *dir, const char *pidprefix,
+static int
+unlink_lockfiles_dir(DIR *dirp, const char *dir, const char *pidprefix,
 		     const char *otherprefix, time_t other_min_time)
 {
-	DIR *dirp;
 	struct dirent *d;
 	struct stat st;
 	string_t *path;
 	unsigned int pidlen, otherlen;
 	int ret = 1;
 
-	/* check for any invalid access files */
-	dirp = opendir(dir);
-	if (dirp == NULL)
-		return -1;
-
-	t_push();
 	path = t_str_new(512);
 	pidlen = pidprefix == NULL ? 0 : strlen(pidprefix);
 	otherlen = otherprefix == NULL ? 0 : strlen(otherprefix);
@@ -63,10 +57,26 @@
 				}
 		}
 	}
+	return ret;
+}
+
+int unlink_lockfiles(const char *dir, const char *pidprefix,
+		     const char *otherprefix, time_t other_min_time)
+{
+	DIR *dirp;
+	int ret;
+
+	/* check for any invalid access files */
+	dirp = opendir(dir);
+	if (dirp == NULL)
+		return -1;
+
+	T_FRAME(
+		ret = unlink_lockfiles_dir(dirp, dir, pidprefix,
+					   otherprefix, other_min_time);
+	);
 
 	if (closedir(dirp) < 0)
 		i_error("closedir(%s) failed: %m", dir);
-
-	t_pop();
 	return ret;
 }
--- a/src/login-common/client-common.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/login-common/client-common.c	Wed Dec 05 17:47:44 2007 +0200
@@ -74,7 +74,7 @@
 	return FALSE;
 }
 
-void client_syslog(struct client *client, const char *msg)
+static void client_syslog_real(struct client *client, const char *msg)
 {
 	static struct var_expand_table static_tab[3] = {
 		{ 's', NULL },
@@ -86,7 +86,6 @@
 	const char *p, *const *e;
 	string_t *str;
 
-	t_push();
 	var_expand_table = get_var_expand_table(client);
 
 	tab = t_malloc(sizeof(static_tab));
@@ -114,6 +113,11 @@
 
 	var_expand(str, log_format, tab);
 	i_info("%s", str_c(str));
+}
 
-	t_pop();
+void client_syslog(struct client *client, const char *msg)
+{
+	T_FRAME(
+		client_syslog_real(client, msg);
+	);
 }
--- a/src/login-common/ssl-proxy-gnutls.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/login-common/ssl-proxy-gnutls.c	Wed Dec 05 17:47:44 2007 +0200
@@ -469,11 +469,12 @@
 static void gcrypt_log_handler(void *context ATTR_UNUSED, int level,
 			       const char *fmt, va_list args)
 {
-	if (level == GCRY_LOG_FATAL) {
-		t_push();
+	if (level != GCRY_LOG_FATAL)
+		return;
+
+	T_FRAME(
 		i_error("gcrypt fatal: %s", t_strdup_vprintf(fmt, args));
-		t_pop();
-	}
+	);
 }
 
 void ssl_proxy_init(void)
--- a/src/master/auth-process.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/master/auth-process.c	Wed Dec 05 17:47:44 2007 +0200
@@ -79,7 +79,6 @@
 	string_t *str;
 	ssize_t ret;
 
-	t_push();
 	str = t_str_new(256);
 	str_printfa(str, "REQUEST\t%u\t%u\t%u\n",
 		    ++auth_tag, login_pid, login_id);
@@ -100,7 +99,6 @@
 	} else {
 		hash_insert(process->requests, POINTER_CAST(auth_tag), request);
 	}
-	t_pop();
 }
 
 static bool
@@ -206,6 +204,21 @@
 	return TRUE;
 }
 
+static bool
+auth_process_input_line(struct auth_process *process, const char *line)
+{
+	if (strncmp(line, "USER\t", 5) == 0)
+		return auth_process_input_user(process, line + 5);
+	else if (strncmp(line, "NOTFOUND\t", 9) == 0)
+		return auth_process_input_notfound(process, line + 9);
+	else if (strncmp(line, "FAIL\t", 5) == 0)
+		return auth_process_input_fail(process, line + 5);
+	else if (strncmp(line, "SPID\t", 5) == 0)
+		return auth_process_input_spid(process, line + 5);
+	else
+		return TRUE;
+}
+
 static void auth_process_input(struct auth_process *process)
 {
 	const char *line;
@@ -246,19 +259,9 @@
 	}
 
 	while ((line = i_stream_next_line(process->input)) != NULL) {
-		t_push();
-		if (strncmp(line, "USER\t", 5) == 0)
-			ret = auth_process_input_user(process, line + 5);
-		else if (strncmp(line, "NOTFOUND\t", 9) == 0)
-			ret = auth_process_input_notfound(process, line + 9);
-		else if (strncmp(line, "FAIL\t", 5) == 0)
-			ret = auth_process_input_fail(process, line + 5);
-		else if (strncmp(line, "SPID\t", 5) == 0)
-			ret = auth_process_input_spid(process, line + 5);
-		else
-			ret = TRUE;
-		t_pop();
-
+		T_FRAME(
+			ret = auth_process_input_line(process, line);
+		);
 		if (!ret) {
 			auth_process_destroy(process);
 			break;
--- a/src/master/dup2-array.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/master/dup2-array.c	Wed Dec 05 17:47:44 2007 +0200
@@ -25,7 +25,6 @@
 
 	dups = array_get_modifiable(dups_arr, &count);
 
-	t_push();
 	moved = t_new(bool, count);
 	for (;;) {
 		conflict = count;
@@ -50,7 +49,6 @@
 					i_error("dup2(%d, %d) failed: %m",
 						dups[i].fd_src,
 						dups[i].fd_dest);
-					t_pop();
 					return -1;
 				}
 			}
@@ -68,13 +66,11 @@
 		fd = dup(dups[conflict].fd_src);
 		if (fd == -1) {
 			i_error("dup(%d) failed: %m", dups[conflict].fd_src);
-			t_pop();
 			return -1;
 		}
 		fd_close_on_exec(fd, TRUE);
                 dups[conflict].fd_src = fd;
 	}
-	t_pop();
 	return 0;
 }
 
--- a/src/master/listener.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/master/listener.c	Wed Dec 05 17:47:44 2007 +0200
@@ -148,7 +148,6 @@
 	l.fd = -1;
 	l.wanted = TRUE;
 
-	t_push();
 	for (tmp = t_strsplit_spaces(listen, ", "); *tmp != NULL; tmp++) {
 		l.port = default_port;
 		resolve_ip(set_name, *tmp, &l.ip, &l.port);
@@ -181,7 +180,6 @@
 			listens = array_get_modifiable(listens_arr, &count);
 		}
 	}
-	t_pop();
 }
 
 static void listener_close_fds(ARRAY_TYPE(listener) *listens_arr)
--- a/src/master/log.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/master/log.c	Wed Dec 05 17:47:44 2007 +0200
@@ -39,6 +39,7 @@
 static bool log_write_pending(struct log_io *log_io)
 {
 	const char *line;
+	bool ret;
 
 	if (log_io->log_stamp != ioloop_time) {
 		log_io->log_stamp = ioloop_time;
@@ -46,7 +47,10 @@
 	}
 
 	while ((line = i_stream_next_line(log_io->stream)) != NULL) {
-		if (!log_it(log_io, line, FALSE))
+		T_FRAME(
+			ret = log_it(log_io, line, FALSE);
+		);
+		if (!ret)
 			return FALSE;
 	}
 
@@ -106,7 +110,6 @@
 		}
 	}
 
-	t_push();
 	prefix = log_io->prefix != NULL ? log_io->prefix : "";
 	switch (log_io->next_log_type) {
 	case 'I':
@@ -131,7 +134,6 @@
 		break;
 	}
 	i_log_type(log_type, "%s%s", prefix, line);
-	t_pop();
 
 	if (!continues)
 		log_io->next_log_type = '\0';
@@ -244,9 +246,9 @@
 	/* write partial data as well */
 	data = i_stream_get_data(log_io->stream, &size);
 	if (size != 0) {
-		t_push();
-		log_it(log_io, t_strndup(data, size), TRUE);
-		t_pop();
+		T_FRAME(
+			log_it(log_io, t_strndup(data, size), TRUE);
+		);
 	}
 
 	if (log_io == log_ios)
--- a/src/master/login-process.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/master/login-process.c	Wed Dec 05 17:47:44 2007 +0200
@@ -97,18 +97,16 @@
 	memset(&master_reply, 0, sizeof(master_reply));
 	if (user == NULL)
 		master_reply.status = MASTER_LOGIN_STATUS_INTERNAL_ERROR;
-	else {
+	else T_FRAME_BEGIN {
 		struct login_group *group = request->process->group;
 
-		t_push();
 		master_reply.status =
 			create_mail_process(group->mail_process_type,
 					    group->set,
 					    request->fd, &request->local_ip,
 					    &request->remote_ip, user, args,
 					    FALSE);
-		t_pop();
-	}
+	} T_FRAME_END;
 
 	/* reply to login */
 	master_reply.tag = request->login_tag;
--- a/src/master/mail-process.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/master/mail-process.c	Wed Dec 05 17:47:44 2007 +0200
@@ -247,8 +247,6 @@
 		default_location = "";
 
 	for (i = 1; ns != NULL; i++, ns = ns->next) {
-		t_push();
-
 		location = *ns->location != '\0' ? ns->location :
 			default_location;
 		location = expand_mail_env(location, table);
@@ -278,7 +276,6 @@
 		if (ns->subscriptions)
 			env_put(t_strdup_printf("NAMESPACE_%u_SUBSCRIPTIONS=1",
 						i));
-		t_pop();
 	}
 }
 
--- a/src/master/main.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/master/main.c	Wed Dec 05 17:47:44 2007 +0200
@@ -150,8 +150,11 @@
 		fd_close_on_exec(null_fd, TRUE);
 	}
 
-	if (!IS_INETD())
-		listeners_open_fds(NULL, FALSE);
+	if (!IS_INETD()) {
+		T_FRAME(
+			listeners_open_fds(NULL, FALSE);
+		);
+	}
 
 	/* close stdin and stdout. */
 	if (dup2(null_fd, 0) < 0)
@@ -444,29 +447,27 @@
 	}
 
 	/* read and verify settings before forking */
-	t_push();
-	master_settings_init();
-	if (!master_settings_read(configfile, exec_protocol != NULL,
-				  dump_config || log_error))
-		i_fatal("Invalid configuration in %s", configfile);
-	t_pop();
+	T_FRAME(
+		master_settings_init();
+		if (!master_settings_read(configfile, exec_protocol != NULL,
+					  dump_config || log_error))
+			i_fatal("Invalid configuration in %s", configfile);
+	);
 
 	if (dump_config) {
 		master_settings_dump(settings_root, dump_config_nondefaults);
 		return 0;
 	}
 
-	if (ask_key_pass) {
+	if (ask_key_pass) T_FRAME_BEGIN {
 		const char *prompt;
 
-		t_push();
 		prompt = t_strdup_printf("Give the password for SSL key file "
 					 "%s: ",
 					 settings_root->defaults->ssl_key_file);
 		askpass(prompt, ssl_manual_key_password,
 			sizeof(ssl_manual_key_password));
-		t_pop();
-	}
+	} T_FRAME_END;
 
 	/* save TZ environment. AIX depends on it to get the timezone
 	   correctly. */
--- a/src/master/master-settings.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/master/master-settings.c	Wed Dec 05 17:47:44 2007 +0200
@@ -1542,13 +1542,13 @@
 			  bool nondefaults, unsigned int indent)
 {
 	const char **str;
+	char num_str[MAX_INT_STRLEN];
 	unsigned int i;
 
 	str = t_new(const char *, count);
 	for (; def->name != NULL; def++) {
 		bool same = TRUE;
 
-		t_push();
 		switch (def->type) {
 		case SET_STR: {
 			const char *const *strp;
@@ -1564,7 +1564,8 @@
 
 			for (i = 0; i < count; i++) {
 				n = CONST_PTR_OFFSET(sets[i], def->offset);
-				str[i] = dec2str(*n);
+				snprintf(num_str, sizeof(num_str), "%u", *n);
+				str[i] = num_str;
 			}
 			break;
 		}
@@ -1597,7 +1598,6 @@
 				       set_names[i], str[i]);
 			}
 		}
-		t_pop();
 	}
 }
 
--- a/src/plugins/acl/acl-api.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/acl/acl-api.c	Wed Dec 05 17:47:44 2007 +0200
@@ -45,8 +45,8 @@
 	return acl_cache_mask_isset(have_mask, right_idx);
 }
 
-int acl_object_get_my_rights(struct acl_object *aclobj, pool_t pool,
-                             const char *const **rights_r)
+static int acl_object_get_my_rights_real(struct acl_object *aclobj, pool_t pool,
+					 const char *const **rights_r)
 {
 	struct acl_backend *backend = aclobj->backend;
 	const struct acl_mask *mask;
@@ -70,9 +70,6 @@
 		}
 	}
 
-	if (!pool->datastack_pool)
-		t_push();
-
 	names = acl_cache_get_names(backend->cache, &names_count);
 	buf = t_new(const char *, (mask->size * CHAR_BIT) + 1);
 	count = 0;
@@ -95,10 +92,20 @@
 	rights = p_new(pool, const char *, count + 1);
 	memcpy(rights, buf, count * sizeof(const char *));
 	*rights_r = rights;
+	return 0;
+}
 
-	if (!pool->datastack_pool)
-		t_pop();
-	return 0;
+int acl_object_get_my_rights(struct acl_object *aclobj, pool_t pool,
+                             const char *const **rights_r)
+{
+	int ret;
+
+	if (pool->datastack_pool)
+		return acl_object_get_my_rights_real(aclobj, pool, rights_r);
+	T_FRAME(
+		ret = acl_object_get_my_rights_real(aclobj, pool, rights_r);
+	);
+	return ret;
 }
 
 int acl_object_update(struct acl_object *aclobj,
--- a/src/plugins/acl/acl-backend-vfile-acllist.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/acl/acl-backend-vfile-acllist.c	Wed Dec 05 17:47:44 2007 +0200
@@ -147,7 +147,6 @@
 	struct acl_object_list_iter *iter;
 	struct acl_rights rights;
 	struct acl_backend_vfile_acllist acllist;
-	const char *line;
 	int ret;
 
 	acl_cache_flush(backend->backend.cache, name);
@@ -167,10 +166,12 @@
 		acllist.name = p_strdup(backend->acllist_pool, name);
 		array_append(&backend->acllist, &acllist, 1);
 
-		t_push();
-		line = t_strdup_printf("%s %s\n", dec2str(acllist.mtime), name);
-		o_stream_send_str(output, line);
-		t_pop();
+		T_FRAME(
+			const char *line;
+			line = t_strdup_printf("%s %s\n",
+					       dec2str(acllist.mtime), name);
+			o_stream_send_str(output, line);
+		);
 	}
 	acl_object_deinit(&aclobj);
 	return ret < 0 ? -1 : 0;
--- a/src/plugins/acl/acl-backend-vfile.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/acl/acl-backend-vfile.c	Wed Dec 05 17:47:44 2007 +0200
@@ -69,7 +69,6 @@
 		(struct acl_backend_vfile *)_backend;
 	const char *const *tmp;
 
-	t_push();
 	tmp = t_strsplit(data, ":");
 	backend->global_dir = p_strdup_empty(_backend->pool, *tmp);
 	backend->cache_secs = ACL_VFILE_DEFAULT_CACHE_SECS;
@@ -81,7 +80,6 @@
 			backend->cache_secs = atoi(*tmp + 11);
 		else {
 			i_error("acl vfile: Unknown parameter: %s", *tmp);
-			t_pop();
 			return -1;
 		}
 	}
@@ -93,7 +91,6 @@
 	_backend->cache =
 		acl_cache_init(_backend,
 			       sizeof(struct acl_backend_vfile_validity));
-	t_pop();
 	return 0;
 }
 
@@ -206,7 +203,6 @@
 		return 0;
 
 	/* <id> [<imap acls>] [:<named acls>] */
-	t_push();
 	p = strchr(line, ' ');
 	if (p == NULL)
 		p = "";
@@ -265,7 +261,6 @@
 
 	if (error != NULL) {
 		i_error("ACL file %s line %u: %s", path, linenum, error);
-		t_pop();
 		return -1;
 	}
 
@@ -275,8 +270,6 @@
 
 	acl_cache_update(aclobj->aclobj.backend->cache,
 			 aclobj->aclobj.name, &rights);
-
-	t_pop();
 	return 0;
 }
 
@@ -359,11 +352,12 @@
 
 	linenum = 1;
 	while ((line = i_stream_read_next_line(input)) != NULL) {
-		if (acl_object_vfile_parse_line(aclobj, path, line,
-						linenum++) < 0) {
-			ret = -1;
+		T_FRAME(
+			ret = acl_object_vfile_parse_line(aclobj, path, line,
+							  linenum++);
+		);
+		if (ret < 0)
 			break;
-		}
 	}
 
 	if (input->stream_errno != 0) {
--- a/src/plugins/acl/acl-backend.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/acl/acl-backend.c	Wed Dec 05 17:47:44 2007 +0200
@@ -67,8 +67,11 @@
 		      i_strcmp_p);
 	}
 
-	if (acl_backend_vfile.init(backend, data) < 0)
-		i_fatal("acl: backend vfile init failed with data: %s", data);
+	T_FRAME(
+		if (acl_backend_vfile.init(backend, data) < 0)
+			i_fatal("acl: backend vfile init failed with data: %s",
+				data);
+	);
 
 	backend->default_aclmask =
 		acl_cache_mask_init(backend->cache, backend->pool,
--- a/src/plugins/acl/acl-cache.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/acl/acl-cache.c	Wed Dec 05 17:47:44 2007 +0200
@@ -86,15 +86,15 @@
 	i_free(obj_cache);
 }
 
-struct acl_mask *acl_cache_mask_init(struct acl_cache *cache, pool_t pool,
-				     const char *const *rights)
+static struct acl_mask *
+acl_cache_mask_init_real(struct acl_cache *cache, pool_t pool,
+			 const char *const *rights)
 {
 	struct acl_mask *mask;
 	unsigned int rights_count, i, idx;
 	unsigned char *p;
 	buffer_t *bitmask;
 
-	t_push();
 	rights_count = str_array_length(rights);
 	bitmask = buffer_create_dynamic(pool_datastack_create(),
 					DEFAULT_ACL_RIGHTS_COUNT / CHAR_BIT);
@@ -109,7 +109,17 @@
 	memcpy(mask->mask, bitmask->data, bitmask->used);
 	mask->pool = pool;
 	mask->size = bitmask->used;
-	t_pop();
+	return mask;
+}
+
+struct acl_mask *acl_cache_mask_init(struct acl_cache *cache, pool_t pool,
+				     const char *const *rights)
+{
+	struct acl_mask *mask;
+
+	T_FRAME(
+		mask = acl_cache_mask_init_real(cache, pool, rights);
+	);
 	return mask;
 }
 
@@ -359,7 +369,6 @@
 	unsigned char *p;
 	unsigned int i, j, right_size;
 
-	t_push();
 	bitmask = buffer_create_dynamic(pool_datastack_create(),
 					DEFAULT_ACL_RIGHTS_COUNT / CHAR_BIT);
 	for (i = 0; i < ACL_ID_TYPE_COUNT; i++) {
@@ -389,7 +398,6 @@
 	memcpy(mask->mask, bitmask->data, bitmask->used);
 	mask->pool = default_pool;
 	mask->size = bitmask->used;
-	t_pop();
 }
 
 const struct acl_mask *
@@ -402,8 +410,11 @@
 	    obj_cache->my_current_rights == &negative_cache_entry)
 		return NULL;
 
-	if (obj_cache->my_current_rights == NULL)
-		acl_cache_my_current_rights_recalculate(obj_cache);
+	if (obj_cache->my_current_rights == NULL) {
+		T_FRAME(
+			acl_cache_my_current_rights_recalculate(obj_cache);
+		);
+	}
 	return obj_cache->my_current_rights;
 }
 
--- a/src/plugins/acl/acl-mailbox-list.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/acl/acl-mailbox-list.c	Wed Dec 05 17:47:44 2007 +0200
@@ -88,7 +88,6 @@
 		return FALSE;
 
 	/* default is to not list mailboxes. we can optimize this. */
-	t_push();
 	if ((ctx->ctx.flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0) {
 		sep = ns->sep;
 		vname = t_str_new(256);
@@ -120,7 +119,6 @@
 		mailbox_tree_deinit(&ctx->tree);
 		acl_backend_nonowner_lookups_iter_deinit(&nonowner_list_ctx);
 	}
-	t_pop();
 	if (ret < 0)
 		return FALSE;
 
@@ -136,12 +134,16 @@
 {
 	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
 	struct acl_mailbox_list_iterate_context *ctx;
+	bool ret;
 
 	ctx = i_new(struct acl_mailbox_list_iterate_context, 1);
 	ctx->ctx.list = list;
 	ctx->ctx.flags = flags;
 
-	if (!acl_mailbox_try_list_fast(ctx, patterns)) {
+	T_FRAME(
+		ret = acl_mailbox_try_list_fast(ctx, patterns);
+	);
+	if (!ret) {
 		ctx->super_ctx = alist->module_ctx.super.
 			iter_init(list, patterns, flags);
 	}
@@ -216,9 +218,9 @@
 	int ret;
 
 	while ((info = acl_mailbox_list_iter_next_info(ctx)) != NULL) {
-		t_push();
-		ret = acl_mailbox_list_info_is_visible(ctx, info);
-		t_pop();
+		T_FRAME(
+			ret = acl_mailbox_list_info_is_visible(ctx, info);
+		);
 		if (ret > 0)
 			break;
 		if (ret < 0) {
@@ -254,7 +256,6 @@
 				       enum mailbox_name_status *status)
 {
 	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
-	const char *parent;
 	int ret;
 
 	ret = acl_mailbox_list_have_right(alist, name, ACL_STORAGE_RIGHT_LOOKUP,
@@ -287,12 +288,14 @@
 		break;
 	case MAILBOX_NAME_NOINFERIORS:
 		/* have to check if we are allowed to see the parent */
-		t_push();
-		parent = acl_mailbox_list_get_parent_mailbox_name(list, name);
-		ret = acl_mailbox_list_have_right(alist, parent,
-						  ACL_STORAGE_RIGHT_LOOKUP,
-						  NULL);
-		t_pop();
+		T_FRAME(
+			const char *parent;
+
+			parent = acl_mailbox_list_get_parent_mailbox_name(list,
+									  name);
+			ret = acl_mailbox_list_have_right(alist, parent,
+						ACL_STORAGE_RIGHT_LOOKUP, NULL);
+		);
 
 		if (ret < 0)
 			return -1;
@@ -355,11 +358,11 @@
 	}
 
 	/* and create the new one under the parent mailbox */
-	t_push();
-	ret = acl_mailbox_list_have_right(alist,
-		acl_mailbox_list_get_parent_mailbox_name(list, newname),
-		ACL_STORAGE_RIGHT_CREATE, NULL);
-	t_pop();
+	T_FRAME(
+		ret = acl_mailbox_list_have_right(alist,
+			acl_mailbox_list_get_parent_mailbox_name(list, newname),
+			ACL_STORAGE_RIGHT_CREATE, NULL);
+	);
 
 	if (ret <= 0) {
 		if (ret == 0) {
--- a/src/plugins/acl/acl-storage.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/acl/acl-storage.c	Wed Dec 05 17:47:44 2007 +0200
@@ -134,11 +134,11 @@
 	struct mailbox_list *list = mail_storage_get_list(storage);
 	int ret;
 
-	t_push();
-	ret = acl_storage_have_right(storage,
+	T_FRAME(
+		ret = acl_storage_have_right(storage,
 			acl_mailbox_list_get_parent_mailbox_name(list, name),
 			ACL_STORAGE_RIGHT_CREATE, NULL);
-	t_pop();
+	);
 
 	if (ret <= 0) {
 		if (ret == 0) {
--- a/src/plugins/convert/convert-storage.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/convert/convert-storage.c	Wed Dec 05 17:47:44 2007 +0200
@@ -315,10 +315,11 @@
 	iter = mailbox_list_iter_init(mail_storage_get_list(source_storage),
 				      "*", MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
 	while ((info = mailbox_list_iter_next(iter)) != NULL) {
-		t_push();
-		ret = mailbox_convert_list_item(source_storage, dest_storage,
-						info, dotlock, set);
-		t_pop();
+		T_FRAME(
+			ret = mailbox_convert_list_item(source_storage,
+							dest_storage,
+							info, dotlock, set);
+		);
 		if (ret < 0)
 			break;
 
--- a/src/plugins/expire/expire-plugin.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/expire/expire-plugin.c	Wed Dec 05 17:47:44 2007 +0200
@@ -95,48 +95,50 @@
 {
 	struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
 	struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
-	const char *key, *value;
+	const char *mailbox_name = t->box->name;
 	time_t new_stamp;
-	bool update_dict;
+	bool update_dict = FALSE;
 	int ret;
 
-	t_push();
-	key = t_strconcat(DICT_PATH_SHARED, expire.username, "/",
-			  t->box->name, NULL);
-
 	if (xt->first_expunged) {
 		/* first mail expunged. dict needs updating. */
 		first_nonexpunged_timestamp(t, &new_stamp);
 		update_dict = TRUE;
-	} else {
-		/* saved new mails. dict needs to be updated only if this is
-		   the first mail in the database */
-		ret = dict_lookup(expire.db, pool_datastack_create(),
-				  key, &value);
-		update_dict = ret == 0 || strtoul(value, NULL, 10) == 0;
-		new_stamp = xt->first_save_time;
 	}
 
 	mail_free(&xt->mail);
-	i_free(xt);
-
 	if (xpr_box->module_ctx.super.
 	    	transaction_commit(t, uid_validity_r,
 				   first_saved_uid_r, last_saved_uid_r) < 0) {
-		t_pop();
+		i_free(xt);
 		return -1;
 	}
 
-	if (update_dict) {
-		struct dict_transaction_context *dctx;
-
-		new_stamp += xpr_box->expire_secs;
+	T_FRAME_BEGIN {
+		const char *key, *value;
 
-		dctx = dict_transaction_begin(expire.db);
-		dict_set(dctx, key, dec2str(new_stamp));
-		dict_transaction_commit(dctx);
-	}
-	t_pop();
+		key = t_strconcat(DICT_PATH_SHARED, expire.username, "/",
+				  mailbox_name, NULL);
+		if (!xt->first_expunged) {
+			/* saved new mails. dict needs to be updated only if
+			   this is the first mail in the database */
+			ret = dict_lookup(expire.db, pool_datastack_create(),
+					  key, &value);
+			update_dict = ret == 0 || strtoul(value, NULL, 10) == 0;
+			new_stamp = xt->first_save_time;
+		}
+
+		if (update_dict) {
+			struct dict_transaction_context *dctx;
+
+			new_stamp += xpr_box->expire_secs;
+
+			dctx = dict_transaction_begin(expire.db);
+			dict_set(dctx, key, dec2str(new_stamp));
+			dict_transaction_commit(dctx);
+		}
+	} T_FRAME_END;
+	i_free(xt);
 	return 0;
 }
 
--- a/src/plugins/expire/expire-tool.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/expire/expire-tool.c	Wed Dec 05 17:47:44 2007 +0200
@@ -125,7 +125,8 @@
 	const struct expire_box *expire_box;
 	time_t oldest;
 	const char *auth_socket, *p, *key, *value;
-	const char *username, *mailbox;
+	const char *userp, *mailbox;
+	int ret;
 
 	dict_driver_register(&dict_driver_client);
 	mail_storage_init();
@@ -153,19 +154,16 @@
 	/* We'll get the oldest values (timestamps) first */
 	while (dict_iterate(iter, &key, &value) > 0) {
 		/* key = DICT_PATH_SHARED<user>/<mailbox> */
-		username = key + strlen(DICT_PATH_SHARED);
+		userp = key + strlen(DICT_PATH_SHARED);
 
-		p = strchr(username, '/');
+		p = strchr(userp, '/');
 		if (p == NULL) {
 			i_error("Expire dictionary contains invalid key: %s",
 				key);
 			continue;
 		}
 
-		t_push();
-		username = t_strdup_until(username, p);
 		mailbox = p + 1;
-
 		expire_box = expire_box_find(env, mailbox);
 		if (expire_box == NULL) {
 			/* we're no longer expunging old messages from here */
@@ -173,28 +171,33 @@
 		} else if (time(NULL) < (time_t)strtoul(value, NULL, 10)) {
 			/* this and the rest of the timestamps are in future,
 			   so stop processing */
-			t_pop();
 			break;
 		} else {
-			if (mailbox_delete_old_mails(&ctx, username, mailbox,
-						     expire_box->expire_secs,
-						     &oldest) == 0) {
-				/* successful update */
-				if (oldest == 0) {
-					/* no more messages or we're no longer
-					   expunging messages from here */
-					dict_unset(trans, key);
-				} else {
-					const char *new_value;
+			T_FRAME(
+				const char *username;
 
-					oldest += expire_box->expire_secs;
-					new_value = dec2str(oldest);
-					if (strcmp(value, new_value) != 0)
-						dict_set(trans, key, new_value);
-				}
+				username = t_strdup_until(userp, p);
+				ret = mailbox_delete_old_mails(&ctx, username,
+						mailbox,
+						expire_box->expire_secs,
+						&oldest);
+			);
+			if (ret < 0) {
+				/* failed to update */
+			} else if (oldest == 0) {
+				/* no more messages or we're no longer
+				   expunging messages from here */
+				dict_unset(trans, key);
+			} else {
+				char new_value[MAX_INT_STRLEN];
+
+				oldest += expire_box->expire_secs;
+				i_snprintf(new_value, sizeof(new_value), "%lu",
+					   (unsigned long)oldest);
+				if (strcmp(value, new_value) != 0)
+					dict_set(trans, key, new_value);
 			}
 		}
-		t_pop();
 	}
 	dict_iterate_deinit(iter);
 	dict_transaction_commit(trans);
--- a/src/plugins/fts-squat/squat-trie.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/fts-squat/squat-trie.c	Wed Dec 05 17:47:44 2007 +0200
@@ -541,7 +541,6 @@
 
 	i_assert(str_len > 0);
 
-	t_push();
 	/* make a copy of the leaf string and convert to normal node by
 	   removing it. */
 	str = t_malloc(str_len);
@@ -578,7 +577,6 @@
 			memcpy(child->children.leaf_string, str + 1, str_len);
 		}
 	}
-	t_pop();
 }
 
 static bool
@@ -592,14 +590,18 @@
 
 	if (data_len != str_len) {
 		/* different lengths, can't match */
-		node_split_string(ctx, node);
+		T_FRAME(
+			node_split_string(ctx, node);
+		);
 		return FALSE;
 	}
 
 	for (i = 0; i < data_len; i++) {
 		if (data[i] != str[i]) {
 			/* non-match */
-			node_split_string(ctx, node);
+			T_FRAME(
+				node_split_string(ctx, node);
+			);
 			return FALSE;
 		}
 	}
@@ -778,9 +780,10 @@
 	return dest;
 }
 
-int squat_trie_build_more(struct squat_trie_build_context *ctx,
-			  uint32_t uid, enum squat_index_type type,
-			  const unsigned char *input, unsigned int size)
+static int
+squat_trie_build_more_real(struct squat_trie_build_context *ctx,
+			   uint32_t uid, enum squat_index_type type,
+			   const unsigned char *input, unsigned int size)
 {
 	struct squat_trie *trie = ctx->trie;
 	const unsigned char *data;
@@ -791,7 +794,6 @@
 
 	uid = uid * 2 + (type == SQUAT_INDEX_TYPE_HEADER ? 1 : 0);
 
-	t_push();
 	char_lengths = t_malloc(size);
 	data = squat_data_normalize(trie, input, size);
 	for (i = 0; i < size; i++) {
@@ -823,7 +825,18 @@
 				     char_lengths + start, i - start) < 0)
 			ret = -1;
 	}
-	t_pop();
+	return ret;
+}
+
+int squat_trie_build_more(struct squat_trie_build_context *ctx,
+			  uint32_t uid, enum squat_index_type type,
+			  const unsigned char *input, unsigned int size)
+{
+	int ret;
+
+	T_FRAME(
+		ret = squat_trie_build_more_real(ctx, uid, type, input, size);
+	);
 	return ret;
 }
 
@@ -862,6 +875,7 @@
 	unsigned int i;
 	uoff_t *node_offsets;
 	uint8_t child_count;
+	int ret;
 
 	i_assert(node->next_uid != 0);
 
@@ -888,13 +902,12 @@
 	children = NODE_CHILDREN_NODES(node);
 	node_offsets = t_new(uoff_t, child_count);
 	for (i = 0; i < child_count; i++) {
-		t_push();
-		if (squat_write_node(ctx, &children[i], &node_offsets[i],
-				     level + 1) < 0) {
-			t_pop();
+		T_FRAME(
+			ret = squat_write_node(ctx, &children[i],
+					       &node_offsets[i], level + 1);
+		);
+		if (ret < 0)
 			return -1;
-		}
-		t_pop();
 	}
 
 	*node_offset_r = ctx->output->offset;
@@ -911,9 +924,9 @@
 	if (ctx->trie->root.next_uid == 0)
 		return 0;
 
-	t_push();
-	ret = squat_write_node(ctx, &ctx->trie->root, &node_offset, 0);
-	t_pop();
+	T_FRAME(
+		ret = squat_write_node(ctx, &ctx->trie->root, &node_offset, 0);
+	);
 	if (ret < 0)
 		return -1;
 
@@ -1525,10 +1538,11 @@
 	}
 }
 
-int squat_trie_lookup(struct squat_trie *trie, const char *str,
-		      enum squat_index_type type,
-		      ARRAY_TYPE(seq_range) *definite_uids,
-		      ARRAY_TYPE(seq_range) *maybe_uids)
+static int
+squat_trie_lookup_real(struct squat_trie *trie, const char *str,
+		       enum squat_index_type type,
+		       ARRAY_TYPE(seq_range) *definite_uids,
+		       ARRAY_TYPE(seq_range) *maybe_uids)
 {
 	struct squat_trie_lookup_context ctx;
 	unsigned char *data;
@@ -1536,7 +1550,6 @@
 	unsigned int i, start, bytes, str_bytelen, str_charlen;
 	int ret = 0;
 
-	t_push();
 	memset(&ctx, 0, sizeof(ctx));
 	ctx.trie = trie;
 	ctx.type = type;
@@ -1578,7 +1591,6 @@
 							char_lengths,
 							i - start);
 		}
-		t_pop();
 		squat_trie_add_unknown(trie, maybe_uids);
 		return ret < 0 ? -1 : 0;
 	}
@@ -1603,11 +1615,24 @@
 		ret = squat_trie_lookup_partial(&ctx, data + start,
 						char_lengths, i - start);
 	}
-	t_pop();
 	squat_trie_add_unknown(trie, maybe_uids);
 	return ret < 0 ? -1 : 0;
 }
 
+int squat_trie_lookup(struct squat_trie *trie, const char *str,
+		      enum squat_index_type type,
+		      ARRAY_TYPE(seq_range) *definite_uids,
+		      ARRAY_TYPE(seq_range) *maybe_uids)
+{
+	int ret;
+
+	T_FRAME(
+		ret = squat_trie_lookup_real(trie, str, type,
+					     definite_uids, maybe_uids);
+	);
+	return ret;
+}
+
 struct squat_uidlist *squat_trie_get_uidlist(struct squat_trie *trie)
 {
 	return trie->uidlist;
--- a/src/plugins/fts-squat/squat-uidlist.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/fts-squat/squat-uidlist.c	Wed Dec 05 17:47:44 2007 +0200
@@ -116,7 +116,6 @@
 		squat_pack_num(&listbufp, offset);
 
 	/* @UNSAFE */
-	t_push();
 	base_uid = uid_list[0] & ~UID_LIST_MASK_RANGE;
 	datastack = uid_count < 1024*8/SQUAT_PACK_MAX_SIZE;
 	if (datastack)
@@ -219,7 +218,6 @@
 	o_stream_send(output, uidbuf, uid_list_len);
 	if (!datastack)
 		i_free(uidbuf);
-	t_pop();
 
 	*size_r = size_value;
 	return 0;
@@ -234,6 +232,7 @@
 	uint32_t uid_count = list->uid_count;
 	uint32_t packed_flags = 0;
 	uint32_t offset = 0;
+	int ret;
 
 	if (list->uid_begins_with_pointer) {
 		/* continued UID list */
@@ -256,8 +255,12 @@
 		uid_count--;
 	}
 
-	return uidlist_write_array(output, uid_list, uid_count,
-				   packed_flags, offset, write_size, size_r);
+	T_FRAME(
+		ret = uidlist_write_array(output, uid_list, uid_count,
+					  packed_flags, offset,
+					  write_size, size_r);
+	);
+	return ret;
 }
 
 static int node_uidlist_map_blocks(struct squat_uidlist *uidlist)
@@ -812,9 +815,14 @@
 void squat_uidlist_rebuild_next(struct squat_uidlist_rebuild_context *ctx,
 				const ARRAY_TYPE(uint32_t) *uids)
 {
-	if (uidlist_write_array(ctx->output, array_idx(uids, 0),
-				array_count(uids), 0, 0, FALSE,
-				&ctx->list_sizes[ctx->list_idx]) < 0)
+	int ret;
+
+	T_FRAME(
+		ret = uidlist_write_array(ctx->output, array_idx(uids, 0),
+					  array_count(uids), 0, 0, FALSE,
+					  &ctx->list_sizes[ctx->list_idx]);
+	);
+	if (ret < 0)
 		squat_uidlist_set_corrupted(ctx->uidlist, "Broken uidlists");
 
 	if (++ctx->list_idx == UIDLIST_BLOCK_LIST_COUNT) {
--- a/src/plugins/fts/fts-api.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/fts/fts-api.c	Wed Dec 05 17:47:44 2007 +0200
@@ -166,7 +166,6 @@
 	/* add/leave to dest_maybe if at least one list has maybe,
 	   and no lists have none */
 
-	t_push();
 	/* create unwanted sequences list from both sources */
 	t_array_init(&src_unwanted, 128);
 	new_range.seq1 = 0; new_range.seq2 = (uint32_t)-1;
@@ -185,7 +184,6 @@
 				seq_range_array_add(dest_maybe, 0, seq);
 		}
 	}
-	t_pop();
 }
 
 int fts_backend_filter(struct fts_backend *backend, const char *key,
@@ -210,8 +208,10 @@
 		array_clear(definite_uids);
 		array_clear(maybe_uids);
 	} else {
-		fts_merge_maybies(maybe_uids, definite_uids,
-				  &tmp_maybe, &tmp_definite);
+		T_FRAME(
+			fts_merge_maybies(maybe_uids, definite_uids,
+					  &tmp_maybe, &tmp_definite);
+		);
 		/* keep only what exists in both lists. the rest is in
 		   maybies or not wanted */
 		seq_range_array_remove_invert_range(definite_uids,
--- a/src/plugins/fts/fts-search.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/fts/fts-search.c	Wed Dec 05 17:47:44 2007 +0200
@@ -87,7 +87,6 @@
 		flags |= FTS_LOOKUP_FLAG_INVERT;
 
 	/* convert key to titlecase */
-	t_push();
 	key_utf8 = t_str_new(128);
 	if (charset_to_utf8_str(fctx->charset, CHARSET_FLAG_DECOMP_TITLECASE,
 				key, key_utf8, &result) < 0) {
@@ -107,7 +106,6 @@
 					 &fctx->definite_seqs,
 					 &fctx->maybe_seqs);
 	}
-	t_pop();
 	return ret;
 }
 
@@ -123,11 +121,16 @@
 	i_array_init(&fctx->maybe_seqs, 64);
 
 	/* start filtering with the best arg */
-	ret = fts_search_lookup_arg(fctx, fctx->best_arg, FALSE);
+	T_FRAME(
+		ret = fts_search_lookup_arg(fctx, fctx->best_arg, FALSE);
+	);
 	/* filter the rest */
 	for (arg = fctx->args; arg != NULL && ret == 0; arg = arg->next) {
-		if (arg != fctx->best_arg)
-			ret = fts_search_lookup_arg(fctx, arg, TRUE);
+		if (arg != fctx->best_arg) {
+			T_FRAME(
+				ret = fts_search_lookup_arg(fctx, arg, TRUE);
+			);
+		}
 	}
 
 	if (fctx->fbox->backend_fast != NULL &&
--- a/src/plugins/fts/fts-storage.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/fts/fts-storage.c	Wed Dec 05 17:47:44 2007 +0200
@@ -249,7 +249,6 @@
 static void fts_build_notify(struct fts_storage_build_context *ctx)
 {
 	struct mailbox *box = ctx->mail->transaction->box;
-	const char *text;
 	float percentage;
 	unsigned int msecs, secs;
 
@@ -266,13 +265,16 @@
 			 ctx->search_start_time.tv_usec) / 1000;
 		secs = (msecs / (percentage / 100.0) - msecs) / 1000;
 
-		t_push();
-		text = t_strdup_printf("Indexed %d%% of the mailbox, "
-				       "ETA %d:%02d", (int)percentage,
-				       secs/60, secs%60);
-		box->storage->callbacks->
-			notify_ok(box, text, box->storage->callback_context);
-		t_pop();
+		T_FRAME(
+			const char *text;
+
+			text = t_strdup_printf("Indexed %d%% of the mailbox, "
+					       "ETA %d:%02d", (int)percentage,
+					       secs/60, secs%60);
+			box->storage->callbacks->
+				notify_ok(box, text,
+				box->storage->callback_context);
+		);
 	}
 	ctx->last_notify = ioloop_timeval;
 }
@@ -287,9 +289,9 @@
 		fts_build_notify(ctx);
 
 	while (mailbox_search_next(ctx->search_ctx, ctx->mail) > 0) {
-		t_push();
-		ret = fts_build_mail(ctx, ctx->mail->uid);
-		t_pop();
+		T_FRAME(
+			ret = fts_build_mail(ctx, ctx->mail->uid);
+		);
 
 		if (ret < 0)
 			return -1;
--- a/src/plugins/imap-quota/imap-quota-plugin.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/imap-quota/imap-quota-plugin.c	Wed Dec 05 17:47:44 2007 +0200
@@ -21,8 +21,6 @@
 	uint64_t value, limit;
 	int ret;
 
-	t_push();
-
 	str = t_str_new(128);
 	str_append(str, "* QUOTA ");
 	imap_quote_append_string(str, quota_root_get_name(root), FALSE);
@@ -45,8 +43,6 @@
 	}
 	str_append_c(str, ')');
 	client_send_line(cmd->client, str_c(str));
-
-	t_pop();
 }
 
 static bool cmd_getquotaroot(struct client_command_context *cmd)
--- a/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Wed Dec 05 17:47:44 2007 +0200
@@ -392,7 +392,6 @@
 						MAILBOX_LIST_PATH_TYPE_MAILBOX);
 	}
 
-	t_push();
 	src2dir = mailbox_list_get_path(src_list, src_name,
 					MAILBOX_LIST_PATH_TYPE_CONTROL);
 	if (strcmp(src2dir, srcdir) != 0) {
@@ -407,7 +406,6 @@
 						MAILBOX_LIST_PATH_TYPE_INDEX);
 		(void)dir_move_or_merge(src_list, src3dir, destdir);
 	}
-	t_pop();
 
 	*_dest_name = dest_name;
 	return 1;
@@ -491,7 +489,6 @@
 
 	/* if this is one of our internal storages, mark it as such before
 	   quota plugin sees it */
-	t_push();
 	p = t_strsplit_spaces(getenv("LAZY_EXPUNGE"), " ");
 	for (i = 0; i < LAZY_NAMESPACE_COUNT; i++, p++) {
 		if (strcmp(storage->ns->prefix, *p) == 0) {
@@ -499,7 +496,6 @@
 			break;
 		}
 	}
-	t_pop();
 
 	llist->storage = storage;
 
@@ -534,7 +530,6 @@
 	if (lazy_expunge_next_hook_mail_namespaces_created != NULL)
 		lazy_expunge_next_hook_mail_namespaces_created(namespaces);
 
-	t_push();
 	p = t_strsplit_spaces(getenv("LAZY_EXPUNGE"), " ");
 	for (i = 0; i < LAZY_NAMESPACE_COUNT; i++, p++) {
 		const char *name = *p;
@@ -556,7 +551,6 @@
 		lstorage = LAZY_EXPUNGE_CONTEXT(lazy_namespaces[i]->storage);
 		lstorage->internal_namespace = TRUE;
 	}
-	t_pop();
 }
 
 void lazy_expunge_plugin_init(void)
--- a/src/plugins/mail-log/mail-log-plugin.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/mail-log/mail-log-plugin.c	Wed Dec 05 17:47:44 2007 +0200
@@ -206,8 +206,6 @@
 	unsigned int i, count;
 	string_t *str;
 	
-	t_push();
-
 	str = t_str_new(128);
 	str_printfa(str, "%s: ", mail_log_event_get_name(group->event));
 
@@ -240,7 +238,6 @@
 	str_truncate(str, str_len(str)-2);
 
 	i_info("%s", str_c(str));
-	t_pop();
 }
 
 static void
@@ -251,8 +248,11 @@
 	unsigned int i, count;
 
 	group = array_get(&lt->group_changes, &count);
-	for (i = 0; i < count; i++)
-		mail_log_group(box, &group[i]);
+	for (i = 0; i < count; i++) {
+		T_FRAME(
+			mail_log_group(box, &group[i]);
+		);
+	}
 }
 
 static void mail_log_action(struct mail *mail, enum mail_log_event event,
@@ -282,7 +282,6 @@
 		return;
 	}
 
-	t_push();
 	str = t_str_new(128);
 	str_printfa(str, "%s: ", mail_log_event_get_name(event));
 
@@ -315,7 +314,6 @@
 	str_truncate(str, str_len(str)-2);
 
 	i_info("%s", str_c(str));
-	t_pop();
 }
 
 static void mail_log_mail_expunge(struct mail *_mail)
@@ -323,7 +321,9 @@
 	struct mail_private *mail = (struct mail_private *)_mail;
 	union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
 
-	mail_log_action(_mail, MAIL_LOG_EVENT_EXPUNGE, NULL);
+	T_FRAME(
+		mail_log_action(_mail, MAIL_LOG_EVENT_EXPUNGE, NULL);
+	);
 	lmail->super.expunge(_mail);
 }
 
@@ -353,8 +353,11 @@
 	if (((old_flags ^ new_flags) & MAIL_DELETED) == 0)
 		return;
 
-	mail_log_action(_mail, (new_flags & MAIL_DELETED) != 0 ?
-			MAIL_LOG_EVENT_DELETE : MAIL_LOG_EVENT_UNDELETE, NULL);
+	T_FRAME(
+		mail_log_action(_mail, (new_flags & MAIL_DELETED) != 0 ?
+				MAIL_LOG_EVENT_DELETE :
+				MAIL_LOG_EVENT_UNDELETE, NULL);
+	);
 }
 
 static struct mail *
@@ -390,10 +393,11 @@
 	if (lbox->super.copy(t, mail, flags, keywords, dest_mail) < 0)
 		return -1;
 
-	t_push();
-	name = str_sanitize(mailbox_get_name(t->box), MAILBOX_NAME_LOG_LEN);
-	mail_log_action(mail, MAIL_LOG_EVENT_COPY, name);
-	t_pop();
+	T_FRAME(
+		name = str_sanitize(mailbox_get_name(t->box),
+				    MAILBOX_NAME_LOG_LEN);
+		mail_log_action(mail, MAIL_LOG_EVENT_COPY, name);
+	);
 	return 0;
 }
 
@@ -553,7 +557,6 @@
 
 	memset(set, 0, sizeof(*set));
 
-	t_push();
 	str = getenv("MAIL_LOG_FIELDS");
 	set->fields = str == NULL ? MAIL_LOG_DEFAULT_FIELDS :
 		mail_log_parse_fields(str);
@@ -563,7 +566,6 @@
 		mail_log_parse_events(str);
 
 	set->group_events = getenv("MAIL_LOG_GROUP_EVENTS") != NULL;
-	t_pop();
 }
 
 void mail_log_plugin_init(void)
--- a/src/plugins/quota/quota-dict.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/quota/quota-dict.c	Wed Dec 05 17:47:44 2007 +0200
@@ -81,11 +81,11 @@
 	if (quota_count(root->root.quota, &bytes, &count) < 0)
 		return -1;
 
-	t_push();
-	dt = dict_transaction_begin(root->dict);
-	dict_set(dt, DICT_QUOTA_CURRENT_BYTES_PATH, dec2str(bytes));
-	dict_set(dt, DICT_QUOTA_CURRENT_COUNT_PATH, dec2str(count));
-	t_pop();
+	T_FRAME(
+		dt = dict_transaction_begin(root->dict);
+		dict_set(dt, DICT_QUOTA_CURRENT_BYTES_PATH, dec2str(bytes));
+		dict_set(dt, DICT_QUOTA_CURRENT_COUNT_PATH, dec2str(count));
+	);
 
 	if (dict_transaction_commit(dt) < 0)
 		i_error("dict_quota: Couldn't update quota");
@@ -99,7 +99,6 @@
 			uint64_t *value_r, uint64_t *limit ATTR_UNUSED)
 {
 	struct dict_quota_root *root = (struct dict_quota_root *)_root;
-	const char *value;
 	bool want_bytes;
 	int ret;
 
@@ -110,24 +109,28 @@
 	else
 		return 0;
 
-	t_push();
-	ret = dict_lookup(root->dict, unsafe_data_stack_pool,
-			  want_bytes ? DICT_QUOTA_CURRENT_BYTES_PATH :
-			  DICT_QUOTA_CURRENT_COUNT_PATH, &value);
-	if (ret < 0)
-		*value_r = 0;
-	else {
-		long long tmp;
+	T_FRAME(
+		const char *value;
+
+		ret = dict_lookup(root->dict, unsafe_data_stack_pool,
+				  want_bytes ? DICT_QUOTA_CURRENT_BYTES_PATH :
+				  DICT_QUOTA_CURRENT_COUNT_PATH, &value);
+		if (ret < 0)
+			*value_r = 0;
+		else {
+			long long tmp;
 
-		/* recalculate quota if it's negative or if it wasn't found */
-		tmp = ret == 0 ? -1 : strtoll(value, NULL, 10);
-		if (tmp < 0)
-			ret = dict_quota_count(root, want_bytes, value_r);
-		else
-			*value_r = tmp;
-	}
-
-	t_pop();
+			/* recalculate quota if it's negative or if it
+			   wasn't found */
+			tmp = ret == 0 ? -1 : strtoll(value, NULL, 10);
+			if (tmp >= 0)
+				*value_r = tmp;
+			else {
+				ret = dict_quota_count(root, want_bytes,
+						       value_r);
+			}
+		}
+	);
 	return ret;
 }
 
--- a/src/plugins/quota/quota-dirsize.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/quota/quota-dirsize.c	Wed Dec 05 17:47:44 2007 +0200
@@ -155,7 +155,6 @@
 	const char *path;
 	bool is_file;
 
-	t_push();
 	t_array_init(&paths, 8);
 	storages = array_get(&root->quota->storages, &count);
 	for (i = 0; i < count; i++) {
@@ -173,13 +172,9 @@
 	count_paths = array_get(&paths, &count);
 	for (i = 0; i < count; i++) {
 		if (get_usage(count_paths[i].path, count_paths[i].is_file,
-			      value_r) < 0) {
-			t_pop();
+			      value_r) < 0)
 			return -1;
-		}
 	}
-
-	t_pop();
 	return 0;
 }
 
@@ -187,13 +182,16 @@
 dirsize_quota_get_resource(struct quota_root *_root, const char *name,
 			   uint64_t *value_r, uint64_t *limit ATTR_UNUSED)
 {
+	int ret;
+
 	if (strcasecmp(name, QUOTA_NAME_STORAGE_BYTES) != 0)
 		return 0;
 
-	if (get_quota_root_usage(_root, value_r) < 0)
-		return -1;
+	T_FRAME(
+		ret = get_quota_root_usage(_root, value_r);
+	);
 
-	return 1;
+	return ret < 0 ? -1 : 1;
 }
 
 static int 
--- a/src/plugins/quota/quota-fs.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/quota/quota-fs.c	Wed Dec 05 17:47:44 2007 +0200
@@ -568,9 +568,9 @@
 	if (strcmp(root->mount->type, "nfs") == 0) {
 		int ret;
 
-		t_push();
-		ret = do_rquota(root, bytes, value_r, limit_r);
-		t_pop();
+		T_FRAME(
+			ret = do_rquota(root, bytes, value_r, limit_r);
+		);
 		return ret;
 	}
 #endif
--- a/src/plugins/quota/quota-maildir.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/quota/quota-maildir.c	Wed Dec 05 17:47:44 2007 +0200
@@ -139,7 +139,6 @@
 maildir_list_next(struct maildir_list_context *ctx, time_t *mtime_r)
 {
 	struct stat st;
-	const char *path;
 	bool is_file;
 
 	for (;;) {
@@ -149,14 +148,17 @@
 				return NULL;
 		}
 
-		t_push();
-		path = mail_storage_get_mailbox_path(ctx->storage,
-						     ctx->info->name,
-						     &is_file);
-		str_truncate(ctx->path, 0);
-		str_append(ctx->path, path);
-		str_append(ctx->path, ctx->state == 0 ? "/new" : "/cur");
-		t_pop();
+		T_FRAME(
+			const char *path;
+
+			path = mail_storage_get_mailbox_path(ctx->storage,
+							     ctx->info->name,
+							     &is_file);
+			str_truncate(ctx->path, 0);
+			str_append(ctx->path, path);
+			str_append(ctx->path, ctx->state == 0 ?
+				   "/new" : "/cur");
+		);
 
 		if (++ctx->state == 2)
 			ctx->state = 0;
@@ -274,11 +276,11 @@
 		if (mtime > root->recalc_last_stamp)
 			root->recalc_last_stamp = mtime;
 
-		t_push();
-		if (maildir_sum_dir(dir, &root->total_bytes,
-				    &root->total_count) < 0)
-			ret = -1;
-		t_pop();
+		T_FRAME(
+			if (maildir_sum_dir(dir, &root->total_bytes,
+					    &root->total_count) < 0)
+				ret = -1;
+		);
 	}
 	if (maildir_list_deinit(ctx) < 0)
 		ret = -1;
@@ -447,7 +449,6 @@
 	unsigned int i, size;
 	int fd, ret = 0;
 
-	t_push();
 	if (root->fd != -1) {
 		if (close(root->fd) < 0)
 			i_error("close(%s) failed: %m", root->maildirsize_path);
@@ -462,7 +463,6 @@
 			ret = -1;
 			i_error("open(%s) failed: %m", root->maildirsize_path);
 		}
-		t_pop();
 		return ret;
 	}
 
@@ -480,7 +480,6 @@
 	if (ret < 0 || size >= sizeof(buf)-1) {
 		/* error / recalculation needed. */
 		(void)close(fd);
-		t_pop();
 		return ret < 0 ? -1 : 0;
 	}
 
@@ -509,7 +508,6 @@
 		root->fd = -1;
 		ret = 0;
 	}
-	t_pop();
 	return ret;
 }
 
@@ -541,7 +539,9 @@
 			return 0;
 	}
 
-	ret = maildirsize_read(root);
+	T_FRAME(
+		ret = maildirsize_read(root);
+	);
 	if (ret == 0) {
 		if (root->message_bytes_limit == (uint64_t)-1 &&
 		    root->message_count_limit == (uint64_t)-1) {
@@ -557,20 +557,19 @@
 static int maildirsize_update(struct maildir_quota_root *root,
 			      int count_diff, int64_t bytes_diff)
 {
-	const char *str;
+	char str[MAX_INT_STRLEN*2 + 2];
 	int ret = 0;
 
 	if (count_diff == 0 && bytes_diff == 0)
 		return 0;
 
-	t_push();
-
 	/* We rely on O_APPEND working in here. That isn't NFS-safe, but it
 	   isn't necessarily that bad because the file is recreated once in
 	   a while, and sooner if corruption causes calculations to go
 	   over quota. This is also how Maildir++ spec specifies it should be
 	   done.. */
-	str = t_strdup_printf("%lld %d\n", (long long)bytes_diff, count_diff);
+	i_snprintf(str, sizeof(str), "%lld %d\n",
+		   (long long)bytes_diff, count_diff);
 	if (write_full(root->fd, str, strlen(str)) < 0) {
 		ret = -1;
 		if (errno == ESTALE) {
@@ -580,7 +579,6 @@
 				root->maildirsize_path);
 		}
 	}
-	t_pop();
 	return ret;
 }
 
--- a/src/plugins/quota/quota-plugin.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/quota/quota-plugin.c	Wed Dec 05 17:47:44 2007 +0200
@@ -23,8 +23,6 @@
 	const char *rule_name, *rule, *error;
 	unsigned int i;
 
-	t_push();
-
 	rule_name = t_strconcat(root_name, "_RULE", NULL);
 	for (i = 2;; i++) {
 		rule = getenv(rule_name);
@@ -38,8 +36,6 @@
 		}
 		rule_name = t_strdup_printf("%s_RULE%d", root_name, i);
 	}
-
-	t_pop();
 }
 
 static void quota_root_add_warning_rules(const char *root_name,
@@ -48,8 +44,6 @@
 	const char *rule_name, *rule, *error;
 	unsigned int i;
 
-	t_push();
-
 	rule_name = t_strconcat(root_name, "_WARNING", NULL);
 	for (i = 2;; i++) {
 		rule = getenv(rule_name);
@@ -63,8 +57,6 @@
 		}
 		rule_name = t_strdup_printf("%s_WARNING%d", root_name, i);
 	}
-
-	t_pop();
 }
 
 void quota_plugin_init(void)
@@ -85,7 +77,6 @@
 	quota_root_add_rules("QUOTA", root);
 	quota_root_add_warning_rules("QUOTA", root);
 
-	t_push();
 	for (i = 2;; i++) {
 		const char *root_name;
 
@@ -101,7 +92,6 @@
 		quota_root_add_rules(root_name, root);
 		quota_root_add_warning_rules(root_name, root);
 	}
-	t_pop();
 
 	quota_next_hook_mail_storage_created = hook_mail_storage_created;
 	hook_mail_storage_created = quota_mail_storage_created;
--- a/src/plugins/quota/quota.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/plugins/quota/quota.c	Wed Dec 05 17:47:44 2007 +0200
@@ -87,8 +87,6 @@
 	const struct quota_backend *backend;
 	const char *p, *args, *backend_name;
 
-	t_push();
-
 	/* <backend>[:<quota root name>[:<backend args>]] */
 	p = strchr(root_def, ':');
 	if (p == NULL) {
@@ -103,8 +101,6 @@
 	if (backend == NULL)
 		i_fatal("Unknown quota backend: %s", backend_name);
 	
-	t_pop();
-
 	root = backend->v.alloc();
 	root->quota = quota;
 	root->backend = *backend;
@@ -288,7 +284,6 @@
 	}
 
 	/* <mailbox name>:<quota limits> */
-	t_push();
 	mailbox_name = t_strdup_until(rule_def, p++);
 
 	rule = quota_root_rule_find(root, mailbox_name);
@@ -316,8 +311,6 @@
 		       (long long)rule->bytes_limit / 1024,
 		       (long long)rule->count_limit);
 	}
-
-	t_pop();
 	return ret;
 }
 
@@ -423,10 +416,8 @@
 	}
 
 	memset(&rule, 0, sizeof(rule));
-	t_push();
 	ret = quota_rule_parse_limits(root, &rule, t_strdup_until(rule_def, p),
 				      error_r);
-	t_pop();
 	if (ret < 0)
 		return -1;
 
--- a/src/pop3-login/client.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/pop3-login/client.c	Wed Dec 05 17:47:44 2007 +0200
@@ -274,24 +274,20 @@
 	struct auth_connect_id *id = &client->auth_id;
 	unsigned char buffer[16];
         buffer_t *buf;
-	char *ret;
 
 	if (!auth_client_reserve_connection(auth_client, "APOP", id))
 		return NULL;
 
-	t_push();
 	random_fill(buffer, sizeof(buffer));
 	buf = buffer_create_static_hard(pool_datastack_create(),
 			MAX_BASE64_ENCODED_SIZE(sizeof(buffer)) + 1);
 	base64_encode(buffer, sizeof(buffer), buf);
 	buffer_append_c(buf, '\0');
 
-	ret = i_strdup_printf("<%x.%x.%lx.%s@%s>",
-			      id->server_pid, id->connect_uid,
-			      (unsigned long)ioloop_time,
-			      (const char *)buf->data, my_hostname);
-	t_pop();
-	return ret;
+	return i_strdup_printf("<%x.%x.%lx.%s@%s>",
+			       id->server_pid, id->connect_uid,
+			       (unsigned long)ioloop_time,
+			       (const char *)buf->data, my_hostname);
 }
 
 static void client_auth_ready(struct pop3_client *client)
--- a/src/pop3/client.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/pop3/client.c	Wed Dec 05 17:47:44 2007 +0200
@@ -295,23 +295,25 @@
 int client_send_line(struct client *client, const char *fmt, ...)
 {
 	va_list va;
-	string_t *str;
 	ssize_t ret;
 
 	if (client->output->closed)
 		return -1;
 
-	t_push();
 	va_start(va, fmt);
 
-	str = t_str_new(256);
-	str_vprintfa(str, fmt, va);
-	str_append(str, "\r\n");
+	T_FRAME(
+		string_t *str;
 
-	ret = o_stream_send(client->output, str_data(str), str_len(str));
+		str = t_str_new(256);
+		str_vprintfa(str, fmt, va);
+		str_append(str, "\r\n");
+
+		ret = o_stream_send(client->output,
+				    str_data(str), str_len(str));
+		i_assert(ret < 0 || (size_t)ret == str_len(str));
+	);
 	if (ret >= 0) {
-		i_assert((size_t)ret == str_len(str));
-
 		if (o_stream_get_buffer_used_size(client->output) <
 		    OUTBUF_THROTTLE_SIZE) {
 			ret = 1;
@@ -333,7 +335,6 @@
 	}
 
 	va_end(va);
-	t_pop();
 	return (int)ret;
 }
 
@@ -388,10 +389,10 @@
 		if (args != NULL)
 			*args++ = '\0';
 
-		t_push();
-		ret = client_command_execute(client, line,
-					     args != NULL ? args : "");
-		t_pop();
+		T_FRAME(
+			ret = client_command_execute(client, line,
+						     args != NULL ? args : "");
+		);
 		if (ret >= 0) {
 			client->bad_counter = 0;
 			if (client->cmd != NULL) {
--- a/src/pop3/commands.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/pop3/commands.c	Wed Dec 05 17:47:44 2007 +0200
@@ -517,6 +517,7 @@
 	};
 	struct var_expand_table *tab;
 	string_t *str;
+	char uid_str[MAX_INT_STRLEN];
 	const char *uidl;
 	int ret;
 	bool found = FALSE;
@@ -525,7 +526,7 @@
 	memcpy(tab, static_tab, sizeof(static_tab));
 	tab[0].value = t_strdup_printf("%u", client->uid_validity);
 
-	str = str_new(default_pool, 128);
+	str = t_str_new(128);
 	while (mailbox_search_next(ctx->search_ctx, ctx->mail) > 0) {
 		if (client->deleted) {
 			uint32_t idx = ctx->mail->seq - 1;
@@ -535,9 +536,11 @@
 		}
 		found = TRUE;
 
-		t_push();
-		if ((uidl_keymask & UIDL_UID) != 0)
-			tab[1].value = dec2str(ctx->mail->uid);
+		if ((uidl_keymask & UIDL_UID) != 0) {
+			i_snprintf(uid_str, sizeof(uid_str), "%u",
+				   ctx->mail->uid);
+			tab[1].value = uid_str;
+		}
 		if ((uidl_keymask & UIDL_MD5) != 0) {
 			if (mail_get_special(ctx->mail, MAIL_FETCH_HEADER_MD5,
 					     &tab[2].value) < 0 ||
@@ -566,18 +569,14 @@
 		else
 			var_expand(str, uidl_format, tab);
 		ret = client_send_line(client, "%s", str_c(str));
-		t_pop();
-
 		if (ret < 0)
 			break;
 		if (ret == 0 && ctx->message == 0) {
 			/* output is being buffered, continue when there's
 			   more space */
-			str_free(&str);
 			return 0;
 		}
 	}
-	str_free(&str);
 
 	/* finished */
 	mail_free(&ctx->mail);
--- a/src/util/idxview.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/util/idxview.c	Wed Dec 05 17:47:44 2007 +0200
@@ -413,11 +413,11 @@
 	}
 	for (seq = 1; seq <= index->map->hdr.messages_count; seq++) {
 		if (uid == 0 || mail_index_lookup(view, seq)->uid == uid) {
-			t_push();
-			dump_record(view, seq);
-			dump_cache(cache_view, seq);
-			printf("\n");
-			t_pop();
+			T_FRAME(
+				dump_record(view, seq);
+				dump_cache(cache_view, seq);
+				printf("\n");
+			);
 		}
 	}
 	mail_cache_view_close(cache_view);
--- a/src/util/listview.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/util/listview.c	Wed Dec 05 17:47:44 2007 +0200
@@ -106,18 +106,16 @@
 			       path, name, crc32_str(name), rec.name_hash);
 		}
 
-		if (rec.dir_offset != 0) {
+		if (rec.dir_offset != 0) T_FRAME_BEGIN {
 			const char *new_path;
 
-			t_push();
 			lseek(fd, rec.dir_offset, SEEK_SET);
 			if (*path == '\0')
 				new_path = t_strdup_printf("%s/", name);
 			else
 				new_path = t_strdup_printf("%s%s/", path, name);
 			dump_dir(fd, show_offset, new_path);
-			t_pop();
-		}
+		} T_FRAME_END;
 
 		offset += sizeof(rec);
 	}
--- a/src/util/logview.c	Wed Dec 05 17:47:19 2007 +0200
+++ b/src/util/logview.c	Wed Dec 05 17:47:44 2007 +0200
@@ -276,7 +276,7 @@
 
 int main(int argc, const char *argv[])
 {
-	int fd;
+	int fd, ret;
 
 	lib_init();
 
@@ -290,12 +290,10 @@
 	}
 
 	dump_hdr(fd);
-	for (;;) {
-		t_push();
-		if (!dump_record(fd))
-			break;
-		t_pop();
-	}
-	t_pop();
+	do {
+		T_FRAME(
+			ret = dump_record(fd);
+		);
+	} while (ret > 0);
 	return 0;
 }