/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
#include "uucp.h"
#include "pk.h"
extern int pksack();
static void pkdata();
static int pkcget();
static void xlatestate(struct pack *, int);
void xlatecntl(int, int);
/*
* Code added to allow translation of states from numbers to
* letters, to be done in such a way as to be meaningful to
* John Q. Public
*/
struct {
int state;
char *msg;
} st_trans[] = {
DEAD, "Dead!",
INITa, "INIT code a",
INITb, "INIT code b",
LIVE, "O.K.",
RREJ, "RREJ?",
PDEBUG, "PDEBUG?",
DRAINO, "Draino...",
WAITO, "Waiting",
DOWN, "Link down",
RCLOSE, "RCLOSE?",
BADFRAME, "Bad frame",
-1, "End of the line",
};
extern char _Protocol[]; /* Protocol string with (options) */
int Ntimeout = 0;
/*
* start initial synchronization.
*/
struct pack *
{
char **bp;
int i;
return(NULL);
}
/*
* We reset to OLDPACKSIZE to maintain compatibility
* with old limited implementations. Maybe we should
* just warn the administrator and continue?
*/
}
/*
* allocate input window
*/
break;
}
if (i == 0)
return(NULL);
/*
* start synchronization
*/
for (i = 0; i < PKMAXSTMSG; i++) {
break;
}
if (i >= PKMAXSTMSG)
return(NULL);
return(pk);
}
/*
* input framing and block checking.
* frame layout for most devices is:
*
* S|K|X|Y|C|Z| ... data ... |
*
* where S == initial synch byte
* K == encoded frame size (indexes pksizes[])
* X, Y == block check bytes
* C == control byte
* Z == XOR of header (K^X^Y^C)
* data == 0 or more data bytes
*
*/
/*
* Byte collection.
*/
void
{
char *p;
struct header *h;
unsigned short sum;
/*
* If we are known to be DOWN, or if we've received too many garbage
* packets or timeouts, give up without a fight.
*/
pkfail();
/*
* Attempt no more than GETRIES times to read a packet. The only valid
* exit from this loop is a return. Break forces a failure.
*/
/*
* Read header.
* First look for SYN. If more than 3 * packetsize characters
* go by w/o a SYN, request a retransmit.
*/
p = (caddr_t) h;
noise = 0;
for ( ; ; ) {
DEBUG(7,
"Alarm while looking for SYN -- request RXMIT\n%s", "");
goto retransmit;
}
if (*p == SYN)
break; /* got it */
else {
*p++ = *pp++;
/* Now look for remainder of header */
SUCCESS) {
DEBUG(7,
"Alarm while looking for header -- request RXMIT\n%s", "");
goto retransmit;
}
p = (caddr_t) h;
break; /* got entire header */
}
}
DEBUG(7,
"No SYN in %d characters -- request RXMIT\n", noise);
goto retransmit;
}
}
/* Validate the header */
Connodata++;
k = h->ksize;
/* bad header */
return;
}
if (k == 9) { /* control packet */
} else {
/* bad header */
}
return;
}
/* data packet */
return;
return;
}
/* Header checks out, go for data */
Ntimeout = 0;
return;
}
/*
* Transmission error or excessive noise. Send a RXMIT
* and try again.
*/
/*
Retries++;
*/
}
pkfail();
}
/*
* Translate pk->p_state into something printable.
*/
static void
int dbglvl;
{
int i;
return;
delimc = '&';
}
}
return;
}
static void
unsigned short sum;
char c;
char **bp;
{
int x;
int t;
char m;
goto drop;
}
goto slot;
}
drop:
return;
slot:
m = mask[x];
}
/*
* Start transmission on output device associated with pk.
* For asynch devices (t_line==1) framing is
* imposed. For devices with framing and crc
* in the driver (t_line==2) the transfer is
* passed on to the driver.
*/
void
int x;
char cntl;
{
char *p;
short checkword;
char hdchk;
*p++ = SYN;
if (x < 0) {
*p++ = hdchk = 9;
} else {
}
*p = checkword;
hdchk ^= *p++;
*p = checkword>>8;
hdchk ^= *p++;
*p = cntl;
hdchk ^= *p++;
*p = hdchk;
/*
* writes
*/
if (Debug >= 9)
if (x < 0) {
pkfail();
/* NOT REACHED */
}
} else {
pkfail();
/* NOT REACHED */
}
Connodata = 0;
}
}
/*
* get n characters from input
* b -> buffer for characters
* fn -> file descriptor
* n -> requested number of characters
* return:
* SUCCESS -> n chars successfully read
* FAIL -> o.w.
*/
static int
int n;
char *b;
int fn;
{
int ret;
#ifdef PKSPEEDUP
extern int linebaudrate;
#endif /* PKSPEEDUP */
if (n == 0)
return(SUCCESS);
Ntimeout++;
return(FAIL);
}
for (;;) {
(void) alarm(0);
if (ret == 0) {
/*
* Device has decided that the connection has no
* more data to send. Any further tries are futile...
* (The only other way to get a zero return value
* is to read a zero length message from a STREAM.
* However, uucp *never* sends zero length messages
* over any sort of channel...)
*/
pkfail();
/* NOT REACHED */
}
if (ret < 0) {
pkfail();
/* NOT REACHED */
}
if ((n -= ret) <= 0)
break;
#ifdef PKSPEEDUP
if (donap) {
/* wait for more chars to come in */
#else
sleep(1);
#endif
}
#endif /* PKSPEEDUP */
b += ret;
}
(void) alarm(0);
return(SUCCESS);
}
/*
* role == 0: receive
* role == 1: send
*/
void
int role;
int cntl;
{
"RR, ", "INITC, ", "INITB, ", "INITA, "};
char *ptr;
if (cntl&0300) {
/* data packet */
if (role)
else
} else {
/* control packet */
}
}