File: PConnection.c

package info (click to toggle)
coldsync 3.0%2Bpre3-3
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 3,188 kB
  • ctags: 2,033
  • sloc: ansic: 20,386; perl: 2,302; cpp: 1,640; yacc: 1,102; lex: 802; makefile: 533; sh: 177
file content (357 lines) | stat: -rw-r--r-- 7,344 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
/* PConnection.c
 *
 * Functions to manipulate Palm connections (PConnection).
 *
 *	Copyright (C) 1999, Andrew Arensburger.
 *	You may distribute this file under the terms of the Artistic
 *	License, as specified in the README file.
 *
 * $Id: PConnection.c,v 1.33 2002/11/23 17:08:25 azummo Exp $
 */
#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

#ifndef HAVE_ENODEV
#  define ENODEV	999	/* Some hopefully-impossible value */
#endif  /* HAVE_ENODEV */

#if  HAVE_SYS_SELECT_H
#  include <sys/select.h>		/* To make select() work rationally
					 * under AIX */
#endif	/* HAVE_SYS_SELECT_H */

#if HAVE_STRINGS_H
#  include <strings.h>			/* For bzero() under AIX */
#endif	/* HAVE_STRINGS_H */

#if HAVE_LIBINTL_H
#  include <libintl.h>		/* For i18n */
#endif	/* HAVE_LIBINTL_H */

#include <pconn/PConnection.h>

int	io_trace = 0;

extern int pconn_serial_open(PConnection *pconn,
			     const char *fname,
			     const pconn_proto_t protocol);
extern int pconn_net_open(PConnection *pconn,
			  const char *fname,
			  const pconn_proto_t protocol);

#if WITH_USB
extern int pconn_usb_open(PConnection *pconn,
			  const char *fname,
			  const pconn_proto_t protocol);
#endif

#if WITH_LIBUSB
extern int pconn_libusb_open(PConnection *pconn,
			  const char *fname,
			  const pconn_proto_t protocol);
#endif

/* new_PConnection
 * Opens a new connection on the named port. Returns a handle to the
 * new connection, or NULL in case of error.
 */
PConnection *
new_PConnection(char *device,
		const pconn_listen_t listenType,
		const pconn_proto_t protocol,
		const unsigned short flags)
{
	PConnection *pconn;		/* New connection */

	/* Allocate space for the new connection */
	if ((pconn = (PConnection *) malloc(sizeof(PConnection)))
	    == NULL)
	{
		fprintf(stderr, _("Can't allocate new connection.\n"));
		return NULL;
	}

	/* Initialize the common part, if only in case the constructor fails */
	pconn->fd		= -1;
	pconn->flags		= flags;
	pconn->io_bind		= NULL;
	pconn->io_read		= NULL;
	pconn->io_write		= NULL;
	pconn->io_connect	= NULL;
	pconn->io_accept	= NULL;
	pconn->io_drain		= NULL;
	pconn->io_close		= NULL;
	pconn->io_select	= NULL;
	pconn->io_private	= NULL;
	pconn->whosonfirst	= 0;
	pconn->speed		= -1;


	/* Initialize callbacks */
	pconn->palm_errno_set_callback = NULL;
	pconn->palm_status_set_callback = NULL;

	switch (listenType) {
	    case LISTEN_SERIAL:
		if (pconn_serial_open(pconn, device, protocol)
		    < 0)
		{
			free(pconn);
			return NULL;
		}
		break;

	    case LISTEN_NET:
		if (pconn_net_open(pconn, device, protocol) < 0)
		{
			free(pconn);
			return NULL;
		}
		break;

	    case LISTEN_USB:
#if WITH_USB
		/* XXX - Should be able to specify "-" for the filename to
		 * listen on stdin/stdout.
		 * USB over stdin/stdout? I don't think that's a good idea :)
		 */
		if (pconn_usb_open(pconn, device, protocol) < 0)
		{
			free(pconn);
			return NULL;
		}
		break;
#else	/* WITH_USB */
		/* This version of ColdSync was built without USB support.
		 * Print a message to this effect. This is done this way
		 * because even without USB support, the parser recognizes
		 *	listen usb {}
		 * the man page talks about it, etc.
		 */
		fprintf(stderr, _("Error: USB support not enabled.\n"));
		free(pconn);
		return NULL;
#endif

	    case LISTEN_LIBUSB:
#if WITH_LIBUSB
		/* XXX - Should be able to specify "-" for the filename to
		 * listen on stdin/stdout.
		 * USB over stdin/stdout? I don't think that's a good idea :)
		 */
		if (pconn_libusb_open(pconn, device, protocol) < 0)
		{
			free(pconn);
			return NULL;
		}
		break;
#else	/* WITH_LIBUSB */
		/* This version of ColdSync was built without libusb support.
		 * Print a message to this effect. This is done this way
		 * because even without USB support, the parser recognizes
		 *	listen libusb {}
		 * the man page talks about it, etc.
		 */
		fprintf(stderr, _("Error: USB through libusb support not enabled.\n"));
		free(pconn);
		return NULL;
#endif
	  
	    default:
		fprintf(stderr, _("%s: unknown listen type %d.\n"),
			"new_PConnection", listenType);
		free(pconn);
		return NULL;
	}
	
	pconn->status = PCONNSTAT_UP;

	return pconn;
}

int
PConnClose(PConnection *pconn)
{
	int err = 0;

	if (pconn == NULL)
		return 0;

	/* Make sure everything that was sent to the Palm has actually been
	 * sent. Without this, the file descriptor gets closed before
	 * having been properly flushed, so the Palm never gets the final
	 * ACK for the DLP EndOfSync command, and hangs until it times out,
	 * which wastes the user's time.
	 */
	/* XXX - Why does this hang until the Palm times out, under
	 * FreeBSD? (But only with 'xcopilot', it appears.)
	 */
	IO_TRACE(4)
		fprintf(stderr, "Calling io_drain()\n");

	if (pconn->io_drain != NULL)
		PConn_drain(pconn);

	/* Close the file descriptor and clean up
	 * The test is for paranoia, in case it never got assigned.
	 */
	if (pconn->io_close != NULL)
		err = PConn_close(pconn);

	/* Free the PConnection */
	free(pconn);

	return err;
}

static void
_PConn_handle_ioerr(struct PConnection *p)
{
	switch (errno)
	{
		case ENODEV:
		case ENXIO:
			p->fd = -1;
			break;
		default:
			break;
	}
}


/* PConn_bind
 * This function is mainly here to try to adhere to the socket API.
 * XXX - For now, it's hardwired to set a SLP address, which is highly
 * bogus.
 */
int
PConn_bind(PConnection *p,
	   const void *addr,
	   const int addrlen)
{
	return (*p->io_bind)(p, addr, addrlen);
}

int
PConn_read(struct PConnection *p,
		unsigned char *buf,
		int len)
{
	int err = (*p->io_read)(p, buf, len);

	if (err < 0)
	{
		_PConn_handle_ioerr(p);
		PConn_set_palmerrno(p, (palmerrno_t) PALMERR_SYSTEM);
	}
	else if (err == 0)
	{
		PConn_set_palmerrno(p, PALMERR_EOF);
	}

	return err;
}

int
PConn_write(struct PConnection *p,
		unsigned const char *buf,
		const int len)
{
	int err = (*p->io_write)(p, buf, len);

	if (err < 0)
	{
		_PConn_handle_ioerr(p);
		PConn_set_palmerrno(p, PALMERR_SYSTEM);
	}

	return err;
}

int
PConn_connect(struct PConnection *p,
		  const void *addr,
		  const int addrlen)
{
	return (*p->io_connect)(p, addr, addrlen);
}

int
PConn_accept(struct PConnection *p)
{
	return (*p->io_accept)(p);
}

int
PConn_drain(struct PConnection *p)
{
	return (*p->io_drain)(p);
}

int
PConn_close(struct PConnection *p)
{
	return (*p->io_close)(p);
}

int
PConn_select(struct PConnection *p,
		 pconn_direction direction,
		 struct timeval *tvp)
{
	int err = (*p->io_select)(p, direction, tvp);

	if (err == 0)
	{
	 	/* select() timed out */
	 	PConn_set_palmerrno(p, PALMERR_TIMEOUT);
	 	PConn_set_status(p, PCONNSTAT_LOST);
	}

	return err;
}

palmerrno_t
PConn_get_palmerrno(PConnection *p)
{
	return p->palm_errno;
}

void
PConn_set_palmerrno(PConnection *p, palmerrno_t palm_errno)
{
	if (p->palm_errno_set_callback)
		(*p->palm_errno_set_callback)(p, palm_errno);

	p->palm_errno = palm_errno;
}

void
PConn_set_status(PConnection *p, pconn_stat status)
{
	if (p->palm_status_set_callback)
		(*p->palm_status_set_callback)(p, status);

	p->status = status;
}

pconn_stat
PConn_get_status(PConnection *p)
{
	return p->status;
}

int
PConn_isonline(PConnection *p)
{
	return p->status & PCONNSTAT_UP;
}

/* This is for Emacs's benefit:
 * Local Variables: ***
 * fill-column:	75 ***
 * End: ***
 */