297 lines
6.2 KiB
C
297 lines
6.2 KiB
C
/*
|
|
*
|
|
* ISDN loader for intelligent cards.
|
|
*
|
|
* Copyright (c) 1993-1995 Matthias Urlichs <urlichs@noris.de>.
|
|
*/
|
|
|
|
#include "master.h"
|
|
|
|
static void
|
|
card_load_close(struct loader *ld, char success)
|
|
{
|
|
if(ld->name != NULL)
|
|
ld->card->name = ld->name;
|
|
if(ld->file != NULL)
|
|
fclose(ld->file);
|
|
if(ld->timer)
|
|
untimeout(card_load,ld);
|
|
{
|
|
struct loader **ldp = &isdn4_loader;
|
|
while(*ldp != NULL) {
|
|
if(*ldp == ld) {
|
|
*ldp = ld->next;
|
|
break;
|
|
}
|
|
ldp = &(*ldp)->next;
|
|
}
|
|
}
|
|
if(success) {
|
|
char newconn = 0;
|
|
struct conninfo *conn;
|
|
for(conn = isdn4_conn; conn != NULL; conn = conn->next) {
|
|
if(conn->seqnum == ld->connseq)
|
|
break;
|
|
}
|
|
if(conn == NULL) {
|
|
conn = gcxmalloc(sizeof(*conn));
|
|
newconn = 1;
|
|
}
|
|
if(conn != NULL) {
|
|
if(newconn) {
|
|
bzero(conn,sizeof(*conn));
|
|
conn->cause = ID_priv_Print;
|
|
conn->cardname = ld->card->name;
|
|
conn->seqnum = ++connseq;
|
|
conn->next = isdn4_conn; isdn4_conn = conn;
|
|
}
|
|
conn->causeInfo = "active interface";
|
|
dropconn(conn);
|
|
}
|
|
}
|
|
gfree(ld);
|
|
if(cards_loading > 0)
|
|
cards_loading--;
|
|
do_run_now++;
|
|
timeout(run_now,NULL,HZ/3);
|
|
}
|
|
|
|
void
|
|
card_load_fail(struct loader *ld, int err)
|
|
{
|
|
mblk_t *mj = allocb (32, BPRI_LO);
|
|
int len;
|
|
struct isdncard **pcard, *card = ld->card;
|
|
|
|
if(err == -EAGAIN) {
|
|
if(ld->timer)
|
|
untimeout(card_load,ld);
|
|
if(ld->thislen > 0)
|
|
ld->foffset -= ld->thislen;
|
|
else {
|
|
ld->thislen = 0;
|
|
ld->nrfile--;
|
|
}
|
|
ld->timer = 1;
|
|
timeout(card_load,ld,HZ/2);
|
|
return;
|
|
}
|
|
|
|
for (pcard = &isdn4_card; *pcard != NULL; pcard = &(*pcard)->next) {
|
|
if (card == *pcard) {
|
|
*pcard = card->next;
|
|
break;
|
|
}
|
|
}
|
|
|
|
syslog(LOG_ERR,"Card %s was not loaded: Error %s at file %d, pos %d\n",ld->card,strerror(-err),ld->nrfile,ld->foffset);
|
|
|
|
/* Tell lower layer to forget the thing */
|
|
|
|
if (mj != NULL) {
|
|
m_putid (mj, CMD_NOCARD);
|
|
m_putsx (mj, ARG_CARD);
|
|
m_putsz (mj, ld->name);
|
|
len = mj->b_wptr - mj->b_rptr;
|
|
DUMPW (mj->b_rptr, len);
|
|
(void) strwrite (xs_mon, (uchar_t *) mj->b_rptr, len, 1);
|
|
freeb (mj);
|
|
}
|
|
|
|
{
|
|
char newconn = 0;
|
|
struct conninfo *conn;
|
|
for(conn = isdn4_conn; conn != NULL; conn = conn->next) {
|
|
if(conn->seqnum == ld->connseq)
|
|
break;
|
|
}
|
|
if(conn == NULL) {
|
|
conn = gcxmalloc(sizeof(*conn));
|
|
newconn = 1;
|
|
}
|
|
if(conn != NULL) {
|
|
if(newconn) {
|
|
bzero(conn,sizeof(*conn));
|
|
conn->cause = ID_priv_Print;
|
|
conn->seqnum = ++connseq;
|
|
conn->next = isdn4_conn; isdn4_conn = conn;
|
|
}
|
|
conn->causeInfo = "Load failed";
|
|
dropconn(conn);
|
|
}
|
|
}
|
|
card_load_close(ld,0);
|
|
gfree(card);
|
|
}
|
|
|
|
void
|
|
card_load(struct loader *ld)
|
|
{
|
|
cf lf;
|
|
int do_again, thisseq;
|
|
|
|
ld->timer = 0;
|
|
again:
|
|
do_again = 0;
|
|
thisseq = 0;
|
|
/* Now find the next applicable entry. ld->seqnum is the cf number of the
|
|
next file to load. */
|
|
for(lf = cf_LF; lf != NULL; lf = lf->next) {
|
|
thisseq++;
|
|
if(!wildmatch(ld->name,lf->card))
|
|
continue;
|
|
if(ld->seqnum != 0 && ld->seqnum != thisseq) {
|
|
if(ld->seqnum < thisseq && (do_again == 0 || do_again < thisseq))
|
|
do_again = thisseq;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
if(lf == NULL) {
|
|
if(ld->seqnum == 0) {
|
|
syslog(LOG_ERR, "Card loader for %s has a config problem (seq %d)!\n",ld->card,ld->seqnum);
|
|
goto ex_load;
|
|
}
|
|
if(do_again) {
|
|
ld->seqnum = do_again;
|
|
goto again;
|
|
}
|
|
} else
|
|
do_again = 1;
|
|
if(ld->thislen >= 0) {
|
|
if (!do_again || (ld->file != NULL)) {
|
|
char *buf = NULL;
|
|
int len, xlen, foffset;
|
|
mblk_t xx;
|
|
struct datab db;
|
|
struct iovec io[3];
|
|
streamchar ans[50];
|
|
|
|
if(ld->file != NULL) {
|
|
buf = gbxmalloc(lf->num);
|
|
if(buf == NULL) {
|
|
syslog(LOG_ERR, "Card loader for %s !\n",ld->card);
|
|
goto ex_load;
|
|
}
|
|
|
|
if(fseek(ld->file,ld->foffset,0) < 0) {
|
|
syslog(LOG_ERR, "Card loader for %s: fseek returned %m\n",ld->card);
|
|
goto ex_load;
|
|
}
|
|
len = fread(buf,1,lf->num,ld->file);
|
|
if(len < 0) {
|
|
syslog(LOG_ERR, "Card loader for %s: read returned %m\n",ld->card);
|
|
gfree(buf);
|
|
goto ex_load;
|
|
}
|
|
foffset = ld->foffset;
|
|
ld->foffset += len;
|
|
ld->thislen = len;
|
|
} else {
|
|
len = 0;
|
|
foffset = 0;
|
|
ld->foffset = 0;
|
|
}
|
|
if(!do_again && (ld->file == NULL))
|
|
++ld->nrfile; /* last file; we're finished */
|
|
xx.b_rptr = xx.b_wptr = ans;
|
|
xx.b_datap = &db;
|
|
db.db_base = ans;
|
|
db.db_lim = ans + sizeof (ans);
|
|
m_putid (&xx, CMD_LOADFILE);
|
|
m_putsx(&xx,ARG_CARD);
|
|
m_putsz(&xx,ld->name);
|
|
m_putsx(&xx,ARG_SEQNUM);
|
|
m_puti(&xx,ld->nrfile);
|
|
m_putsx(&xx,ARG_OFFSET);
|
|
m_puti(&xx,foffset);
|
|
|
|
*xx.b_wptr++ = ' ';
|
|
xlen = xx.b_wptr - xx.b_rptr;
|
|
DUMPW (ans, xlen);
|
|
io[0].iov_base = ans;
|
|
io[0].iov_len = xlen;
|
|
io[1].iov_base = "::";
|
|
io[1].iov_len = 2;
|
|
if(len > 0) {
|
|
io[2].iov_base = buf;
|
|
io[2].iov_len = len;
|
|
len = 3;
|
|
} else {
|
|
len = 2;
|
|
if(ld->file != NULL) {
|
|
fclose(ld->file);
|
|
ld->file = NULL;
|
|
ld->seqnum++;
|
|
}
|
|
}
|
|
(void) strwritev (xs_mon, io,len, 1);
|
|
if(buf != NULL)
|
|
gfree(buf);
|
|
ld->timer = 1;
|
|
timeout(card_load,ld,(ld->file || !lf) ? HZ : (HZ*lf->num2+HZ/3));
|
|
if(!do_again)
|
|
ld->thislen = -1;
|
|
return;
|
|
} else {
|
|
ld->seqnum = thisseq;
|
|
ld->nrfile++;
|
|
ld->file = fopen(lf->arg,"r");
|
|
ld->foffset = 0;
|
|
if(ld->file == NULL) {
|
|
syslog(LOG_ERR, "Card loader for %s: file %s: %m\n",ld->card,lf->arg);
|
|
goto ex_load;
|
|
}
|
|
ld->timer = 1;
|
|
timeout(card_load,ld,HZ/3);
|
|
return;
|
|
}
|
|
} else {
|
|
cf dl;
|
|
|
|
for(dl = cf_DL; dl != NULL; dl = dl->next) {
|
|
struct iovec io[3];
|
|
int len;
|
|
mblk_t xx;
|
|
struct datab db;
|
|
streamchar ans[30];
|
|
|
|
if(!wildmatch(dl->card,ld->name))
|
|
continue;
|
|
xx.b_rptr = xx.b_wptr = ans;
|
|
xx.b_datap = &db;
|
|
db.db_base = ans;
|
|
db.db_lim = ans + sizeof (ans);
|
|
m_putid (&xx, CMD_DOCARD);
|
|
m_putsx(&xx,ARG_CARD);
|
|
m_putsz(&xx,ld->name);
|
|
|
|
*xx.b_wptr++ = ' ';
|
|
len = xx.b_wptr - xx.b_rptr;
|
|
DUMPW (ans, len);
|
|
io[0].iov_base = ans;
|
|
io[0].iov_len = len;
|
|
len = 1;
|
|
if(dl->args != NULL) {
|
|
printf ("+ ");
|
|
io[len].iov_base = "::";
|
|
io[len].iov_len = 2;
|
|
len++;
|
|
io[len].iov_base = dl->args;
|
|
io[len].iov_len = strlen(dl->args);
|
|
DUMPW (dl->args,io[len].iov_len);
|
|
len++;
|
|
}
|
|
(void) strwritev (xs_mon, io,len, 1);
|
|
card_load_close(ld,1);
|
|
return;
|
|
}
|
|
card_load_fail(ld,-EIO);
|
|
}
|
|
return;
|
|
|
|
ex_load:
|
|
card_load_fail(ld,-EIO);
|
|
return;
|
|
}
|