📄 ckudia.c
字号:
#define FAILED 2
/*
* Failure reasons for use with the 'longjmp' exit.
*/
#define F_time 1 /* timeout */
#define F_int 2 /* interrupt */
#define F_modem 3 /* modem-detected failure */
#define F_minit 4 /* cannot initialize modem */
static
char *F_reason[5] = { /* failure reasons for message */
"Unknown", "Timeout", "Interrupt", "Modem", "Initialize" };
static int tries = 0;
#define LBUFL 100
static char lbuf[LBUFL];
static jmp_buf sjbuf;
static int (*savAlrm)(); /* for saving alarm handler */
static int (*savInt)(); /* for saving interrupt handler */
dialtime() { /* timer interrupt handler */
longjmp( sjbuf, F_time );
}
dialint() /* user-interrupt handler */
{
longjmp( sjbuf, F_int );
}
static
ttolSlow(s,millisec) char *s; int millisec; { /* output s-l-o-w-l-y */
for (; *s; s++) {
ttoc(*s);
msleep(millisec);
}
}
/*
* Wait for a string of characters.
*
* The characters are waited for individually, and other characters may
* be received "in between". This merely guarantees that the characters
* ARE received, and in the order specified.
*/
static
waitFor(s) char *s;
{
CHAR c;
while ( c = *s++ ) /* while more characters remain... */
while ( ( ttinc(0) & 0177 ) != c ) ; /* wait for the character */
}
static
didWeGet(s,r) char *s, *r; { /* Looks in string s for response r */
int lr = strlen(r); /* 0 means not found, 1 means found it */
int i;
for (i = strlen(s)-lr; i >= 0; i--)
if ( s[i] == r[0] ) if ( !strncmp(s+i,r,lr) ) return( 1 );
return( 0 );
}
/* R E S E T -- Reset alarms, etc. on exit. */
static
reset ()
{
alarm(0);
signal(SIGALRM,savAlrm); /* restore alarm handler */
signal(SIGINT,savInt); /* restore interrupt handler */
}
/* D I A L -- Dial up the remote system */
dial(telnbr) char *telnbr; {
char c;
char *i, *j;
int waitct, status;
char errmsg[50], *erp;
MDMINF *pmdminf; /* pointer to modem-specific info */
int augmdmtyp; /* "augmented" modem type, to handle modem modes */
int mdmEcho = 0; /* assume modem does not echo */
int n, n1;
char *pc; /* pointer to a character */
if (!mdmtyp) {
printf("Sorry, you must 'set modem' first\n");
return(-2);
}
if (!local) {
printf("Sorry, you must 'set line' first\n");
return(-2);
}
if (speed < 0) {
printf("Sorry, you must 'set speed' first\n");
return(-2);
}
if (ttopen(ttname,&local,mdmtyp) < 0) {/* Open, no wait for carrier */
erp = errmsg;
sprintf(erp,"Sorry, can't open %s",ttname);
perror(errmsg);
return(-2);
}
pmdminf = ptrtab[mdmtyp-1]; /* set pointer to modem info */
augmdmtyp = mdmtyp; /* initialize "augmented" modem type */
/* cont'd... */
/* interdigit waits for tone dial */
/* ...dial, cont'd */
waitct = 1*strlen(telnbr) ; /* compute time to dial worst case */
waitct += pmdminf->dial_time; /* dialtone + completion wait times */
for (i=telnbr; *i; i++) /* add in pause characters time */
for (j=pmdminf->pause_chars; *j; j++)
if (*i == *j) {
waitct += pmdminf->pause_time;
break;
}
printf("Dialing thru %s, speed %d, number %s.\r\n",ttname,speed,telnbr);
printf("The timeout for completing the call is %d seconds.\r\n",waitct);
printf("Type the interrupt character to cancel the dialing.\r\n");
/* Hang up the modem (in case it wasn't "on hook") */
if ( tthang() < 0 ) {
printf("Sorry, Can't hang up tty line\n");
return(-2);
}
/* Condition console terminal and communication line */
/* place line into "clocal" dialing state */
if ( ttpkt(speed,DIALING) < 0 ) {
printf("Sorry, Can't condition communication line\n");
return(-2);
}
/*
* Establish jump vector, or handle "failure" jumps.
*/
if ( n = setjmp(sjbuf) ) /* if a "failure jump" was taken... */
{
alarm ( 0 ); /* disable timeouts */
if ( n1 = setjmp(sjbuf) ) /* failure while handling failure */
{
printf ( "%s failure while handling failure.\r\n", F_reason[n1] );
}
else /* first (i.e., non-nested) failure */
{
signal ( SIGALRM, dialtime ); /* be sure to catch signals */
if ( signal ( SIGINT, SIG_IGN ) != SIG_IGN )
signal ( SIGINT, dialint );
alarm ( 5 ); /* be sure to get out of this section */
ttclos (); /* hangup and close the line */
}
switch ( n ) /* type of failure */
{
case F_time: /* timed out */
{
printf ( "No connection made within the allotted time.\r\n" );
break;
}
case F_int: /* dialing interrupted */
{
printf ( "Dialing interrupted.\r\n" );
break;
}
case F_modem: /* modem detected a failure */
{
printf ( "Failed (\"" );
for ( pc=lbuf; *pc; pc++ )
if ( isprint(*pc) )
putchar(*pc); /* display printable reason */
printf ( "\").\r\n" );
break;
}
case F_minit: /* cannot initialize modem */
{
printf ( "Cannot initialize modem.\r\n" );
break;
}
}
reset (); /* reset alarms, etc. */
return ( -2 ); /* exit with failure code */
}
/*
* Set timer and interrupt handlers.
*/
savAlrm = signal(SIGALRM,dialtime); /* set alarm handler */
if ( ( savInt = signal ( SIGINT, SIG_IGN ) ) != SIG_IGN )
signal ( SIGINT, dialint ); /* set int handler if not ignored */
alarm(10); /* give modem 10 seconds to wake up */
ttflui(); /* flush input buffer if any */
/*
* Put modem in command mode.
*/
#define OKAY 1 /* modem attention attempt status */
#define IGNORE 2
#define GOT_O -2
#define GOT_A -3
switch (augmdmtyp) {
case n_HAYES:
case n_HAYESNV:
while(tries++ < 4) {
ttol( HAYES.wake_str, strlen(HAYES.wake_str) ); /* wakeup */
status = 0;
while ( status <= 0 ) {
switch (ttinc(0) & 0177) {
case 'A': /* echoing, ignore */
status = GOT_A;
break;
case 'T':
if (status == GOT_A) {
mdmEcho = 1; /* expect echoing later */
status = 0;
break;
}
status = IGNORE;
break;
case '\n':
case '\r':
status = 0;
break;
case '0': /* numeric result code */
augmdmtyp = n_HAYESNV; /* nonverbal result codes */
status = OKAY;
break;
case 'O': /* maybe English result code*/
status = GOT_O;
break;
case 'K':
if (status == GOT_O) {
augmdmtyp = n_HAYES;
status = OKAY;
break;
} /* else its default anyway */
default:
status = IGNORE;
break;
}
}
if (status == OKAY) break;
if (status == IGNORE) ttflui();
sleep(1); /* wait before retrying */
}
if (status != 0) break;
longjmp( sjbuf, F_minit ); /* modem-initialization failure */
/* cont'd... */
/* interdigit waits for tone dial */
/* ...dial, cont'd */
default: /* place modem into command mode */
ttolSlow(pmdminf->wake_str, pmdminf->wake_rate);
waitFor(pmdminf->wake_prompt);
break;
}
alarm(0); /* turn off alarm */
msleep(500); /* give things settling time */
alarm(10); /* alarm on dialing prompts */
/* Dial the number */
/* put modem into dialing mode */
ttolSlow(pmdminf->dmode_str, pmdminf->dial_rate);
if (pmdminf->dmode_prompt) { /* wait for prompt, if any expected */
waitFor(pmdminf->dmode_prompt);
msleep(300);
}
alarm(0); /* turn off alarm on dialing prompts */
alarm(waitct); /* time to allow for connecting */
ttflui(); /* clear out stuff from waking modem up */
sprintf(lbuf, pmdminf->dial_str, telnbr); /* form dialing string */
ttolSlow(lbuf,pmdminf->dial_rate); /* send dialing string */
if (augmdmtyp == n_RACAL) { /* acknowledge printout of dialing string */
sleep(3);
ttflui();
ttoc('\r');
}
/* cont'd... */
/* interdigit waits for tone dial */
/* ...dial, cont'd */
/* Check for connection */
/*
* I believe we also need to look for carrier in order to determine if a
* connection has been made. In fact, for many we may only want to look for
* the "failure" responses in order to short-circuit the timeout, and let
* carrier be the determination of whether a connection has been made. -- DS
*/
status = 0;
strcpy(lbuf,"No Connection"); /* default failure reason */
while (status == 0) {
switch (augmdmtyp) {
default:
for (n=0; n < LBUFL; n++) { /* accumulate response */
lbuf[n] = (ttinc(0) & 0177);
if ( lbuf[n] == '\r' || lbuf[n] == '\n' ) break;
}
lbuf[n] = '\0'; /* terminate response from modem */
if (n) { /* if one or more characters present */
switch (augmdmtyp) {
case n_CERMETEK:
if (didWeGet(lbuf,"\016A")) {
status = CONNECTED;
ttolSlow("\016U 1\r",200); /* make transparent*/
}
break;
case n_DF100: /* DF100 won't generate some of these */
case n_DF200:
if (didWeGet(lbuf,"Attached")) status = CONNECTED;
/*
* The DF100 will respond with "Attached" even if DTR
* and/or carrier are not present. Another reason to
* (also) wait for carrier?
*/
if (didWeGet(lbuf,"Busy")) status = FAILED;
if (didWeGet(lbuf,"Disconnected")) status = FAILED;
if (didWeGet(lbuf,"Error")) status = FAILED;
if (didWeGet(lbuf,"No answer")) status = FAILED;
if (didWeGet(lbuf,"No dial tone")) status = FAILED;
if (didWeGet(lbuf,"Speed:")) status = FAILED;
/*
* It appears that the "Speed:..." response comes after an
* "Attached" response, so this is never seen. HOWEVER,
* it would be very handy to detect this and temporarily
* reset the speed, since it's a nuiscance otherwise.
* If we wait for some more input from the modem, how do
* we know if it's from the remote host or the modem?
* Carrier reportedly doesn't get set until after the
* "Speed:..." response (if any) is sent. Another reason
* to (also) wait for carrier.
*/
break;
case n_GDC:
if (didWeGet(lbuf,"ON LINE")) status = CONNECTED;
if (didWeGet(lbuf,"NO CONNECT")) status = FAILED;
break;
case n_HAYES:
case n_USROBOT:
if (didWeGet(lbuf,"CONNECT")) status = CONNECTED;
if (didWeGet(lbuf,"NO CARRIER")) status = FAILED;
break;
case n_PENRIL:
if (didWeGet(lbuf,"OK")) status = CONNECTED;
if (didWeGet(lbuf,"BUSY")) status = FAILED;
if (didWeGet(lbuf,"NO RING")) status = FAILED;
break;
case n_RACAL:
if (didWeGet(lbuf,"ON LINE")) status = CONNECTED;
if (didWeGet(lbuf,"FAILED CALL")) status = FAILED;
break;
case n_VENTEL:
if (didWeGet(lbuf,"ONLINE!")) status = CONNECTED;
if (didWeGet(lbuf,"BUSY")) status = FAILED;
if (didWeGet(lbuf,"DEAD PHONE")) status = FAILED;
break;
}
}
break;
case n_DF03: /* because response lacks CR or NL */
c = ttinc(0) & 0177;
if ( c == 'A' ) status = CONNECTED;
if ( c == 'B' ) status = FAILED;
break;
case n_HAYESNV:
c = ttinc(0) & 0177;
if (mdmEcho) { /* sponge up dialing string */
mdmEcho = c!='\r'; /* until return is echoed */
break;
}
if (c == '1') status = CONNECTED;
if (c == '3') status = FAILED;
if (c == '5') status = CONNECTED;
break;
case n_UNKNOWN:
/** SHOULD WAIT FOR CARRIER OR TIMEOUT -- DS **/
break;
} /* switch (augmdmtyp) */
} /* while status == 0 */
alarm(0); /* turn off alarm on connecting */
if ( status != CONNECTED ) /* modem-detected failure */
longjmp( sjbuf, F_modem ); /* exit (with reason in lbuf) */
alarm(3); /* precaution in case of trouble */
ttpkt(speed,CONNECT); /* cancel dialing state ioctl */
reset (); /* reset alarms, etc. */
if ( ! quiet )
printf ( "Call completed.\07\r\n" );
return ( 0 ); /* return, and presumably connect */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -