⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tap.c

📁 使用Modem发送网上传呼
💻 C
字号:
/*	-*- mode: c; mode: fold -*-	*/# include	"config.h"# include	<stdio.h># include	<stdlib.h># include	<ctype.h># include	<string.h># include	"pager.h"/*{{{	definitions & typedefs */# define	DEF_SERVICE_TYPE	"PG"# define	DEF_TERMINAL_TYPE	'1'# define	CHKTYPE(sss,ccc)	((((sss)[0] & 0xff) << 16) | (((sss)[1] & 0xff) << 8) | ((ccc) & 0xff))# define	CHKSTYPE(cc1,cc2,cc3)	((((cc1) & 0xff) << 16) | (((cc2) & 0xff) << 8) | ((cc3) & 0xff))typedef enum {	None,	PG1}	Type;typedef struct _rmsg {	string_t	*str;	int		rnr;	struct _rmsg	*next;}	rmsg;typedef struct {# ifndef	NDEBUG# define	MAGIC		MKMAGIC ('t', 'a', 'p', '\0')	long	magic;# endif		/* NDEBUG */	void	*sp;		/* the serial connection		*/	void	*ctab;		/* the conversion table			*/	void	(*logger) (char, char *, ...);	string_t		*callid;	/* caller id				*/	Type	typ;		/* the connection type			*/	Bool	pre16;		/* if p.version before 1.6 is used	*/	/* timing and retry values					*/	int	t1, t2, t3, t4, t5;	int	n1, n2, n3;	int	licnt, locnt;		rmsg	*r, *prv;	/* response message(s) on callback	*/}	tap;/*}}}*//*{{{	convert */static intfield_convert (tap *t, string_t *ptr, string_t *cf){	int	n;	int	ch;	cf -> str = NULL;	cf -> size = ptr -> len + 32;	if (! (cf -> str = malloc (cf -> size + 2)))		return ERR_FATAL;	for (n = 0, cf -> len = 0; n < ptr -> len; ++n) {		if (cf -> len + 2 >= cf -> size)			if (! sexpand (cf, cf -> size + 32))				return ERR_FATAL;		ch = cv_conv (t -> ctab, ptr -> str[n]);		if (ch != -1)			switch ((char_t) ch) {			case '\x0d': case '\x0a': case '\x1b':			case '\x02': case '\x03': case '\x1f':			case '\x17': case '\x04': case '\x1a':				if (! t -> pre16) {					cf -> str[cf -> len++] = '\x1a';					cf -> str[cf -> len++] = (char_t) (ch + 0x40);				}				break;			default:				cf -> str[cf -> len++] = (char_t) ch;				break;		}	}	if (cf -> str) {		cf -> str[cf -> len] = '\0';		return NO_ERR;	}	return ERR_FATAL;}static char	chkstr[] = "0123456789:;<=>?";static string_t **convert_tap (tap *t, string_t **field){	string_t	**ret;	int		fcnt;	string_t	*cf;	char_t		*ptr;	int		cnt, siz;	char_t		tmp[260];	Bool		needchk;	unsigned long	chk;	int		fld, off, len;	int		n, m;	ret = NULL;	for (fcnt = 0; field[fcnt]; ++fcnt)		;	if (cf = (string_t *) malloc ((fcnt + 1) * sizeof (string_t))) {		for (fld = 0; fld < fcnt; ++fld)			if (field_convert (t, field[fld], & cf[fld]) != NO_ERR) {				while (--fld >= 0)					free (cf[fld].str);				free (cf);				break;			}		if (fld < fcnt)			return NULL;		cnt = 0;		siz = 0;		n = 0;		needchk = False;		for (fld = 0, off = 0; fld < fcnt; ) {			ptr = cf[fld].str + off;			len = cf[fld].len - off;			do {				if (! n)					tmp[n++] = '\x02';				if (len) {					tmp[n++] = *ptr++;					--len;					++off;				}				if (! len) {					off = 0;					++fld;					tmp[n++] = '\r';					if (fld == fcnt) {						tmp[n++] = '\x03';						needchk = True;					} else if (n >= 230) {						tmp[n++] = '\x17';						needchk = True;					}				} else if (n >= 250) {					tmp[n++] = '\x1f';					needchk = True;				}				if (needchk) {					needchk = False;					for (m = 0, chk = 0; m < n; ++m)						chk += tmp[m] & 0xff;					tmp[n++] = chkstr[(chk >> 8) & 0xf];					tmp[n++] = chkstr[(chk >> 4) & 0xf];					tmp[n++] = chkstr[chk & 0xf];					tmp[n++] = '\r';					tmp[n] = '\0';					if (cnt >= siz) {						siz += 4;						if (! (ret = (string_t **) Realloc (ret, (siz + 1) * sizeof (string_t *))))							return NULL;					}					if (! (ret[cnt] = snew (tmp, n))) {						while (--cnt >= 0)							sfree (ret[cnt]);						free (ret);						return NULL;					}					++cnt;					ret[cnt] = NULL;					n = 0;				}			}	while (len);		}		for (fld = 0; fld < fcnt; ++fld)			free (cf[fld].str);		free (cf);	}	return ret;}/*}}}*//*{{{	callback interface for receiving response numbers */static voidgetresponse (void *sp, string_t *s, char_t ch, void *data){	tap	*t = (tap *) data;	rmsg	*r;		if (t && (! t -> pre16) && s && (s -> len > 0))		if (sisdigit (s, 0)) {			if (r = (rmsg *) malloc (sizeof (rmsg)))				if (r -> str = snew (s -> str, s -> len + 2)) {					r -> rnr = stoi (r -> str);					r -> next = NULL;					if (t -> prv)						t -> prv -> next = r;					else						t -> r = r;					t -> prv = r;				} else					free (r);		} else if ((! siscntrl (s, 0)) && (r = t -> prv) && scatc (r -> str, "\n")) {			if (sisspace (s, 0))				sdel (s, 0, 1);			scat (r -> str, s);		}}static voidfree_resp (tap *t){	rmsg	*tmp;		if (t) {		while (t -> r) {			tmp = t -> r;			t -> r = t -> r -> next;			sfree (tmp -> str);			free (tmp);		}		t -> prv = NULL;	}}static voidsetcb (tap *t){	if (! t -> pre16) {		free_resp (t);		tty_suspend_callback (t -> sp, False);	}}static voidclrcb (tap *t){	if (! t -> pre16) {		tty_suspend_callback (t -> sp, True);		free_resp (t);	}}/*}}}*//*{{{	response handling */static intshow_response (tap *t){	rmsg		*r;	int		nr, typ;	char		*line, *ptr;		for (r = t -> r, nr = -1; r; r = r -> next) {		nr = r -> rnr;		if (line = sextract (r -> str)) {			for (ptr = line; isdigit (*ptr); ++ptr)				;			while (isspace (*ptr))				++ptr;		} else			ptr = "(none)";		switch (nr) {		case 110:			V (1, ("TAP Version: %s\n", ptr));			break;		case 111:			V (1, ("processing input\n"));			break;		case 112:			V (1, ("maximum pages entered\n"));			break;		case 113:			V (1, ("maximum time reached\n"));			break;		case 114:			V (1, ("Welcome: %s\n", ptr));			break;		case 115:			V (1, ("Byebye: %s\n", ptr));			break;		case 211:			V (1, ("Page(s) sent successful\n"));			break;		case 212:			V (1, ("Long message truncated and sent\n"));			break;		case 213:			V (1, ("Message accepted - held for deferred delivery\n"));			break;		case 214:			V (1, ("%d character maximum, message has been truncated and sent\n", atoi (ptr)));			break;		case 501:			V (1, ("Timeout during input\n"));			break;		case 502:			V (1, ("Unexpected character received before transaction\n"));			break;		case 503:			V (1, ("Excessive attempts to send/re-send a transaction with checksum errors\n"));			break;		case 504:			V (1, ("Message have to be empty for tone-only pager\n"));			break;		case 505:			V (1, ("Message must not contain characters for a numeric pager\n"));			break;		case 506:			V (1, ("Excessive invalid pages received\n"));			break;		case 507:			V (1, ("Invalid logon attempt: Incorrectly formed logon sequence\n"));			break;		case 508:			V (1, ("Invalid Logon attempt: Service type and category given is not supported\n"));			break;		case 509:			V (1, ("Invalid Logon attempt: Invalid password supplied\n"));			break;		case 510:			V (1, ("Illegal Pager ID\n"));			break;		case 511:			V (1, ("Invalid Pager ID\n"));			break;		case 512:			V (1, ("Temporarily cannot deliver to Pager ID\n"));			break;		case 513:			V (1, ("Long message rejected for exceeding maximum character length\n"));			break;		case 514:			V (1, ("Checksum error\n"));			break;		case 515:			V (1, ("Message format error\n"));			break;		case 516:			V (1, ("Message quota temporarily exceeded\n"));			break;		case 517:			V (1, ("%d character maximum, message rejected\n", atoi (ptr)));			break;		default:			typ = nr / 100;			switch (typ) {			default:				V (1, ("Response"));				break;			case 1:				V (1, ("Informal"));				break;			case 2:				V (1, ("Success"));				break;			case 5:				V (1, ("Fail"));				break;			}			V (1, (" %03d: %s\n", r -> rnr, ptr));			break;		}		if (line)			free (line);	}	return nr;}/*}}}*//*{{{	login/logout */inttap_login (void *tp, char *stype, char ttype, char *passwd, string_t *callid){	tap	*t = (tap *) tp;	int	n, ep;	char	*cbuf;	int	clen;	int	err;	MCHK (t);	if ((! t) || (! t -> sp))		return ERR_ABORT;	if (! stype)		stype = DEF_SERVICE_TYPE;	else if (strlen (stype) != 2) {		V (1, ("Invalid service type %s\n", stype));		return ERR_ABORT;	}	if (! ttype)		ttype = DEF_TERMINAL_TYPE;	switch (CHKTYPE (stype, ttype)) {	case CHKSTYPE ('P', 'G', '1'):		t -> typ = PG1;		break;	}	if (t -> typ == None) {		V (1, ("Invalid service/terminal type combination\n"));		return ERR_ABORT;	}	t -> callid = sfree (t -> callid);	if (callid && (! (t -> callid = snew (callid -> str, callid -> len))))		return ERR_ABORT;	for (n = 0; n < t -> n1; ++n)		if (tty_send (t -> sp, "\r", 1) != 1)			V (1, ("Unable to send initial CR\n"));		else if (tty_expect (t -> sp, t -> t1, "ID=", 3, NULL) == 1) {			V (1, ("Send initial CR\n"));			break;		}	if (n == t -> n1) {		V (1, ("Didn't got initial response\n"));		return ERR_ABORT;	}	if (cbuf = malloc ((passwd ? strlen (passwd) : 0) + strlen (stype) + 16)) {		if (passwd)			sprintf (cbuf, "\x1b%s%c%s\r", stype, ttype, passwd);		else			sprintf (cbuf, "\x1b%s%c\r", stype, ttype);		clen = strlen (cbuf);	} else {		V (1, ("Out of memory!\n"));		return ERR_ABORT;	}	err = NO_ERR;	for (n = 0; n < t -> licnt; ++n)		if (tty_send (t -> sp, cbuf, clen) != clen)			V (1, ("Unable to send Logon request\n"));		else {			setcb (t);			ep = tty_expect (t -> sp, t -> t3, "\x06\r", 2, "ID=", 3, "\x15\r", 2, "\x1b\x04\r", 3, NULL);			if ((! t -> pre16) && t -> r)				show_response (t);			if (ep == 1) {				V (1, ("Login request accepted\n"));				break;			} else if (ep == 2)				V (1, ("Oops, got ID= again\n"));			else if (ep == 3) 				V (1, ("Login request not accepted\n"));			else if (ep == 4) {				V (1, ("Logout forced\n"));				n = t -> licnt;				err = ERR_ABORT;				break;			}		}	free (cbuf);	clrcb (t);	if (n == t -> licnt) {		V (1, ("Could not login\n"));		return (err == NO_ERR) ? ERR_FATAL : err;	}	if (tty_expect (t -> sp, t -> t3, "\x1b[p\r", 4, NULL) != 1) {		V (1, ("Didn't got Go Ahead message\n"));		return ERR_FATAL;	} else		V (1, ("Successful login\n"));	return NO_ERR;}inttap_logout (void *tp){	tap	*t = (tap *) tp;	int	err;	int	n, ep;	MCHK (t);	if ((! t) || (! t -> sp))		return ERR_FATAL;	err = NO_ERR;	for (n = 0; n < t -> locnt; ++n) 		if (tty_send (t -> sp, "\x04\r", 2) != 2)			V (1, ("Unable to send logout request\n"));		else {			setcb (t);			ep = tty_expect (t -> sp, t -> t3, "\x1b\x04\r", 3, "\x1e\r", 2, NULL);			if ((! t -> pre16) && t -> r)				show_response (t);			if (ep == 1) {				V (1, ("Message sending completed\n"));				break;			} else if (ep == 2) {				V (1, ("Message sending failed (%d)\n", ep));				err = ERR_FATAL;				n = t -> locnt;				break;			}		}	clrcb (t);	if (n == t -> locnt) {		if (err == NO_ERR)			err = ERR_FAIL;		V (1, ("Unable to logout\n"));		return err;	} else		V (1, ("Logout successful\n"));	return NO_ERR;}/*}}}*//*{{{	transmit */inttap_transmit (void *tp, string_t **field, Bool last){	tap		*t = (tap *) tp;	int		err;	string_t	**snd;	char		*ptr;	int		len;	int		n, m, ep;	MCHK (t);	if ((! t) || (! t -> sp))		return ERR_FATAL;	switch (t -> typ) {	default:	case None:		V (1, ("Invalid service/terminal type\n"));		return ERR_FAIL;	case PG1:		for (n = 0; field[n]; ++n)			;		if (n != 2) {			V (1, ("PG1 service/terminal type needs exactly two fields\n"));			return ERR_FAIL;		}		break;	}	err = ERR_FATAL;	if (snd = convert_tap (t, field)) {		err = NO_ERR;		for (m = 0; snd[m]; ++m) {			ptr = (char *) snd[m] -> str;			len = snd[m] -> len;			for (n = 0; n < t -> n2; ++n)				if (tty_send (t -> sp, ptr, len) != len)					V (1, ("Unable to transmit part\n"));				else {					setcb (t);					ep = tty_expect (t -> sp, t -> t3, "\x06\r", 2, "\x15\r", 2, "\x1e\r", 2, "\x1b\x04\r", 3, NULL);					if ((! t -> pre16) && t -> r)						show_response (t);					if (ep == 1) {						V (1, ("Transmited part\n"));						break;					} else if (ep == 2)						V (1, ("Can't transmit part\n"));					else if (ep == 3) {						V (1, ("Can't transmit this message\n"));						err = ERR_FAIL;						n = t -> n2;						break;					} else if (ep == 4) {						V (1, ("Logout forced\n"));						err = ERR_ABORT;						n = t -> n2;						break;					}				}			sfree (snd[m]);			clrcb (t);			if (n == t -> n2) {				V (1, ("Unable to send part %d\n", m));				for (n = m + 1; snd[n]; ++n)					sfree (snd[n]);				break;			}		}		if (! snd[m])			V (1, ("Sent message\n"));		else if (err == NO_ERR)			err = ERR_FAIL;		free (snd);	} else		V (1, ("Unable to convert message\n"));	return err;}/*}}}*//*{{{	configuration */voidtap_config (void *tp, void (*logger) (char, char *, ...), Bool pre16){	tap	*t = (tap *) tp;		MCHK (t);	if (t) {		t -> logger = logger;		if (t -> pre16 = pre16)			tty_suspend_callback (t -> sp, True);	}}voidtap_timeouts (void *tp, int t1, int t2, int t3, int t4, int t5){	tap	*t = (tap *) tp;	MCHK (t);	if (t) {		if (t1 != -1)			t -> t1 = t1;		if (t2 != -1)			t -> t2 = t2;		if (t3 != -1)			t -> t3 = t3;		if (t4 != -1)			t -> t4 = t4;		if (t5 != -1)			t -> t5 = t5;	}}voidtap_retries (void *tp, int n1, int n2, int n3, int licnt, int locnt){	tap	*t = (tap *) tp;	MCHK (t);	if (t) {		if (n1 != -1)			t -> n1 = n1;		if (n2 != -1)			t -> n2 = n2;		if (n3 != -1)			t -> n3 = n3;		if (licnt != -1)			t -> licnt = licnt;		if (locnt != -1)			t -> locnt = locnt;	}}voidtap_set_convtable (void *tp, void *ctab){	tap	*t = (tap *) tp;		MCHK (t);	if (t) {		if (t -> ctab)			cv_free (t -> ctab);		t -> ctab = ctab;	}}static voidnew_convtab (tap *t){	int	n;		if (t -> ctab = cv_new ())		for (n = 128; n < 256; ++n)			cv_invalid (t -> ctab, (char_t) n);}voidtap_add_convtable (void *tp, void *ctab){	tap	*t = (tap *) tp;		MCHK (t);	if (t) {		if (! t -> ctab)			new_convtab (t);		if (t -> ctab)			cv_merge (t -> ctab, ctab, True);	}}/*}}}*//*{{{	new/free/etc */void *tap_new (void *sp){	tap	*t;		if (t = (tap *) malloc (sizeof (tap))) {# ifndef	NDEBUG		t -> magic = MAGIC;# endif		/* NDEBUG */		t -> sp = sp;		new_convtab (t);		t -> logger = NULL;		t -> callid = NULL;		t -> typ = None;		t -> pre16 = False;		t -> t1 = 2;		t -> t2 = 1;		t -> t3 = 10;		t -> t4 = 4;		t -> t5 = 8;		t -> n1 = 3;		t -> n2 = 3;		t -> n3 = 3;		t -> licnt = 3;		t -> locnt = 3;		t -> r = NULL;		t -> prv = NULL;		tty_set_line_callback (t -> sp, getresponse, "\r", (void *) t);		tty_suspend_callback (t -> sp, True);	}	return (void *) t;}void *tap_free (void *tp){	tap	*t = (tap *) tp;		MCHK (t);	if (t) {		if (t -> ctab)			cv_free (t -> ctab);		if (t -> sp)			tty_set_line_callback (t -> sp, NULL, NULL, NULL);		if (t -> callid)			sfree (t -> callid);		if (t -> r)			free_resp (t);		free (t);	}	return NULL;}inttap_preinit (void){	return 0;}voidtap_postdeinit (void){}/*}}}*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -