Thanks for your kind reply. The attachment is a simple example show eventpool
file descriptor leak, please check, thanks.
Run following command compile this example.
# gcc -Wall -I /usr/local/samba/include/ exmain.c -L /usr/local/samba/lib/
-lmapi
# ./a.out
# lsof -p $(pgrep a.out)
>> The calling sequence as follows:
>>
>> MAPIInitialize->MapiLogonEx->OpenMsgStore->...->mapi_object_release->MAPIUn
>> initialize
>Can you show a simple compilable example that reproduces the problem?
>
>Brad
>
>[BTW: I got your private email, but your provider won't accept mail that
>doesn't have SPF.]
#include <unistd.h>
#include <stdio.h>
#include <inttypes.h>
#include <pthread.h>
#include <talloc.h>
#include <libmapi/libmapi.h>
// # gcc -Wall -I /usr/local/samba/include/ exmain.c -L /usr/local/samba/lib/
-lmapi
// # ./a.out
// # lsof -p $(pgrep a.out)
#define DEFAULT_PROFDB_LOCATION "/tmp"
#define DEFAULT_PROFDB_FILE "profiles.ldb"
#define DEFAULT_EXCHANGE_VERSION_NUMBER 0
struct exClient {
char username[32]; // generated by email
char password[32];
char serverip[20];
char emailaddress[48]; // [email protected]
char *profname; // equal to username
char *profdb; // generated by domain
char *domain; // generated by emailaddress
unsigned int n_curmailcount;
struct mapi_context *m_mapi_ctx; // MAPI context
struct mapi_session *m_session; // Login Session
};
void init_exclient(struct exClient *oclient)
{
memset (oclient->username, 0, sizeof(oclient->username));
memset (oclient->password, 0, sizeof(oclient->password));
memset (oclient->emailaddress, 0, sizeof(oclient->emailaddress));
memset (oclient->serverip, 0, sizeof(oclient->serverip));
oclient->profname = NULL;
oclient->profdb = NULL;
oclient->domain = NULL;
oclient->n_curmailcount = -1;
oclient->m_mapi_ctx = NULL;
oclient->m_session = NULL;
}
int gen_exclient(struct exClient* oclient,
const char* emailaddress, const char* password, const char* serveraddr,
const char* profdb_location)
{
strncpy (oclient->emailaddress, emailaddress,
sizeof(oclient->emailaddress));
strncpy (oclient->password, password, sizeof(oclient->password));
strncpy (oclient->serverip, serveraddr, sizeof(oclient->serverip));
int length;
const char* delim = "@";
char profbuffer[256] = "\0", email[64] = "\0", *p;
strncpy (email, emailaddress, sizeof(email));
if ((p = strtok (email, delim)) != NULL) {
strncpy (oclient->username, p, sizeof(oclient->username));
}
oclient->profname = oclient->username;
if ((oclient->domain= strpbrk (oclient->emailaddress, delim)) != NULL) {
oclient->domain++;
}
else {
printf("email:%s Invalid mail address !", emailaddress);
return 1;
}
if (profdb_location != NULL) {
sprintf (profbuffer, "%s/%s.%s", profdb_location,
oclient->domain, DEFAULT_PROFDB_FILE);
}
else {
sprintf (profbuffer, "%s/%s.%s", DEFAULT_PROFDB_LOCATION,
oclient->domain, DEFAULT_PROFDB_FILE);
}
length = strlen(profbuffer);
oclient->profdb = malloc (length+1);
strcpy (oclient->profdb, profbuffer);
oclient->profdb[length] = 0;
return 0;
}
void dump_exclient(const struct exClient* oclient)
{
printf ("\n");
printf ("username : %s\n", oclient->username);
printf ("password : %s\n", oclient->password);
printf ("serverip : %s\n", oclient->serverip);
printf ("email : %s\n", oclient->emailaddress);
printf ("profname : %s\n", oclient->profname);
printf ("profdb : %s\n", oclient->profdb);
printf ("domain : %s\n", oclient->domain);
}
static uint32_t callback(struct SRowSet *rowset, void *private)
{
uint32_t i;
struct SPropValue *lpProp;
const char *label = "username checked matches several
usernames, select the first one";
printf("Warning: %s:", label);
for (i = 0; i < rowset->cRows; i++) {
lpProp = get_SPropValue_SRow(&(rowset->aRow[i]),
PR_DISPLAY_NAME);
if (lpProp && lpProp->value.lpszA) {
printf("\t[%u] %s", i, lpProp->value.lpszA);
}
}
return 0;
}
bool profcreate(const struct exClient * oclient, uint32_t flags)
{
enum MAPISTATUS retval;
struct mapi_context *mapi_ctx;
struct mapi_session *session = NULL;
TALLOC_CTX *mem_ctx;
struct mapi_profile profile;
const char *locale;
uint32_t cpid;
uint32_t lcid;
char *cpid_str;
char *lcid_str;
char workstation[128] = "\0";
char exchange_version_str[8];
mem_ctx = talloc_named(NULL, 0, "profcreate");
retval = MAPIInitialize(&mapi_ctx, oclient->profdb);
if (retval != MAPI_E_SUCCESS) {
printf ("email:%s <profcreate> MAPIInitialize error: 0x%X\n",
oclient->emailaddress,retval);
talloc_free(mem_ctx);
return false;
}
/* Sanity check */
retval = OpenProfile(mapi_ctx, &profile, oclient->profname, NULL);
if (retval == MAPI_E_SUCCESS) {
printf("email:%s <profcreate> profile \"%s\" already exists\n",
oclient->emailaddress,oclient->profname);
MAPIUninitialize(mapi_ctx);
talloc_free(mem_ctx);
return true;
}
retval = CreateProfile(mapi_ctx, oclient->profname, oclient->username,
oclient->password, flags);
if (retval != MAPI_E_SUCCESS) {
printf ("email:%s <profcreate> CreateProfile error: 0x%X\n",
oclient->emailaddress,retval);
MAPIUninitialize(mapi_ctx);
talloc_free(mem_ctx);
return false;
}
gethostname(workstation, sizeof(workstation));
sprintf (exchange_version_str, "%d", DEFAULT_EXCHANGE_VERSION_NUMBER);
mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "binding",
oclient->serverip);
mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "domain",
oclient->domain);
mapi_profile_add_string_attr(mapi_ctx, oclient->profname,
"workstation", workstation);
mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "seal",
"false");
mapi_profile_add_string_attr(mapi_ctx, oclient->profname,
"exchange_version", exchange_version_str);
locale = mapi_get_system_locale();
if (locale) {
cpid = mapi_get_cpid_from_locale(locale);
lcid = mapi_get_lcid_from_locale(locale);
}
if (!locale || !cpid || !lcid) {
printf("email:%s <profcreate> Invalid Language supplied or
unknown system language\nDeleting profile\n",oclient->emailaddress);
if ((retval = DeleteProfile(mapi_ctx, oclient->profname)) !=
MAPI_E_SUCCESS) {
printf("email:%s <profcreate> DeleteProfile error:
0x%X\n", oclient->emailaddress,retval);
}
talloc_free(mem_ctx);
MAPIUninitialize(mapi_ctx);
return false;
}
cpid_str = talloc_asprintf(mem_ctx, "%d", cpid);
lcid_str = talloc_asprintf(mem_ctx, "0x%.4x", lcid);
mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "codepage",
cpid_str);
mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "language",
lcid_str);
mapi_profile_add_string_attr(mapi_ctx, oclient->profname, "method",
lcid_str);
talloc_free(cpid_str);
talloc_free(lcid_str);
retval = MapiLogonProvider(mapi_ctx, &session, oclient->profname,
oclient->password, PROVIDER_ID_NSPI);
if (retval != MAPI_E_SUCCESS) {
printf("email:%s <profcreate> MapiLogonProvider error:
0x%X\nDeleting profile\n", oclient->emailaddress,retval);
if ((retval = DeleteProfile(mapi_ctx, oclient->profname)) !=
MAPI_E_SUCCESS) {
printf("email:%s <profcreate> DeleteProfile error:
0x%X\n", oclient->emailaddress,retval);
}
MAPIUninitialize(mapi_ctx);
talloc_free(mem_ctx);
return false;
}
retval = ProcessNetworkProfile(session, oclient->username,
(mapi_profile_callback_t) callback, NULL);
if (retval != MAPI_E_SUCCESS && retval != 0x1) {
printf("email:%s <profcreate> ProcessNetworkProfile error:
0x%X\nDeleting profile\n", oclient->emailaddress,retval);
if ((retval = DeleteProfile(mapi_ctx, oclient->profname)) !=
MAPI_E_SUCCESS) {
printf("email:%s <profcreate> DeleteProfile error:
0x%X\n", oclient->emailaddress,retval);
}
MAPIUninitialize(mapi_ctx);
talloc_free(mem_ctx);
return false;
}
MAPIUninitialize(mapi_ctx);
talloc_free(mem_ctx);
return true;
}
bool proflookup(const struct exClient * oclient)
{
enum MAPISTATUS retval;
struct mapi_context *mapi_ctx;
struct mapi_profile profile;
if ((retval = MAPIInitialize(&mapi_ctx, oclient->profdb)) !=
MAPI_E_SUCCESS) {
printf("email:%s <proflookup> MAPIInitialize error : 0x%X\n",
oclient->emailaddress,retval);
return false;
}
retval = OpenProfile(mapi_ctx, &profile, oclient->profname, NULL);
if (retval != MAPI_E_SUCCESS) {
MAPIUninitialize(mapi_ctx);
if(retval != MAPI_E_INVALID_PARAMETER) {
printf("email:%s <proflookup> OpenProfile error :
0x%X\n", oclient->emailaddress,retval);
}
else
printf("email:%s <proflookup> OpenProfile error :
MAPI_E_INVALID_PARAMETER\n",oclient->emailaddress);
return false;
}
MAPIUninitialize(mapi_ctx);
return true;
}
int loginserver(struct exClient *oclient)
{
enum MAPISTATUS retval;
bool need_profcreate = false;
// Check profile database exists
if (access(oclient->profdb, F_OK) != 0) {
need_profcreate = true;
}
// Check specific user's profile exists
if (!proflookup(oclient) != 0) {
need_profcreate = true;
}
// If profile database or specific user's profile not exist, create it
if (need_profcreate) {
if (!profcreate(oclient, 0)) {
printf ("email:%s <loginserver> create profile
failed.\n", oclient->emailaddress);
return -1;
}
else {
printf ("Profile \"%s\" completed and added to
database.\n", oclient->profname);
}
}
// Initialize MAPI
retval = MAPIInitialize(&(oclient->m_mapi_ctx), oclient->profdb);
if (retval != MAPI_E_SUCCESS) {
printf ("email:%s <loginserver> Initialize MAPI failed:
0x%X\n", oclient->emailaddress,retval);
return -1;
}
// Log on EMSMDB and NSPI
retval = MapiLogonEx(oclient->m_mapi_ctx, &(oclient->m_session),
oclient->profname, NULL);
if (retval != MAPI_E_SUCCESS) {
MAPIUninitialize(oclient->m_mapi_ctx);
printf("email:%s <loginserver> Logon EMSMDB and NSPI failed:
0x%X\n", oclient->emailaddress,retval);
return -1;
}
return 0;
}
int fetchmail(struct exClient *oclient)
{
enum MAPISTATUS retval;
TALLOC_CTX *mem_ctx;
mapi_id_t id_inbox;
mapi_object_t obj_store;
mapi_object_t obj_inbox;
mapi_object_t obj_table;
struct SRowSet rowset;
struct SPropTagArray *SPropTagArray;
uint32_t i, ret=0, mailcount=0,
newmail=0;
const uint64_t *mid;
const char *subject;
char subject_show[10] = "\0";
mem_ctx = talloc_named(NULL, 0, "fetchmail");
printf ("email:%s Fetch mail from exchange server, Open Message
Store.\n", oclient->emailaddress);
// Open Message Store
mapi_object_init(&obj_store);
retval = OpenMsgStore(oclient->m_session, &obj_store);
if (retval != MAPI_E_SUCCESS) {
talloc_free(mem_ctx);
printf("email:%s <fetchmail> OpenMsgStore error: 0x%X\n",
oclient->emailaddress,retval);
return 1;
}
// Find Inbox default folder
retval = GetDefaultFolder(&obj_store, &id_inbox, olFolderInbox);
if (retval != MAPI_E_SUCCESS) {
mapi_object_release(&obj_store);
talloc_free(mem_ctx);
printf("email:%s <fetchmail> GetDefaultFolder error: 0x%X\n",
oclient->emailaddress,retval);
return 1;
}
// Open Inbox folder
mapi_object_init(&obj_inbox);
retval = OpenFolder(&obj_store, id_inbox, &obj_inbox);
if (retval != MAPI_E_SUCCESS) {
mapi_object_release(&obj_store);
talloc_free(mem_ctx);
printf("email:%s <fetchmail> OpenFolder error: 0x%X\n",
oclient->emailaddress,retval);
return 1;
}
// Retrieve Inbox content table
mapi_object_init(&obj_table);
retval = GetContentsTable(&obj_inbox, &obj_table, 0, &mailcount);
if (retval != MAPI_E_SUCCESS) {
mapi_object_release(&obj_inbox);
mapi_object_release(&obj_store);
talloc_free(mem_ctx);
printf("email:%s <fetchmail> GetContentsTable error: 0x%X\n",
oclient->emailaddress,retval);
return 1;
}
if (mailcount<=oclient->n_curmailcount || oclient->n_curmailcount==-1) {
ret = 0;
if (oclient->n_curmailcount == -1) oclient->n_curmailcount =
mailcount; // first login
if (mailcount < oclient->n_curmailcount) {
oclient->n_curmailcount = mailcount; // update current
mail count
printf ("email:%s Current inbox mail count: %d,
DECREASED\n", oclient->emailaddress, mailcount);
}
else {
printf ("email:%s Current inbox mail count: %d,
UNCHANGED\n", oclient->emailaddress, mailcount);
}
goto end;
}
newmail = mailcount - oclient->n_curmailcount;
oclient->n_curmailcount = mailcount;
printf ("email:%s Current inbox mail count: %d, %d New
Mail:\n",oclient->emailaddress, mailcount, newmail);
// Create the MAPI table view
SPropTagArray = set_SPropTagArray(mem_ctx, 0x2, PR_MID, PR_SUBJECT);
retval = SetColumns(&obj_table, SPropTagArray);
MAPIFreeBuffer(SPropTagArray);
if (retval != MAPI_E_SUCCESS) {
ret = 1;
printf("email:%s <fetchmail> SetColumns error: 0x%X\n",
oclient->emailaddress,retval);
goto end;
}
// Iterate through rows
while ((retval = QueryRows(&obj_table, 0x32, TBL_ADVANCE, &rowset))
!= -1 && rowset.cRows) {
int n = newmail<rowset.cRows ? newmail : rowset.cRows;
for (i = 0; i < n; i++) {
mid = (const uint64_t
*)find_SPropValue_data(&rowset.aRow[i], PR_MID);
subject = (const char
*)find_SPropValue_data(&rowset.aRow[i], PR_SUBJECT);
if (subject == NULL)
strcpy(subject_show, "null");
else
strncpy(subject_show, subject, 6);
if (strlen (subject_show) == 6) {
strcat (subject_show, "...");
subject_show[9] = 0;
}
printf(" subject: %s [MID: 0x%016"PRIx64"]\n",
subject_show, mid?*mid:0);
}
}
end:
// Note: release sequence is very important
mapi_object_release(&obj_table);
mapi_object_release(&obj_inbox);
mapi_object_release(&obj_store);
talloc_free(mem_ctx);
MAPIUninitialize(oclient->m_mapi_ctx);
return ret;
}
void* simple_thread(void* param)
{
struct exClient* client = (struct exClient*)param;
dump_exclient(client);
while (true) {
if (loginserver(client) != 0) break;
if (fetchmail(client) != 0) break;
sleep (5);
}
return NULL;
}
int main(int argc, char *argv[])
{
struct exClient oclient;
init_exclient(&oclient);
if (gen_exclient (&oclient, "[email protected]",
"hesine-01", "172.27.235.199", NULL))
return 1;
dump_exclient(&oclient);
pthread_t th;
pthread_attr_t thattr;
pthread_attr_init(&thattr);
pthread_create(&th, &thattr, simple_thread, &oclient);
pthread_join (th, NULL);
return 0;
}
_______________________________________________
devel mailing list
[email protected]
http://mailman.openchange.org/listinfo/devel