home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 2
/
goldfish_vol2_cd1.bin
/
files
/
comm
/
misc
/
elcheapofax
/
faxcmd
/
libfax
/
rcs
/
response.c,v
< prev
next >
Wrap
Text File
|
1993-12-21
|
12KB
|
572 lines
head 1.7;
access;
symbols
OCT93:1.7;
locks;
comment @ * @;
1.7
date 93.09.18.20.16.23; author Rhialto; state Exp;
branches;
next 1.6;
1.6
date 93.07.13.05.41.27; author Rhialto; state Exp;
branches;
next 1.5;
1.5
date 93.07.12.02.52.14; author Rhialto; state Exp;
branches;
next 1.4;
1.4
date 93.06.12.00.25.58; author Rhialto; state Exp;
branches;
next 1.3;
1.3
date 93.06.11.23.22.07; author Rhialto; state Exp;
branches;
next 1.2;
1.2
date 93.06.11.16.15.25; author Rhialto; state Exp;
branches;
next 1.1;
1.1
date 93.06.11.15.19.27; author Rhialto; state Exp;
branches;
next ;
desc
@Parse modem responses, both normal and fax types.
@
1.7
log
@Add FAX_F_FPOLL.
@
text
@/* $Id: response.c,v 1.6 1993/07/13 05:41:27 Rhialto Exp $
* $Log: response.c,v $
* Revision 1.6 1993/07/13 05:41:27 Rhialto
* Now understands verbal response codes instead of non-standard
* numeric codes only.
*
* Revision 1.5 1993/07/12 02:52:14 Rhialto
* Allow both \r and \n at end of numeric responses.
*
* Revision 1.4 1993/06/12 00:25:58 Rhialto
* Simplify parsing of OK and CONNECT responses.
*
* Revision 1.3 1993/06/11 23:22:07 Rhialto
* Recognise numeric form of CONNECT message.
*
* Revision 1.2 1993/06/11 16:15:25 Rhialto
* First real RCS checkin
*
*/
/*
This file is part of the NetFax system.
(c) Copyright 1989 by David M. Siegel and Sundar Narasimhan.
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "log.h"
#include "c2proto.h"
#include "read.h"
#include "response.h"
static int parse_t30_response(char * reply, char * offset);
static int parse_id_response(char * reply, char * str);
static int parse_int_response(char * reply, char * offset);
static int parse_text_response(FaxModem * f, char * reply);
static int parse_3_response(char * reply, FaxModem * f);
static int parse_4_response(char * reply, FaxModem * f);
static int parse_6_response(char * reply, FaxModem * f);
static int parse_7_response(char * reply, FaxModem * f);
static int parse_8_response(char * reply, FaxModem * f);
#define arg(f) ((int)(&(((FaxModem *)NULL)->f)))
#define sarg(f) ((int)(((FaxModem *)NULL)->f))
static struct _parse_switch {
int flag;
char *string;
int (*func)(char *, char *);
int offset;
} parse_switch[] = {
{FAX_F_FCON, "+FCON", NULL, 0},
{FAX_F_FNSF, "+FNSF", NULL, 0},
{FAX_F_FCFR, "+FCFR", NULL, 0},
{FAX_F_FHNG, "+FHNG", parse_int_response, arg(hangup_code)},
{FAX_F_FPTS, "+FPTS", parse_int_response, arg(ppr_code)},
{FAX_F_FET, "+FET", parse_int_response, arg(ppm_code)},
{FAX_F_FTSI, "+FTSI", parse_id_response, sarg(ftsi_id)},
{FAX_F_FCSI, "+FCSI", parse_id_response, sarg(fcsi_id)},
{FAX_F_FCSI, "+FCIG", parse_id_response, sarg(fcig_id)},
{FAX_F_FDCS, "+FDCS", parse_t30_response, arg(fdcs_params)},
{FAX_F_FDCS, "+FDIS", parse_t30_response, arg(fdis_params)},
{FAX_F_FDCS, "+FDTC", parse_t30_response, arg(fdtc_params)},
{FAX_F_FPOLL,"+FPOLL", NULL, 0},
{0, "CED", NULL, NULL}, /* some faxes send this */
{0, "NO CARRIER", parse_3_response, 0},
{0, "ERROR", parse_4_response, 0},
{0, "NO DIALTONE", parse_6_response, 0},
{0, "BUSY", parse_7_response, 0},
{0, "NO ANSWER", parse_8_response, 0},
};
#define parse_switch_len (sizeof(parse_switch)/sizeof(struct _parse_switch))
#undef arg
#undef sarg
static int parse_t30_response(reply, offset)
char *reply;
char *offset;
{
T30params *params = (T30params *)offset;
if (strlen(reply) < 6)
return (-1);
if (sscanf(reply+6, "%d,%d,%d,%d,%d,%d,%d,%d",
¶ms->vr, ¶ms->br, ¶ms->wd, ¶ms->ln,
¶ms->df, ¶ms->ec, ¶ms->bf, ¶ms->st) != 8)
return (-1);
return (0);
}
static int parse_id_response(reply, str)
char *reply;
char *str;
{
char *fquote, *lquote;
if ((fquote = strchr(reply, '"')) == NULL) {
/* return (-1); */
lquote = reply + 7;
/*printf("sharp mode, scanning %s.\n", lquote);*/
while (*lquote == ' ')
lquote++;
strcpy(str, lquote);
return (0);
}
if ((lquote = strrchr(reply, '"')) == NULL)
return (-1);
if (fquote == lquote)
return (-1);
*lquote = '\0';
strcpy(str, fquote+1);
return (0);
}
static int parse_int_response(reply, offset)
char *reply;
char *offset;
{
int *value = (int *)offset;
char *start = strchr(reply, ':');
if (start == NULL)
return (-1);
if (sscanf(start+1, "%d", value) != 1)
return (-1);
return (0);
}
static int parse_3_response(char * reply, FaxModem * f)
{
f->result = RESULT_NO_CARRIER;
}
static int parse_4_response(char * reply, FaxModem * f)
{
f->result = RESULT_ERROR;
}
static int parse_6_response(char * reply, FaxModem * f)
{
f->result = RESULT_NO_DIALTONE;
}
static int parse_7_response(char * reply, FaxModem * f)
{
f->result = RESULT_BUSY;
}
static int parse_8_response(char * reply, FaxModem * f)
{
f->result = RESULT_NO_ANSWER;
}
/*
Parse a text response from the modem. Update the flag for the response,
and process the message according to the switch, as defined above.
*/
static int parse_text_response(f, reply)
FaxModem *f;
char *reply;
{
int i;
log(L_INFO, "parse_text_response: parsing: \"%s\"", reply);
for (i = 0; i < parse_switch_len; i++) {
struct _parse_switch *p = &parse_switch[i];
if (strncmp(p->string, reply, strlen(p->string)) == 0) {
f->flags |= p->flag;
if (p->func != NULL) {
if ((*p->func)(reply, &((char *)f)[p->offset]) < 0) {
log(L_NOTICE, "parse_text_response: error processing \"%s\"",
reply);
return -1;
}
}
return (0);
}
}
log(L_NOTICE, "parse_text_response: parse failed: \"%s\"", reply);
return (-1);
}
typedef enum {
RESPONSE_START,
RESPONSE_NUMERIC,
RESPONSE_TEXT,
RESPONSE_DONE,
} response_state;
/*
* This function parses numeric and connect responses from the faxmodem.
* It is assumed that the modem is in numeric response mode. We first
* parse the response from the passed in buf, and then we read more
* from the modem, if necessary. We do this since some routines do
* read ahead.
*
* INPUTS: serial_fd a serial stream file descriptor from which to read
* response a faxmodem_response structure
*
* It fills in any relevant slots of the faxmodem_response structure
* which is passed to it.
*
* Responses are a single digit followed by <CR>.
*/
int get_modem_response_from_buf(f, timeout, buf, bufsize)
FaxModem *f;
int timeout;
char *buf;
int bufsize;
{
response_state state = RESPONSE_START;
char reply[1024];
char *reply_ptr;
char c;
log(L_DEBUG, "get_modem_reponse: entering with timeout %d", timeout);
/* start with a clean status */
f->status = MODEM_STATUS_OK;
f->result = 0;
/*
* Read in all responses, and figure out if we are getting a number
* result code (RESPONSE_NUMERIC) or text (RESPONSE_TEXT).
*/
while (state != RESPONSE_DONE) {
int count;
if (bufsize > 0) {
c = *(buf++);
bufsize--;
count = 1;
} else
count = tread(f->fd, &c, 1, timeout);
switch (count) {
case -1:
f->status = MODEM_STATUS_FAILED;
return (-1);
case 0:
f->status = MODEM_STATUS_TIMEOUT;
return (-1);
default:
break;
}
switch (state) {
case RESPONSE_START:
reply_ptr = reply;
if (isdigit(c)) {
f->result = (int)(c - '0');
state = RESPONSE_NUMERIC;
} else if (c == '\r' || c == '\n') {
state = RESPONSE_START;
} else {
*reply_ptr++ = c;
state = RESPONSE_TEXT;
}
break;
case RESPONSE_NUMERIC:
/* Numeric responses (not allowed by the spec anyway)
* apparently only end in \r, not in \r\n
*/
if (c == '\r' || c == '\n') {
log(L_INFO, "numeric response code: %d", f->result);
if (f->result == RESULT_CONNECT)
goto connect;
state = RESPONSE_DONE;
} else {
*reply_ptr++ = c;
state = RESPONSE_TEXT;
}
break;
case RESPONSE_TEXT:
if (c == '\n') {
state = RESPONSE_START;
*reply_ptr++ = '\0';
if (strncmp(reply, "CONNECT", 7) == 0) {
connect:
log(L_INFO, "received connect response");
f->flags |= FAX_F_CONNECT;
f->result = 1;
state = RESPONSE_DONE;
} else if (strncmp(reply, "OK", 2) == 0) {
f->result = 0;
state = RESPONSE_DONE;
} else {
parse_text_response(f, reply);
if (f->result)
state = RESPONSE_DONE;
}
} else
*reply_ptr++ = c;
break;
default:
log(L_EMERG, "get_modem_response: illegal state");
abort();
}
}
return (0);
}
/*
* Since most routines are in sync with the modem, they simply call
* this convenience function.
*/
int get_modem_response(f, timeout)
FaxModem *f;
int timeout;
{
return (get_modem_response_from_buf(f, timeout, NULL, 0));
}
/*
* This function clears the state of the modem, and should only
* be called when starting a new fax session. Other than that,
* the FaxModem structure will always hold the most complete
* information available for the current fax session.
*/
void init_modem_response(f)
FaxModem *f;
{
f->status = MODEM_STATUS_OK;
f->flags = 0;
f->result = 0;
f->dialer_code = 0;
}
/* ARGSUSED */
void faxmodem_print_status(f)
FaxModem *f;
{
}
@
1.6
log
@Now understands verbal response codes instead of non-standard
numeric codes only.
@
text
@d1 1
a1 1
/* $Id: response.c,v 1.5 1993/07/12 02:52:14 Rhialto Exp $
d3 4
d81 1
@
1.5
log
@Allow both \r and \n at end of numeric responses.
@
text
@d1 1
a1 1
/* $Id: response.c,v 1.4 1993/06/12 00:25:58 Rhialto Exp $
d3 3
d50 5
d65 3
a67 3
{FAX_F_FCON, "+FCON", NULL, NULL},
{FAX_F_FNSF, "+FNSF", NULL, NULL},
{FAX_F_FCFR, "+FCFR", NULL, NULL},
d78 5
d151 25
d245 1
d309 3
d314 5
a318 4
} else if (strncmp(reply, "OK", 2) == 0) {
state = RESPONSE_DONE;
} else
parse_text_response(f, reply);
d320 1
a320 1
*reply_ptr++ = c;
@
1.4
log
@Simplify parsing of OK and CONNECT responses.
@
text
@d1 1
a1 1
/* $Id: response.c,v 1.3 1993/06/11 23:22:07 Rhialto Exp $
d3 3
d248 4
a251 1
if (c == '\r') {
@
1.3
log
@Recognise numeric form of CONNECT message.
@
text
@d1 1
a1 1
/* $Id: response.c,v 1.2 1993/06/11 16:15:25 Rhialto Exp $
d3 3
d152 1
a152 1
if ((*p->func)(reply, &((char *)f)[p->offset]) < 0)
d155 2
a170 1
RESPONSE_CONNECT,
d257 1
a257 1
if (c == '\r' || c == '\n') {
d260 9
a268 3
if (strncmp(reply, "CONNECT", 7) == 0)
state = RESPONSE_CONNECT; /* assume \r then \n for this to work */
else
a271 12
break;
case RESPONSE_CONNECT:
if (c != '\n')
log(L_WARNING, "invalid connect message");
else {
connect:
log(L_INFO, "received connect response");
}
f->flags |= FAX_F_CONNECT;
f->result = 0;
state = RESPONSE_DONE;
@
1.2
log
@First real RCS checkin
@
text
@d1 5
a5 2
/* $Id$
* $Log$
d227 1
a227 1
case RESPONSE_START:
d240 1
a240 1
case RESPONSE_NUMERIC:
d243 2
d252 1
a252 1
case RESPONSE_TEXT:
d257 1
a257 1
state = RESPONSE_CONNECT;
d264 1
a264 1
case RESPONSE_CONNECT:
d266 5
a270 3
log(L_WARNING, "invalid connect message");
else
log(L_INFO, "received connect response");
d276 1
a276 1
default:
@
1.1
log
@Initial revision
@
text
@d1 3
d60 1
d90 10
a99 2
if ((fquote = strchr(reply, '"')) == NULL)
return (-1);
@