📄 laps.c
字号:
#ifndef lintstatic char *sccsid = "@(#)laps.c 4.1 ULTRIX 7/2/90";#endif/* * laps.c Local Area Print Service * ***************************************************************************** * * * COPYRIGHT (c) 1986, 1987, 1988 * * By DIGITAL EQUIPMENT CORPORATION, Maynard, Mass. * * * * This software is furnished under a license and may be used and copied * * only in accordance with the terms of such license and with the * * inclusion of the above copyright notice. This software or any other * * copies thereof may not be provided or otherwise made available to any * * other person. No title to and ownership of the software is hereby * * transferred. * * * * The information in this software is subject to change without notice * * and should not be construed as a commitment by Digital Equipment * * Corporation. * * * * Digital assumes no responsibility for the use or reliability of its * * software on equipment which is not supplied by Digital. * * * ***************************************************************************** * EDIT HISTORY * -------------- * * V2.000 27-Jan-1989 APK Fix unalinged data access problem for MIPS * (1) By adding ifdef MIPS -INSERT16 macro, and * (2) temporary coping data before referencing it. * * V1.000 5-May-1989 APK Change user infor from "host::username" to * "username@host" -- QAR#13 * *---------------------Begin V2.0--------------------------------------- * V0.012 2-Nov-1988 APK Sleep when write blocks to avoid CPU hog! * V0.011 18-Jul-1988 APK Implement Resource Reporting * V0.010 15-Jul-1988 APK Implement RETURN_STATUS * Also loop around while waiting for EOS and EOJ sts * V0.009 12-Jul-1988 APK write and close printer should be executed * even when laps_abort is true * V0.008 8-Jul-1988 APK proc_status should not proceed if laps_abort is * true and connect is not accepted since server * brakes the link resulting in read to hang. * V0.007 28-Jun-1988 APK Implement Out_Of_Band message for interrup * V0.006 3-Jun-1988 APK close stdout if LAPS_TRACE is not defined * V0.005 31-May-1988 APK Update write_printer so that it write only * if it wouldnot block. * V0.004 24-May-1988 APK Update the LAPS_PROTOCOL version number * V0.003 21-Apr-1988 APK Update total_page_count in decode_status block * V0.002 20-Apr-1988 APK Donot read_msg when laps_abort is true * V0.001 16-Mar-1988 APK Updated open_printer to include client::username * and job_id in printer connection block * */#include <stdio.h> /* standard i/o library */#include <errno.h> /* error numbers */#include "laps.h" /* laps protocol definitions */#include "lpsmsg.h" /* lps message definitions */#include "descrip.h" /* VMS descriptor definitions *//* * VMS Message file masks needed for Return_Status implementation */#define MESSAGE_MASK 0xfff8#define FACILITY_MASK 0xfff0000#define CONTROL_MASK 0xf0000000#define MESSAGE_OFFSET 3#define FACILITY_OFFSET 16#define CONTROL_OFFSET 26#define RTNSTAT_FACILITY (LPS$_FACILITY << FACILITY_OFFSET)#define RTNSTAT_MESSAGE (LPS$$CLI__RTNSTAT__BASE << MESSAGE_OFFSET)#define RETURNSTATUS_START (RTNSTAT_FACILITY + RTNSTAT_MESSAGE + 0x8000)#define PUT8(msgp, data) (*(FIELD8 *)(msgp)++ = ((FIELD8)data))#ifdef vax#define PUT16(msgp, data) (*(FIELD16 *)(msgp)++ = ((FIELD16)data))#define INSERT8(msgp, data) (*(FIELD8 *)(msgp) = ((FIELD8)data))#define INSERT16(msgp, data) (*(FIELD16 *)(msgp) = ((FIELD16)data))#endif vax#ifdef mips#define PUT16(p, v) { FIELD16 tmp = (v); bcopy(&tmp, (p), 2); (p) += 2; } #define INSERT8(p, v) { ((FIELD8 *)(p))[0] = (v); } #define INSERT16(p, v) { register FIELD8 *q = (FIELD8 *) (p); \ if ((int)q & 1) { \ register int w = (v); \ *q++ = w & 0xFF; w >>= 8; \ *q = w & 0xFF; \ } else { \ *(FIELD16 *)q = (v); \ } \ }#endif mips#ifndef ECONNREFUSED#define ECONNREFUSED 61#define EMSGSIZE 40#define ENOPROTOOPT 42#endif /* * buffers for sending/receiving laps messages */FIELD8 xmit_buf[LAPS_BUF_SIZE]; /* transmit buffer */FIELD8 *xmit_ptr; /* current position in transmit buffer */int xmit_len; /* current amount of data in transmit buffer */ FIELD8 rcv_buf[LAPS_BUF_SIZE]; /* receive buffer */FIELD8 *rcv_ptr; /* current position in receive buffer */int rcv_len; /* current amount of data in receive buffer */FIELD8 rcv_msg_type; /* block type received */FIELD8 rcv_blk_type; /* block type received */FIELD16 rcv_blk_len; /* length of block received *//* * buffers for sending laps interrupt message */FIELD8 intr_buf[LAPS_BUF_SIZE]; /* interrupt buffer */FIELD8 *intr_ptr; /* current position in interrupt buffer */int intr_len; /* current amount of data in interrupt buffer *//* * Resource reporting flags/count */int accepted_flag; /* hold onto acceptance */int rcount_flag; /* have we already receive resource count block? */FIELD8 rrecv; /* current count of resource recvd */FIELD8 rpromised; /* number of resources we should get *//* * status variables */int sock; /* socket to server */int trace_flag; /* trace messages to stdout */#define TRACE_MSGS (1 << 0) /* flag to trace messages (at all) */#define TRACE_DATA (1 << 1) /* flag to trace data contents */#define TRACE_ASCII (1 << 2) /* flag to trace data in ascii */int laps_abort; /* abort current job */int (*cond_handler)(); /* pointer to condition rec handler */FIELD32 cur_page_cnt; /* current page count */FIELD16 cur_job_state; /* current job state */FIELD16 cur_con_state; /* current connection state */FIELD16 con_accepted; /* boolean for connection accpeted */struct pro_ver station_pro_ver; /* print station protocol version */FIELD32 station_job_id; /* job id at print station */struct pro_ver lo_ver = { /* lowest version supported */ PRO_VER_MAJOR_LO, PRO_VER_MINOR_LO, PRO_VER_EDIT_LO, PRO_VER_USER_LO };struct pro_ver hi_ver = { /* highest version supported */ PRO_VER_MAJOR_HI, PRO_VER_MINOR_HI, PRO_VER_EDIT_HI, PRO_VER_USER_HI };/* * l a p s _ i n i t * * This routine called to initialize laps variables. * It also closes stdout, if LAPS_TRACE isn't defined * * Returns: NULL if success * EOF if fatal error * * Inputs: None */laps_init(){ char *cp, *getenv(); /* * init trace_flag to environment variable "LAPS_TRACE" */ if ((cp = getenv("LAPS_TRACE")) != NULL) trace_flag = atoi(cp); else close (1); /* * reset transmit and receive buffer variables */ xmit_len = 0; xmit_ptr = xmit_buf; rcv_len = 0; rcv_ptr = rcv_buf; return(NULL);}/* * o p e n _ p r i n t e r * * This routine is called to create a connection to, and start a * stream on a LAPS printer. * * Returns: socket number for printer * -1 if fatal error * * Inputs: * server = Node name of server * user = Name of user * userl = Length of user name * client = Node name of client * clientl = Length of client node name * job_id = Job ID in Daemon database * printer = number of printer on server * */open_printer(server, user, userl, client, clientl, job_id, printer)char *server;char *user;int userl;char *client;int clientl;int job_id;int printer;{ int status; FIELD8 *ptr; FIELD8 tmp_buf[100]; /* buffer for building connect data */ int len; /* * init internal variables */ if (laps_init() != NULL) return(-1); /* * init resource reporting variables */ accepted_flag = rcount_flag = rrecv = rpromised = 0; /* * connect to the specified printer */ if ((sock = conn_ps(server)) < 0) return(-1); /* * format the connect data */ bzero(tmp_buf, sizeof(tmp_buf)); ptr = tmp_buf; *((int *)ptr) = job_id; ptr = &tmp_buf[4]; len = (clientl + strlen ("@") + userl); *((short *)ptr) = len; ptr = &tmp_buf[6]; strncpy(ptr, user, userl); strncat(ptr, "@", strlen("@")); strncat(ptr, client, clientl); /* * send a connect message, hi and low version numbers */ init_msg_hdr(LMT_CONNECT); insert_block(LBT_CON_DATA, tmp_buf, len + 4 + 2); insert_block(LBT_CON_HI_VER, &hi_ver, PRO_VER_LEN); insert_block(LBT_CON_LO_VER, &lo_ver, PRO_VER_LEN); if (flush_xmit() != NULL) { disconn_ps(sock); return(-1); } /* * read the received status message */ cur_con_state = 0; con_accepted = 0; while (cur_con_state == 0) { if (proc_status() != NULL) { disconn_ps(sock); return(-1); } switch (cur_con_state) { case 0: /* * If accepted and received promised resources */ if (accepted_flag && (rrecv == rpromised)) { con_accepted = 1; break; } /* * else assume PENDING */ case LBV_STA_C_PENDING: cur_con_state = 0; continue; break; case LBV_STA_C_COMPLETED: case LBV_STA_C_ACCEPTED: /* * If already received accepted message-ERROR */ if (accepted_flag) { disconn_ps(sock); errno = ECONNREFUSED; return(-1); } else { accepted_flag = 1; if (rrecv == rpromised) con_accepted = 1; else /* assume pending */ { cur_con_state = 0; continue; } } break; case LBV_STA_C_JOB_ABORT: case LBV_STA_C_DISABLED: default: disconn_ps(sock); errno = ECONNREFUSED; return(-1); break; } } /* * output null resource tag indicating end of resource reporting */ report_resource(ptr, 0); return(sock);}/* * w r i t e _ p r i n t e r * * This routine is called to write data to the printer. * * Beware: Write is done using non-blocking I/O * * Returns: 0 on success * -1 on error * * Inputs: * buf = Pointer to data * len = Length of data to be written * (a length of 0 indicates end-of-stream) * type = Type of data (0 takes default of PostScript) * */write_printer(buf, len, type)FIELD8 *buf;int len;FIELD8 type;{ int status, proceed, on = 1, off = 0; /* * loop reading status messages - until socket is ready for write */ proceed = 0; do { /* * process any status records which may have arrived */ if (proc_asynch() != NULL) { disconn_ps(sock); return(-1); } /* * write in nonblocking mode and check if EWOULDBLOCK */ nonblock_io (sock, on); errno = 0; status = send_data_msg(buf, len, len ? 0 : 1, LBV_DAT_PRINT_DATA, type); nonblock_io (sock, off); switch (status) { case NULL : proceed = 0; break; default : if (errno == EWOULDBLOCK) { sleep (2); proceed = 1; } else { disconn_ps(sock); return(-1); } } } while (proceed == 1); /* * if the length was 0, then this is a "end-of-stream" request. * process the expected status. */ if (len == 0) { cur_con_state = 0; while (cur_con_state == 0) { if (proc_status() != NULL) { fprintf (stderr, "Olpscomm: error from process_status: eos sent\n"); disconn_ps(sock); return(-1); } switch (cur_con_state) { case 0: continue; break; case LBV_STA_C_COMPLETED: break; case LBV_STA_C_JOB_ABORT: /* * if abort is reported then this is okay * otherwise, it's an error */ if (laps_abort) break; default: errno = EIO; disconn_ps(sock); return(-1); } } } return(NULL);}/* * c l o s e _ p r i n t e r * * This routine is called to terminate access to a printer. * * Returns: 0 on success * -1 on failure * * Inputs: * abort = 0 if not aborting print job * = not 0 if aborting */close_printer(abort)int abort;{ FIELD8 reason; /* * process any status records which may have arrived */ if (proc_asynch() != NULL) { disconn_ps(sock); return(-1); } /* * set close reason */ if (abort) reason = LBV_EOJ_ABNORMAL; else reason = LBV_EOJ_OK; /* * send an EOJ message */ if (send_eoj_msg(reason) != NULL) { disconn_ps(sock); return(-1); } /* * wait for, and process status message */ cur_con_state = 0; while (cur_con_state == 0) { if (proc_status() != NULL) { fprintf (stderr, "Olpscomm: error from process_status: eoj sent\n"); disconn_ps(sock); return(-1); } switch (cur_con_state) { case 0: continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -