Highley Recommended, Inc.
Below is socket source code that uses the Annex spooling service to send relay codes that enable an embeded product to be rebooted from a remote location or to down load its battery backed up RAM.
#ifndef NULL #define NULL 0 #endif #define CNULL (char *)NULL #ifndef BUFSIZ #define BUFSIZ 512 #endif #if NDPTG > 0 #define MAX_SERIAL_PORTS 999 /* allow for DPTG ports */ #else #define MAX_SERIAL_PORTS 72 /* allow for ANNEX 3 */ #endif #define SERIAL 1 #define PARALLEL 2 #define AF_INET 2
/*
* Include Files
*/
#include <sys/types.h>
#include "port/port.h"
#include "../libannex/api_if.h"
#include <netinet/in.h>
#include <strings.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "rreboot.h"
/*
* External Definitions
*/
extern int errno;
extern char *getenv();
#ifndef BSDI
#ifndef FREEBSD
#ifndef SYS_V
#ifndef AIX
#ifndef LINUX
extern char *sprintf();
#endif
#endif
#endif
#endif
#endif
/*
* Global Data Declarations
*/
int debug = 0; /* debugging level */
int so; /* token for socket number */
char *prog; /* name of this program */
char *file_printing;
INT32 bytes; /* total bytes to send to printer */
/* Last message read from or sent to the Annex */
char buffer[BUFSIZ];
int buffer_count;
int block_send = 0; /* if set, send in 1-255 byte blocks */
int do_oob_ack = 0; /* if set, use old out-of-band ack */
char *sock_errors[] = {
#define SEND_FF 0
"file \"%s\" aborted while sending formfeed to Annex",
#define SEND_DATA 1
"file \"%s\" aborted while sending data to Annex",
#define SEND_FINAL_FF 2
"error sending final formfeed to Annex",
#define SEND_PORTSET 3
"error during Annex port select",
#define ACK_PORTSET 4
"error during wait for ACK after port select",
#define ACK_FINAL 5
"error during wait for final ACK"
};
/*
* Macro Definitions
*/
#ifndef BADSIG
#ifndef SIG_ERR
#define BADSIG (int (*)())-1
#else
#define BADSIG SIG_ERR
#endif
#endif
#define ARGVAL (*++(*argv) || (--argc && *++argv))
#define ARGSTR(s) *argv += strlen((s) = *argv);
#define SEND(buf,len,msg) \
if (api_send(so,(buf),(len),API_NOFLAGS,app_nam,TRUE) != (len)) { \
fatal(CNULL, sock_errors[(msg)], file_printing); \
}
#define SENDOOB(buf,len,msg) \
if (api_send(so, (buf), (len), API_OOB, app_nam, TRUE) != (len)) { \
fatal(CNULL, sock_errors[(msg)], file_printing); \
}
#define RECV(buf,len,msg,ret) \
if((ret = api_recv(so,(buf),(len),API_NOFLAGS,TRUE,app_nam)) < 0) { \
if (debug > 1) \
printf("Error: api_recv returned %d.\n",ret); \
fatal(CNULL, sock_errors[(msg)], file_printing); \
} else if (debug > 1) \
printf("Received %d bytes. %02X %02X ...\n",ret,(buf)[0],(buf)[1]);
/*
* Annex LPD protocol definitions
*/
#define ANNEX_SPOOL_CMD '\011'
#define ACK '\0'
#define NACK '\001'
#define FRAME '\002'
#define OFF 0 /* timer off */
#define ACK_WAIT 10 /* seconds to wait for initial ACK */
#define ACK_TIMEOUT 30 /* seconds to timeout final ACK */
/*
* usage: display usage info and exit
*/
usage()
{
fprintf(stderr,
"Usage: %s -r#; relay_number1_thru_26\n",prog);
exit(1);
}
/*
* fatal: print error message and give up
*/
void
fatal(perr,str,arg1)
char *perr,*str,*arg1;
{
fprintf(stderr, "%s: ", prog);
if (str != NULL)
fprintf(stderr,str,arg1);
if (perr != NULL) {
if (str != NULL)
fprintf(stderr, ": ");
perror(perr);
} else
fprintf(stderr, "\n");
exit(1);
}
/*
* gotpipe: catch SIGPIPE and die
*/
void
gotpipe(dummy)
int dummy;
{
fatal(CNULL,
file_printing == NULL
? "Annex connection was lost unexpectedly"
: "Annex connection was lost during attempt to spool \"%s\"" ,
file_printing);
}
main(argc,argv)
int argc;
char *argv[];
{
char *printer = NULL, *annex = "annex", *ff = NULL, *port = NULL;
int pport = 0;
int gotl = 0;
int gotp = 0;
int type = SERIAL; /* default, if nothing specified */
int line = 64;
int relay= 0;
int MAX_RELAY_PORTS = 26;
char opt;
/* FILE *userfile; */
FILE *file;
int i;
int energize;
int de_energize;
prog = (prog = (char *)rindex(argv[0],'/')) ? ++prog : *argv;
/*
* Crack arguments
*/
if (debug > 0 )
printf("Entering argument switch, %d\n",argc);
if (argc != 2)
usage();
if (**(++argv) == '-') /* found a flag, deal with it */
while (**argv && (opt = *++*argv) != '\0')
switch (opt) {
case 'r':
if (!ARGVAL)
usage();
ARGSTR(port);
relay = atoi(port);
if (relay < 1 || relay > MAX_RELAY_PORTS)
fatal(CNULL,
"Relay must be in range (1-26), not %s",
port);
energize = relay * 2 - 1;
de_energize = relay * 2 - 2;
break;
default: /* unknown argument */
usage();
break;
}
if (debug > 0)
printf("Relay port %s\n",port);
make_connection(annex);
set_annex_line(line, type);
if (debug > 1)
printf("Connection set-up is complete.\n");
if (debug > 1)
printf("Sending energize to relay %d.\n",energize);
buffer[0] = (char) (relay * 2 - 1);
buffer[1] = NULL;
send_block(buffer, strlen(buffer), SEND_DATA);
system("sleep 1");
if (debug > 1)
printf("Sending denergize to relay %d.\n",de_energize);
buffer[0] = (char) (relay * 2 - 2);
send_block(buffer, strlen(buffer), SEND_DATA);
/*
* End-of-job handshake; wait for final ACK
*/
if (ack_ack())
fatal(CNULL,"Annex didn't acknowledge final data",CNULL);
exit (0);
}
/*
* make_connection: establish TCP connection with designated Annex
*/
make_connection (hostname)
char *hostname;
{
struct hostent *host;
struct servent *serv;
struct sockaddr_in sname;
static char app_nam[]="rreboot:make_connection";
if (signal(SIGPIPE, gotpipe) == BADSIG)
fatal("signal",CNULL,CNULL);
bzero ((char *)&sname, sizeof(sname));
if (debug > 1)
printf("Attempting to resolve host name \"%s\".\n",hostname);
sname.sin_addr.s_addr = inet_addr(hostname);
if (sname.sin_addr.s_addr != -1) {
sname.sin_family = AF_INET;
} else {
host = gethostbyname(hostname);
if (host) {
sname.sin_family = host->h_addrtype;
bcopy(host->h_addr,
(caddr_t)&sname.sin_addr,
host->h_length);
} else
fatal(CNULL,
"can't find host address for Annex \"%s\"",
hostname);
}
#ifdef DEBUG
sname.sin_port = htons(5555);
#else
if (debug > 1)
printf("Attempting to resolve service \"printer/tcp\".\n");
serv = getservbyname("printer","tcp");
if (serv == NULL)
fatal(CNULL,"can't get service to printer",CNULL);
sname.sin_port = serv->s_port;
if (debug > 1)
printf("\t-> resolved to port %d.\n",
ntohs(sname.sin_port));
#endif
#ifdef EXOS
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = 0;
#endif
if (debug > 1)
printf("Opening connection to API layer.\n");
if((so = api_open(IPPROTO_TCP, &sname, app_nam, TRUE)) < 0)
exit(1);
#ifdef TLI /* only bind for TLI, Sockets don't need bind*/
if (debug > 1)
printf("Binding API address.\n");
switch (api_bind(so, (struct t_bind **)0, (struct sockaddr_in *)0, app_nam, TRUE)) {
case 0:
break;
case 1:
exit(-1);
case 2:
exit(1);
default:
break;
}
#endif
if (debug > 1)
printf("Connecting to host through API.\n");
switch (api_connect(so, &sname, IPPROTO_TCP, app_nam, TRUE)) {
case 0:
break;
case 1:
exit(-1);
case 2:
exit(1);
default:
break;
}
}
/*
* Tell the Annex which port to print on by creating a escape sequence
* to select which port to print on:
*
* CMD TYPE ; UNIT ; BYTES \n
*
* CMD is \011 is for the new-style lpd, where you select, get an ack,
* and then shovel data.
*
* serial parallel
* TYPE is the port type: 1 2
* UNIT is the unit number: [1-MAX_SERIAL_PORTS] 1
* (TYPE & UNIT are ASCII strings)
*/
set_annex_line(line, type)
int line;
int type;
{
static char app_nam[]="rreboot:set_annex_line";
(void)sprintf(buffer,"%c%d;%d;%ld\n",
ANNEX_SPOOL_CMD, /* command byte */
type, /* parallel or serial */
line, /* unit */
bytes);
if (debug > 1)
printf("Sending port designator --\n\t%s",buffer);
SEND(buffer, strlen(buffer), SEND_PORTSET);
/* check if Annex supports ACKing */
if (ack_wait(ACK_PORTSET))
fatal(CNULL, "Annex can't access requested printer",CNULL);
/* Check if count/buffers needed and supported */
if (buffer_count > 1) {
if (buffer[1] == 1) {
block_send = 1;
if (debug > 0)
printf("Block send mode.\n");
} else if (debug > 0)
printf("Stream mode.\n");
} else {
do_oob_ack = 1; /* backwards compatibility */
if (debug > 0)
printf("Backward compatibility mode.\n");
}
}
/*
* Send a block of data to the Annex.
*
* In block_send mode, this is a pair of bytes that encode an integer
* in big-endian format in the range 0x0001 through 0xFFFF, followed by
* 1 to 65536 bytes. A count of 0x0000 is reserved for end-of-all-files
* indication.
*
* When not in block_send mode, data are just streamed over.
*/
send_block(ptr,len,msg)
char *ptr;
int len,msg;
{
char blockbuf[2];
unsigned int piece;
static char app_nam[]="rreboot:send_block";
if (block_send) {
while (len > 0) {
piece = len;
if (piece > 65535)
piece = 65535;
blockbuf[0] = piece / 256;
blockbuf[1] = piece % 256;
SEND(blockbuf,2,msg);
SEND(ptr,piece,msg);
len -= piece;
ptr += piece;
}
}
else
SEND(ptr,len,msg);
}
/************** Annex LPD protocol handshaking routines **************/
/*
* ack_alrm: catch SIGALRM and longjmp back
*/
void
ack_alrm(dummy)
int dummy;
{
static char app_nam[]="rreboot:ack_alrm";
#ifdef SYS_V
signal(SIGALRM,ack_alrm);
#endif
(void)alarm(ACK_TIMEOUT);
if (debug > 0)
printf("ACK timeout -- going to re-try.\n");
SEND("",1,ACK_FINAL); /* detect lost connections! */
}
/*
* Wait for an inline acknowledgement from the Annex
*
* return 0 if we get the ACK, 1 o/w.
*/
int
ack_wait(msg)
int msg;
{
static char app_nam[]="rreboot:ack_wait";
if (debug > 1)
printf("Waiting for acknowledge.\n");
RECV(buffer,BUFSIZ,msg,buffer_count);
return (buffer_count <= 0 || buffer[0] != ACK);
}
/*
* Send an OOB ACK and wait for an inline ACK back.
* Use timeout to prevent waiting forever.
*
* return 0 if exit handshake went ok, 1 o/w.
*
* If in block_send mode, then send the magic end-of-all-blocks message
* and wait for ACK (no OOB). If old (pre R6.2) Annex detected in
* set-up, then send an OOB message to terminate the data. This part is
* a little unclean.
*/
ack_ack()
{
int gotack;
static char app_nam[]="rreboot:ack_ack";
if (block_send) {
char endblock[2];
if (debug > 0)
printf("Sending End-Of-Blocks message.\n");
/* send end-of-all-blocks message */
endblock[0] = endblock[1] = '\0';
SEND(endblock,2,ACK_FINAL);
}
else if (do_oob_ack) {
#ifdef MSG_OOB
if (debug > 0)
printf("Sending OOB message.\n");
/* try to get the OOB past the end of the data for SysV */
sleep(7);
/* send OOB ACK to indicate EOF */
SENDOOB("",1,ACK_FINAL);
/* clear for recv's on broken 4.2 systems */
SEND("",1,ACK_FINAL);
#else
if (debug > 0)
printf("No OOB possible -- just closing.\n");
/* if no OOB available, then just trust that it got there. */
return 0;
#endif
}
if (debug > 0)
printf("Waiting for final ACK.\n");
if (signal(SIGALRM, ack_alrm) == BADSIG)
fatal("signal",CNULL,CNULL);
(void)alarm(ACK_TIMEOUT);
gotack = ack_wait(ACK_FINAL);
(void)alarm(OFF);
return gotack;
}
Below is socket source code that uses the Annex spooling service to send commands to an embeded product to reload its NVRAM and then it sends a file.
/*
* Include Files
*/
#include <sys/types.h>
#include "port/port.h"
#include "../libannex/api_if.h"
#include <netinet/in.h>
#include <strings.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "rreboot.h"
/*
* External Definitions
*/
extern int errno;
extern char *getenv();
#ifndef BSDI
#ifndef FREEBSD
#ifndef SYS_V
#ifndef AIX
#ifndef LINUX
extern char *sprintf();
#endif
#endif
#endif
#endif
#endif
/*
* Global Data Declarations
*/
int debug = 0; /* debugging level */
int so; /* token for socket number */
char *prog; /* name of this program */
char *file_printing;
INT32 bytes; /* total bytes to send to printer */
/* Last message read from or sent to the Annex */
char buffer[BUFSIZ];
int buffer_count;
int block_send = 0; /* if set, send in 1-255 byte blocks */
int do_oob_ack = 0; /* if set, use old out-of-band ack */
char *sock_errors[] = {
#define SEND_FF 0
"file \"%s\" aborted while sending formfeed to Annex",
#define SEND_DATA 1
"file \"%s\" aborted while sending data to Annex",
#define SEND_FINAL_FF 2
"error sending final formfeed to Annex",
#define SEND_PORTSET 3
"error during Annex port select",
#define ACK_PORTSET 4
"error during wait for ACK after port select",
#define ACK_FINAL 5
"error during wait for final ACK"
};
/*
* Macro Definitions
*/
#ifndef BADSIG
#ifndef SIG_ERR
#define BADSIG (int (*)())-1
#else
#define BADSIG SIG_ERR
#endif
#endif
#define ARGVAL (*++(*argv) || (--argc && *++argv))
#define ARGSTR(s) *argv += strlen((s) = *argv);
#define SEND(buf,len,msg) \
if (api_send(so,(buf),(len),API_NOFLAGS,app_nam,TRUE) != (len)) { \
fatal(CNULL, sock_errors[(msg)], file_printing); \
}
#define SENDOOB(buf,len,msg) \
if (api_send(so, (buf), (len), API_OOB, app_nam, TRUE) != (len)) { \
fatal(CNULL, sock_errors[(msg)], file_printing); \
}
#define RECV(buf,len,msg,ret) \
if((ret = api_recv(so,(buf),(len),API_NOFLAGS,TRUE,app_nam)) < 0) { \
if (debug > 1) \
printf("Error: api_recv returned %d.\n",ret); \
fatal(CNULL, sock_errors[(msg)], file_printing); \
} else if (debug > 1) \
printf("Received %d bytes. %02X %02X ...\n",ret,(buf)[0],(buf)[1]);
/*
* Annex LPD protocol definitions
*/
#define ANNEX_SPOOL_CMD '\011'
#define ACK '\0'
#define NACK '\001'
#define FRAME '\002'
#define OFF 0 /* timer off */
#define ACK_WAIT 10 /* seconds to wait for initial ACK */
#define ACK_TIMEOUT 30 /* seconds to timeout final ACK */
/*
* usage: display usage info and exit
*/
usage()
{
fprintf(stderr, "Usage: %s file\n", prog);
exit(1);
}
/*
* fatal: print error message and give up
*/
void
fatal(perr,str,arg1)
char *perr,*str,*arg1;
{
fprintf(stderr, "%s: ", prog);
if (str != NULL)
fprintf(stderr,str,arg1);
if (perr != NULL) {
if (str != NULL)
fprintf(stderr, ": ");
perror(perr);
} else
fprintf(stderr, "\n");
exit(1);
}
/*
* gotpipe: catch SIGPIPE and die
*/
void
gotpipe(dummy)
int dummy;
{
fatal(CNULL,
file_printing == NULL
? "Annex connection was lost unexpectedly"
: "Annex connection was lost during attempt to spool \"%s\"" ,
file_printing);
}
main(argc,argv)
int argc;
char *argv[];
{
char *printer = NULL, *annex = "annex", *ff = NULL, *port = NULL;
int pport = 0;
int gotl = 0;
int gotp = 0;
int type = SERIAL; /* default, if nothing specified */
int line = 63;
char opt;
FILE *userfile;
int i;
char *cmd = "lo 0\015";
prog = (prog = (char *)rindex(argv[0],'/')) ? ++prog : *argv;
/*
* Crack arguments
*/
if (argc != 2)
usage();
/*
* Note that we might have problems here if the file extends itself
* after we've counted up the bytes and the socket to the Annex doesn't
* linger and the Annex requests non-blocked data -- the Annex will ACK
* this program N bytes early, and it might exit before its time.
* This is just too bad.
*/
bytes = 0L;
userfile = fopen(argv[1],"r");
if (userfile == NULL) {
perror(argv[1]);
argv[1] = NULL;
}
else if (fseek(userfile,0L,2) < 0) {
/* Darn. Looks like we can't count the number of bytes. */
perror(argv[1]);
bytes = 0;
fclose(userfile);
}
else {
bytes += ftell(userfile);
fclose(userfile);
}
if (debug > 0)
printf("Connecting to Annex %s port %d\n",annex,line);
make_connection(annex);
set_annex_line(line, type);
if (debug > 1)
printf("Connection set-up is complete. Handling %d files.\n",argc);
/* Tell CTU to do a load of file starting at address 0, BBRAM */
send_block(cmd, strlen(cmd), SEND_DATA);
system("sleep 1");
userfile = fopen(argv[1], "r");
if (userfile == NULL)
perror(argv[1]);
else {
(void)print_file(argv[1],userfile);
(void)fclose(userfile);
}
exit (0);
}
/*
* print_file: spool file over TCP connection
*/
print_file(name,file)
char *name;
FILE *file;
{
file_printing = name;
if (debug > 0)
printf("Printing file \"%s\".\n",name);
for (;;) {
buffer_count = fread(buffer, sizeof(*buffer), BUFSIZ, file);
#ifdef DEBUG
fprintf(stderr,"object size=%d, buffer size=%d, length=%d\nbuffer=>>s<<n",
sizeof(*buffer),BUFSIZ,len,len,buffer);
#endif
/* fread should never return <0, but... */
if (buffer_count <= 0)
break;
send_block(buffer, buffer_count, SEND_DATA);
system("sleep 1");
}
return(0);
}
/*
* make_connection: establish TCP connection with designated Annex
*/
make_connection (hostname)
char *hostname;
{
struct hostent *host;
struct servent *serv;
struct sockaddr_in sname;
static char app_nam[]="aprint:make_connection";
if (signal(SIGPIPE, gotpipe) == BADSIG)
fatal("signal",CNULL,CNULL);
bzero ((char *)&sname, sizeof(sname));
if (debug > 1)
printf("Attempting to resolve host name \"%s\".\n",hostname);
sname.sin_addr.s_addr = inet_addr(hostname);
if (sname.sin_addr.s_addr != -1) {
sname.sin_family = AF_INET;
} else {
host = gethostbyname(hostname);
if (host) {
sname.sin_family = host->h_addrtype;
bcopy(host->h_addr,
(caddr_t)&sname.sin_addr,
host->h_length);
} else
fatal(CNULL,
"can't find host address for Annex \"%s\"",
hostname);
}
#ifdef DEBUG
sname.sin_port = htons(5555);
#else
if (debug > 1)
printf("Attempting to resolve service \"printer/tcp\".\n");
serv = getservbyname("printer","tcp");
if (serv == NULL)
fatal(CNULL,"can't get service to printer",CNULL);
sname.sin_port = serv->s_port;
if (debug > 1)
printf("\t-> resolved to port %d.\n",
ntohs(sname.sin_port));
#endif
#ifdef EXOS
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = 0;
#endif
if (debug > 1)
printf("Opening connection to API layer.\n");
if((so = api_open(IPPROTO_TCP, &sname, app_nam, TRUE)) < 0)
exit(1);
#ifdef TLI /* only bind for TLI, Sockets don't need bind*/
if (debug > 1)
printf("Binding API address.\n");
switch (api_bind(so, (struct t_bind **)0, (struct sockaddr_in *)0, app_nam, TRUE)) {
case 0:
break;
case 1:
exit(-1);
case 2:
exit(1);
default:
break;
}
#endif
if (debug > 1)
printf("Connecting to host through API.\n");
switch (api_connect(so, &sname, IPPROTO_TCP, app_nam, TRUE)) {
case 0:
break;
case 1:
exit(-1);
case 2:
exit(1);
default:
break;
}
}
/*
* Tell the Annex which port to print on by creating a escape sequence
* to select which port to print on:
*
* CMD TYPE ; UNIT ; BYTES \n
*
* CMD is \011 is for the new-style lpd, where you select, get an ack,
* and then shovel data.
*
* serial parallel
* TYPE is the port type: 1 2
* UNIT is the unit number: [1-MAX_SERIAL_PORTS] 1
* (TYPE & UNIT are ASCII strings)
*/
set_annex_line(line, type)
int line;
int type;
{
static char app_nam[]="aprint:set_annex_line";
(void)sprintf(buffer,"%c%d;%d;%ld\n",
ANNEX_SPOOL_CMD, /* command byte */
type, /* parallel or serial */
line, /* unit */
bytes);
if (debug > 1)
printf("Sending port designator --\n\t%s",buffer);
SEND(buffer, strlen(buffer), SEND_PORTSET);
/* check if Annex supports ACKing */
if (ack_wait(ACK_PORTSET))
fatal(CNULL, "Annex can't access requested printer",CNULL);
/* Check if count/buffers needed and supported */
if (buffer_count > 1) {
if (buffer[1] == 1) {
block_send = 1;
if (debug > 0)
printf("Block send mode.\n");
} else if (debug > 0)
printf("Stream mode.\n");
} else {
do_oob_ack = 1; /* backwards compatibility */
if (debug > 0)
printf("Backward compatibility mode.\n");
}
}
/*
* Send a block of data to the Annex.
*
* In block_send mode, this is a pair of bytes that encode an integer
* in big-endian format in the range 0x0001 through 0xFFFF, followed by
* 1 to 65536 bytes. A count of 0x0000 is reserved for end-of-all-files
* indication.
*
* When not in block_send mode, data are just streamed over.
*/
send_block(ptr,len,msg)
char *ptr;
int len,msg;
{
char blockbuf[2];
unsigned int piece;
static char app_nam[]="aprint:send_block";
if (block_send) {
while (len > 0) {
piece = len;
if (piece > 65535)
piece = 65535;
blockbuf[0] = piece / 256;
blockbuf[1] = piece % 256;
SEND(blockbuf,2,msg);
SEND(ptr,piece,msg);
len -= piece;
ptr += piece;
}
}
else
SEND(ptr,len,msg);
}
/************** Annex LPD protocol handshaking routines **************/
/*
* ack_alrm: catch SIGALRM and longjmp back
*/
void
ack_alrm(dummy)
int dummy;
{
static char app_nam[]="aprint:ack_alrm";
#ifdef SYS_V
signal(SIGALRM,ack_alrm);
#endif
(void)alarm(ACK_TIMEOUT);
if (debug > 0)
printf("ACK timeout -- going to re-try.\n");
SEND("",1,ACK_FINAL); /* detect lost connections! */
}
/*
* Wait for an inline acknowledgement from the Annex
*
* return 0 if we get the ACK, 1 o/w.
*/
int
ack_wait(msg)
int msg;
{
static char app_nam[]="aprint:ack_wait";
if (debug > 1)
printf("Waiting for acknowledge.\n");
RECV(buffer,BUFSIZ,msg,buffer_count);
return (buffer_count <= 0 || buffer[0] != ACK);
}
/*
* Send an OOB ACK and wait for an inline ACK back.
* Use timeout to prevent waiting forever.
*
* return 0 if exit handshake went ok, 1 o/w.
*
* If in block_send mode, then send the magic end-of-all-blocks message
* and wait for ACK (no OOB). If old (pre R6.2) Annex detected in
* set-up, then send an OOB message to terminate the data. This part is
* a little unclean.
*/
ack_ack()
{
int gotack;
static char app_nam[]="aprint:ack_ack";
if (block_send) {
char endblock[2];
if (debug > 0)
printf("Sending End-Of-Blocks message.\n");
/* send end-of-all-blocks message */
endblock[0] = endblock[1] = '\0';
SEND(endblock,2,ACK_FINAL);
}
else if (do_oob_ack) {
#ifdef MSG_OOB
if (debug > 0)
printf("Sending OOB message.\n");
/* try to get the OOB past the end of the data for SysV */
sleep(7);
/* send OOB ACK to indicate EOF */
SENDOOB("",1,ACK_FINAL);
/* clear for recv's on broken 4.2 systems */
SEND("",1,ACK_FINAL);
#else
if (debug > 0)
printf("No OOB possible -- just closing.\n");
/* if no OOB available, then just trust that it got there. */
return 0;
#endif
}
if (debug > 0)
printf("Waiting for final ACK.\n");
if (signal(SIGALRM, ack_alrm) == BADSIG)
fatal("signal",CNULL,CNULL);
(void)alarm(ACK_TIMEOUT);
gotack = ack_wait(ACK_FINAL);
(void)alarm(OFF);
return gotack;
}