373 lines
6.4 KiB
C
373 lines
6.4 KiB
C
/* -*- mode: c; mode: fold -*- */
|
|
# include "config.h"
|
|
# include <stdio.h>
|
|
# include <stdlib.h>
|
|
# include <ctype.h>
|
|
# include <string.h>
|
|
# include "pager.h"
|
|
|
|
/*{{{ typedefs */
|
|
typedef struct {
|
|
# ifndef NDEBUG
|
|
# define MAGIC MKMAGIC('a', 's', 'c', '\0')
|
|
long magic;
|
|
# endif /* NDEBUG */
|
|
void *sp;
|
|
void *ctab;
|
|
void (*logger) (char, char *, ...);
|
|
char *callid;
|
|
int deftout;
|
|
char *alogin;
|
|
char *alogout;
|
|
char *apid;
|
|
char *amsg;
|
|
char *anext;
|
|
char *async;
|
|
|
|
date_t delay;
|
|
date_t expire;
|
|
Bool rds;
|
|
} asc;
|
|
/*}}}*/
|
|
/*{{{ convert */
|
|
static char *
|
|
escape_string (asc *a, char *str)
|
|
{
|
|
int c;
|
|
char ch, prev;
|
|
char *ret;
|
|
int n;
|
|
|
|
if (ret = malloc (strlen (str) * 2 + 16)) {
|
|
prev = '\0';
|
|
ch = '\0';
|
|
for (n = 0; *str; prev = ch) {
|
|
c = cv_conv (a -> ctab, (char_t) *str++);
|
|
if (c < 0)
|
|
continue;
|
|
ch = (char) c;
|
|
if ((ch == '<') && isspace (prev)) {
|
|
ret[n++] = '\\';
|
|
ret[n++] = '<';
|
|
} else if (ch == ' ') {
|
|
ret[n++] = '\\';
|
|
ret[n++] = 's';
|
|
} else if (ch == '\a') {
|
|
ret[n++] = '\\';
|
|
ret[n++] = 'a';
|
|
} else if (ch == '\b') {
|
|
ret[n++] = '\\';
|
|
ret[n++] = 'b';
|
|
} else if (ch == '\f') {
|
|
ret[n++] = '\\';
|
|
ret[n++] = 'f';
|
|
} else if (ch == '\n') {
|
|
ret[n++] = '\\';
|
|
ret[n++] = 'n';
|
|
} else if (ch == '\r') {
|
|
ret[n++] = '\\';
|
|
ret[n++] = 'r';
|
|
} else if (ch == '\t') {
|
|
ret[n++] = '\\';
|
|
ret[n++] = 't';
|
|
} else if (ch) {
|
|
if ((ch == '\\') || (ch == '^') || (ch == '%'))
|
|
ret[n++] = '\\';
|
|
ret[n++] = ch;
|
|
}
|
|
}
|
|
ret[n] = '\0';
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static char *
|
|
convert_asc (asc *a, char *pat, char *pid, char *msg)
|
|
{
|
|
char *str;
|
|
int siz, len;
|
|
char *ptr;
|
|
int plen;
|
|
char scr[32];
|
|
|
|
str = NULL;
|
|
siz = 0;
|
|
len = 0;
|
|
while (*pat) {
|
|
if (len + 2 >= siz) {
|
|
siz += 32;
|
|
if (! (str = Realloc (str, siz + 2)))
|
|
break;
|
|
}
|
|
if (*pat == '\\') {
|
|
++pat;
|
|
if (*pat) {
|
|
ptr = NULL;
|
|
switch (*pat) {
|
|
case 'C': ptr = a -> callid; break;
|
|
case 'P': ptr = pid; break;
|
|
case 'M': ptr = msg; break;
|
|
case 'R':
|
|
strcpy (scr, (a -> rds ? "1" : "0"));
|
|
ptr = scr;
|
|
break;
|
|
default:
|
|
str[len++] = '\\';
|
|
str[len++] = *pat;
|
|
break;
|
|
}
|
|
if (ptr && (ptr = escape_string (a, ptr))) {
|
|
if (plen = strlen (ptr)) {
|
|
if (len + plen + 2 >= siz) {
|
|
siz = len + plen + 32;
|
|
if (! (str = Realloc (str, siz)))
|
|
break;
|
|
}
|
|
strcpy (str + len, ptr);
|
|
len += plen;
|
|
}
|
|
free (ptr);
|
|
}
|
|
++pat;
|
|
}
|
|
} else if (! iscntrl (*pat))
|
|
str[len++] = *pat++;
|
|
else {
|
|
str[len++] = ' ';
|
|
++pat;
|
|
}
|
|
}
|
|
if (str)
|
|
str[len] = '\0';
|
|
return str;
|
|
}
|
|
/*}}}*/
|
|
/*{{{ general sending routine */
|
|
static int
|
|
do_send (asc *a, char *what, char *pat, char *pid, char *msg)
|
|
{
|
|
int ret;
|
|
char *str;
|
|
|
|
ret = ERR_FAIL;
|
|
if (a && a -> sp)
|
|
if (pat && *pat) {
|
|
if (str = convert_asc (a, pat, pid, msg)) {
|
|
if (tty_send_expect (a -> sp, a -> deftout, str, NULL) != -1) {
|
|
V (1, ("Ascii %s sent\n", what));
|
|
ret = NO_ERR;
|
|
} else
|
|
V (1, ("Unable to send %s\n", what));
|
|
free (str);
|
|
}
|
|
} else
|
|
ret = NO_ERR;
|
|
return ret;
|
|
}
|
|
/*}}}*/
|
|
/*{{{ login/logout/transmit/next/sync */
|
|
int
|
|
asc_login (void *ap, string_t *cid)
|
|
{
|
|
asc *a = (asc *) ap;
|
|
|
|
MCHK (a);
|
|
if (a) {
|
|
if (a -> callid)
|
|
free (a -> callid);
|
|
a -> callid = sextract (cid);
|
|
}
|
|
return a ? do_send (a, "login", a -> alogin, NULL, NULL) : ERR_ABORT;
|
|
}
|
|
|
|
int
|
|
asc_logout (void *ap)
|
|
{
|
|
asc *a = (asc *) ap;
|
|
|
|
MCHK (a);
|
|
return a ? do_send (a, "logout", a -> alogout, NULL, NULL) : ERR_FATAL;
|
|
}
|
|
|
|
int
|
|
asc_transmit (void *ap, char *pid, char *msg)
|
|
{
|
|
asc *a = (asc *) ap;
|
|
int n;
|
|
|
|
MCHK (a);
|
|
if (! a)
|
|
return ERR_FATAL;
|
|
if ((n = do_send (a, "pagerid", a -> apid, pid, NULL)) != NO_ERR)
|
|
return n;
|
|
return do_send (a, "message", a -> amsg, NULL, msg);
|
|
}
|
|
|
|
int
|
|
asc_next (void *ap)
|
|
{
|
|
asc *a = (asc *) ap;
|
|
|
|
MCHK (a);
|
|
return a ? do_send (a, "next", a -> anext, NULL, NULL) : ERR_FATAL;
|
|
}
|
|
|
|
int
|
|
asc_sync (void *ap)
|
|
{
|
|
asc *a = (asc *) ap;
|
|
|
|
MCHK (a);
|
|
return a ? do_send (a, "sync", a -> async, NULL, NULL) : ERR_FATAL;
|
|
}
|
|
/*}}}*/
|
|
/*{{{ config */
|
|
void
|
|
asc_config (void *ap, void (*logger) (char, char *, ...),
|
|
int deftout, char *alogin, char *alogout, char *apid, char *amsg, char *anext, char *async,
|
|
date_t *delay, date_t *expire, Bool rds)
|
|
{
|
|
asc *a = (asc *) ap;
|
|
|
|
MCHK (a);
|
|
if (a) {
|
|
a -> logger = logger;
|
|
if (deftout != -1)
|
|
a -> deftout = deftout;
|
|
if (alogin) {
|
|
if (a -> alogin)
|
|
free (a -> alogin);
|
|
a -> alogin = strdup (alogin);
|
|
}
|
|
if (alogout) {
|
|
if (a -> alogout)
|
|
free (a -> alogout);
|
|
a -> alogout = strdup (alogout);
|
|
}
|
|
if (apid) {
|
|
if (a -> apid)
|
|
free (a -> apid);
|
|
a -> apid = strdup (apid);
|
|
}
|
|
if (amsg) {
|
|
if (a -> amsg)
|
|
free (a -> amsg);
|
|
a -> amsg = strdup (amsg);
|
|
}
|
|
if (anext) {
|
|
if (a -> anext)
|
|
free (a -> anext);
|
|
a -> anext = strdup (anext);
|
|
}
|
|
if (async) {
|
|
if (a -> async)
|
|
free (a -> async);
|
|
a -> async = strdup (async);
|
|
}
|
|
if (delay)
|
|
a -> delay = *delay;
|
|
else
|
|
dat_clear (& a -> delay);
|
|
if (expire)
|
|
a -> expire = *expire;
|
|
else
|
|
dat_clear (& a -> expire);
|
|
a -> rds = rds;
|
|
}
|
|
}
|
|
|
|
void
|
|
asc_set_convtable (void *ap, void *ctab)
|
|
{
|
|
asc *a = (asc *) ap;
|
|
|
|
MCHK (a);
|
|
if (a) {
|
|
if (a -> ctab)
|
|
cv_free (a -> ctab);
|
|
a -> ctab = ctab;
|
|
}
|
|
}
|
|
|
|
void
|
|
asc_add_convtable (void *ap, void *ctab)
|
|
{
|
|
asc *a = (asc *) ap;
|
|
|
|
MCHK (a);
|
|
if (a) {
|
|
if (! a -> ctab)
|
|
a -> ctab = cv_new ();
|
|
if (a -> ctab)
|
|
cv_merge (a -> ctab, ctab, True);
|
|
}
|
|
}
|
|
/*}}}*/
|
|
/*{{{ new/free/etc */
|
|
void *
|
|
asc_new (void *sp)
|
|
{
|
|
asc *a;
|
|
|
|
if (a = (asc *) malloc (sizeof (asc))) {
|
|
# ifndef NDEBUG
|
|
a -> magic = MAGIC;
|
|
# endif /* NDEBUG */
|
|
a -> sp = sp;
|
|
a -> ctab = NULL;
|
|
a -> logger = NULL;
|
|
a -> callid = NULL;
|
|
a -> deftout = 10;
|
|
a -> alogin = NULL;
|
|
a -> alogout = NULL;
|
|
a -> apid = NULL;
|
|
a -> amsg = NULL;
|
|
a -> anext = NULL;
|
|
a -> async = NULL;
|
|
dat_clear (& a -> delay);
|
|
dat_clear (& a -> expire);
|
|
a -> rds = False;
|
|
}
|
|
return (void *) a;
|
|
}
|
|
|
|
void *
|
|
asc_free (void *ap)
|
|
{
|
|
asc *a = (asc *) ap;
|
|
|
|
MCHK (a);
|
|
if (a) {
|
|
if (a -> ctab)
|
|
cv_free (a -> ctab);
|
|
if (a -> callid)
|
|
free (a -> callid);
|
|
if (a -> alogin)
|
|
free (a -> alogin);
|
|
if (a -> alogout)
|
|
free (a -> alogout);
|
|
if (a -> apid)
|
|
free (a -> apid);
|
|
if (a -> amsg)
|
|
free (a -> amsg);
|
|
if (a -> anext)
|
|
free (a -> anext);
|
|
if (a -> async)
|
|
free (a -> async);
|
|
free (a);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int
|
|
asc_preinit (void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
asc_postdeinit (void)
|
|
{
|
|
}
|
|
/*}}}*/
|