[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [coldsync-hackers] speed



On Friday 17 October 2003 19:07, Christophe Beauregard wrote:

> Correct me if I'm wrong, but instead of implementing another SPC stack,
> couldn't he just link his C program to libpconn and use
> spc_client/dlp_cmd directly? That _appears_ to be what it's for, but I'm
> not sure how far the implementation goes towards what is needed.

Okay, that's cool. It actually works.

I cranked out a couple simple C conduits that use the spc_client code. See 
attached. Once the SPC pipe is set up, all the DLP stuff just plain works. 
There's also a plethora of code within coldsync itself which can serve as 
guidelines on how to use the DLP stuff.

libpconn isn't exacly designed to be an external library (spc.h #including 
"config.h" is a good indicator), but I hacked up a Makefile that does the 
trick.

Oh, and it would probably be a Bad Thing to try to close the SPC pconn using 
PConn_close(). The spc_client close function looks like it'll probably do 
the Wrong Thing. Actually, spc_client.c could use some fine tuning all 
around. The read() and write() methods don't handle errors, for example.

c.
/*
	Very simple example of a ColdSync sync conduit in C.

	It demonstrates an interesting function: to be able to use the
	DLP (PalmOS RPC) function set from a C conduit.

	It's also not one of my better pieces of code. You're better off throwing
	away the code and using the concepts than trying to expand this into a
	"real" conduit.

	christophe.beauregard@sympatico.ca
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>

#include <pconn/spc_client.h>
#include <pconn/dlp_cmd.h>

int main( int ac, char* av[] ) {
	PConnection* pconn = NULL;
	struct dlp_time dt;
	time_t t;
	struct tm* now;
	int spc_fd = -1;
	char* tmp;
	char buf[PATH_MAX];
	char* prefs[256];	/* arbitrary, but large enough */
	unsigned int nprefs = 0;
	char* headers[256];
	unsigned int nheaders = 0;

	memset( &dt, 0, sizeof(dt) );

	/* not pretty, but all we expect is "-config" or "conduit sync" */
	if( ac == 2 ) {
		if( strcmp(av[1],"-config") ) {
			fprintf( stderr, "usage: %s <flavor|-config>\n", av[0] );
			exit( -1 );
		}

		printf(
			"conduit sync {\n"
			"\tpath: \"%s\"\n"
			"\ttype: none\n"
			"}\n", av[0] );

		exit( 0 );
	} else if( ac == 3 && !strcmp(av[1],"conduit") ) {
		if( strcmp(av[2],"sync") ) {
			fprintf( stderr, "401 Unknown flavor '%s'\n", av[2] );
			exit( -1 );
		}
	} else {
		fprintf( stderr, "usage: %s -config\n", av[0] );
		exit( -1 );
	}

	/* read headers */
	while( fgets(buf,sizeof(buf),stdin) != NULL ) {
		buf[sizeof(buf)-1] = 0;	/* fgets() is pretty stupid */
		tmp = strrchr( buf, '\n' );	/* fgets doesn't strip trailing newline */
		if( tmp ) *tmp = 0;

		if( buf[0] == 0 ) break;	/* end of headers */

		tmp = strchr(buf,':');
		if( tmp == NULL ) {
			printf( "401 Invalid input [%s]\n", buf );
			exit( -1 );
		}
		tmp ++;
		while( *tmp && isspace(*tmp) ) tmp++;

		if( !strncmp("Preference:", buf, 11 ) ) {
			prefs[nprefs++] = strdup( tmp );
		} else {
			headers[nheaders++] = strdup( headers );
			
			/* For this conduit, we only care about SPCpipe. The rest of the
			headers are gravy */
			if( !strncmp( "SPCPipe:", buf, 8 ) ) {
				spc_fd = atoi( tmp );
			}
		}
	}

	if( spc_fd < 0 ) {
		printf( "401 Unable to get SPC pipe\n" );
		exit( -1 );
	}

	/* open a SPC connection */
	pconn = new_spc_client( spc_fd );
	if( pconn == NULL ) {
		printf( "401 Failed to create SPC connection\n" );
		exit( -1 );
	}

	/* feed time to PDA */
	t = time(NULL);
	now = localtime(&t);
	if( now == NULL ) {
		printf( "401 %s\n", strerror(errno) );
		exit( -1 );
	}

	dt.year = now->tm_year + 1900;
	dt.month = now->tm_mon + 1;
	dt.day = now->tm_mday;
	dt.hour = now->tm_hour;
	dt.minute = now->tm_min;
	dt.second = now->tm_sec;

	DlpSetSysDateTime( pconn, &dt );

	printf( "201 Timing is everything\n" );
	exit( 0 );
}
/*
	More complicated example of a ColdSync sync conduit in C.

	This is ugly, but it shows you how you can read the memo database
	in a C conduit.

	christophe.beauregard@sympatico.ca
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>

#include <pconn/spc_client.h>
#include <pconn/dlp_cmd.h>

static void process_memo( PConnection* pconn ) {
	ubyte dbhandle;
	uword index;
	struct dlp_recinfo record;
	char* buf = NULL;
	struct dlp_opendbinfo dbinfo;
	int rc;

	rc = DlpOpenDB( pconn, 0, "MemoDB", DLPCMD_MODE_READ, &dbhandle );
	if( rc ) return;

	rc = DlpReadOpenDBInfo( pconn, dbhandle, &dbinfo );
	if( rc ) dbinfo.numrecs = 0;

	fprintf( stderr, "Reading %hu records\n", dbinfo.numrecs );

	for( index = 0; index < dbinfo.numrecs; index ++ ) {
		rc = DlpReadRecordByIndex( pconn, dbhandle, index, &record );
		if( rc ) break;

		rc = DlpReadRecordByID( pconn, dbhandle, record.id, 0, DLPC_RECORD_TOEND,
			&record, &buf );
		if( rc ) break;

		fprintf( stderr, "Memo %u (%hu bytes)\n%s\n\n\n",
			record.id, record.size, buf );
	}

	DlpCloseDB( pconn, dbhandle, 0 );
}

int main( int ac, char* av[] ) {
	PConnection* pconn = NULL;
	int spc_fd = -1;
	char* tmp;
	char buf[PATH_MAX];
	char* prefs[256];	/* arbitrary, but large enough */
	unsigned int nprefs = 0;
	char* headers[256];
	unsigned int nheaders = 0;

	/* not pretty, but all we expect is "-config" or "conduit sync" */
	if( ac == 2 ) {
		if( strcmp(av[1],"-config") ) {
			fprintf( stderr, "usage: %s <flavor|-config>\n", av[0] );
			exit( -1 );
		}

		printf(
			"conduit sync {\n"
			"\tpath: \"%s\"\n"
			"\ttype: memo/DATA\n"
			"}\n", av[0] );

		exit( 0 );
	} else if( ac == 3 && !strcmp(av[1],"conduit") ) {
		if( strcmp(av[2],"sync") ) {
			fprintf( stderr, "401 Unknown flavor '%s'\n", av[2] );
			exit( -1 );
		}
	} else {
		fprintf( stderr, "usage: %s -config\n", av[0] );
		exit( -1 );
	}

	/* read headers */
	while( fgets(buf,sizeof(buf),stdin) != NULL ) {
		buf[sizeof(buf)-1] = 0;	/* fgets() is pretty stupid */
		tmp = strrchr( buf, '\n' );	/* fgets doesn't strip trailing newline */
		if( tmp ) *tmp = 0;

		if( buf[0] == 0 ) break;	/* end of headers */

		tmp = strchr(buf,':');
		if( tmp == NULL ) {
			printf( "401 Invalid input [%s]\n", buf );
			exit( -1 );
		}
		tmp ++;
		while( *tmp && isspace(*tmp) ) tmp++;

		if( !strncmp("Preference:", buf, 11 ) ) {
			prefs[nprefs++] = strdup( tmp );
		} else {
			headers[nheaders++] = strdup( headers );
			
			/* For this conduit, we only care about SPCpipe. The rest of the
			headers are gravy */
			if( !strncmp( "SPCPipe:", buf, 8 ) ) {
				spc_fd = atoi( tmp );
			}
		}
	}

	if( spc_fd < 0 ) {
		printf( "401 Unable to get SPC pipe\n" );
		exit( -1 );
	}

	/* open a SPC connection */
	pconn = new_spc_client( spc_fd );
	if( pconn == NULL ) {
		printf( "401 Failed to create SPC connection\n" );
		exit( -1 );
	}

	process_memo( pconn );

	printf( "201 Make a note\n" );
	exit( 0 );
}
all: time-conduit memo-conduit

COLDSYNC=$(HOME)/src/coldsync-cvs/coldsync

time-conduit: time-conduit.c
	$(CC) $(CFLAGS) -g -o time-conduit -I$(COLDSYNC) -I$(COLDSYNC)/include \
		-L$(COLDSYNC)/libpconn -L$(COLDSYNC)/libpdb \
		-lusb -lcap time-conduit.c -lpconn

memo-conduit: memo-conduit.c
	$(CC) $(CFLAGS) -g -o memo-conduit -I$(COLDSYNC) -I$(COLDSYNC)/include \
		-L$(COLDSYNC)/libpconn -L$(COLDSYNC)/libpdb \
		-lusb -lcap memo-conduit.c -lpconn