📄 lpcomm.c
字号:
fprintf(stderr,"Exiting incrP return FALSE, ast_completed[%d] = %d\n", FD,ast_completed[FD]);#endif VMS return(FALSE);}/* * L P _ C _ p r o b e * * Test to see whether or not there is a message waiting to be read. * * Inputs: int FD * Outputs: TRUE if a msg is waiting, else FALSE * Side Effects: none * */LP_C_probe(FD)int FD;{ char *buffer; int jp; int retval; int SelectStatus; /* status returned to us from select() */ long SelectMask; /* mask given by us to select() */#ifndef VMS struct timeval timeout;#endif VMS#ifdef VMS if (debug > 8) fprintf(stderr,"Entering LP_C_probe, ast_completed[%d] = %d\n", FD,ast_completed[FD]);#endif VMS if (FD < 0) return (FALSE);/* The cached copy of the probe information makes sure that we don't call select any more than necessary. It is not very fast, at least not with sockets. */ if (probeCache[FD]) {#ifdef VMS if (debug > 8) fprintf(stderr,"Exiting LP_C_probe via probeCache check, ast_completed[%d] = %d\n", FD,ast_completed[FD]);#endif VMS return(TRUE); } buffer = inputBuffers[FD]; if (buffer == 0) goto notInBuffer; /* not yet allocated */ jp = firstUnused[FD]; if (jp < 0 || jp > lastByteIn[FD]) goto notInBuffer; while (jp < lastByteIn[FD]) { if (buffer[jp++] == RELAY_SOM) { retval = TRUE; goto collect; } }/* No data in buffer. Check to see if any is pending on socket */notInBuffer: #ifndef VMS timeout.tv_sec = 0; timeout.tv_usec = 0; SelectMask = 1<<FD; SelectStatus = select(32, &SelectMask, 0, 0, &timeout); retval = (SelectStatus > 0);#else VMS if (ast_completed[FD]) retval = TRUE; else retval = FALSE;#endif VMScollect: probeCache[FD] = retval;#ifdef VMS if (debug > 8) fprintf(stderr,"Exiting LP_C_probe, ast_completed[%d] = %d\n", FD,ast_completed[FD]);#endif VMS return(retval);}/* * * L P _ C _ g e t s * * This routine behaves identically to the stdio routine "gets", namely * it reads a string from standard input into the buffer that is its argument. * The only difference is that after it is done reading, it resets the * probe cache so that the client code will no longer make assumptions * about whether or not there is input. * * */char *LP_C_gets(str)char *str;{ probeCache[stdinFD] = FALSE; return(gets(str));}/* * * L P _ C _ g e t c * * This routine behaves identically to the stdio routine "getc", namely * it reads a character from standard input and returns it. * The only difference is that after it is done reading, it resets the * probe cache so that the client code will no longer make assumptions * about whether or not there is input. * * The assumption here is that we get "an interrupt per character" and the * read from stdin or qioBuffers[stdinFD] returnes a single character. */LP_C_getc(){#ifndef VMS probeCache[stdinFD] = FALSE; return(getc(stdin));#else VMS static char *qiobuf; probeCache[stdinFD] = FALSE; rcv_pending[stdinFD] = FALSE; ast_completed[stdinFD] = FALSE; qiobuf = qioBuffers[stdinFD]; return(*qiobuf);#endif VMS}/* * L P _ C _ w a i t F o r M s g * * If there is a message waiting on one of the indicated FD's, then return * immediately. If not, then block until a message is available. * * Inputs: int FD1, FD2 * Outputs: none * Side Effects: none * Action: Blocks until a message is available, then returns. * * The temptation was strong to write a generalized N-way block routine, * using arrays of FD's, but the truth is that for this application you * really only need 2-way waiting. */void LP_C_waitForMsg (FD1,FD2)int FD1,FD2;{ long SelectMask; long ExceptMask;#ifdef VMS if (debug > 7) { fprintf(stderr,"Entering LP_C_waitForMsg\n"); fprintf(stderr," ast_completed[%d] = %d, rcv_pending[%d] = %d, probeCache[%d] = %d\n", FD1,ast_completed[FD1],FD1,rcv_pending[FD1],FD1,probeCache[FD1]); fprintf(stderr," ast_completed[%d] = %d, rcv_pending[%d] = %d, probeCache[%d] = %d\n", FD2,ast_completed[FD2],FD2,rcv_pending[FD2],FD2,probeCache[FD2]); } /* * If we have an AST completed on a specific channel, we want to set * probeCache TRUE so that the following test will allow us to return * and process the message. * * We explicitly check for the second channel (which will always be the * channel assigned to stdin) because the second channel is initialized * to -1 and the compiler will allow you to read ast_completed[-1] without * generating an access violation. However, we can't set the value!!! */ if (ast_completed[FD1]) probeCache[FD1] = TRUE; if (FD2 >= 0 && ast_completed[FD2]) probeCache[FD2] = TRUE;#endif VMS if (FD1 >= 0 && LP_C_probe(FD1)) return; if (FD2 >= 0 && LP_C_probe(FD2)) return;#ifndef VMS SelectMask = 0; if (FD1 >= 0) SelectMask |= (1<<FD1); if (FD2 >= 0) SelectMask |= (1<<FD2); ExceptMask = SelectMask; select(32, &SelectMask, 0, &ExceptMask, 0); SelectMask |= ExceptMask; if (FD1>=0 && (SelectMask & (1<<FD1))) probeCache[FD1] = TRUE; if (FD2>=0 && (SelectMask & (1<<FD2))) probeCache[FD2] = TRUE;#else VMS if (FD1 >= 0) if (!rcv_pending[FD1]) issue_read(FD1); if (FD2 >= 0) if (!rcv_pending[FD2]) issue_read(FD2); if (debug > 7) { fprintf(stderr,"In LP_C_waitForMsg before call to HIBER\n"); fprintf(stderr," ast_completed[%d] = %d, rcv_pending[%d] = %d, probeCache[%d] = %d\n", FD1,ast_completed[FD1],FD1,rcv_pending[FD1],FD1,probeCache[FD1]); fprintf(stderr," ast_completed[%d] = %d, rcv_pending[%d] = %d, probeCache[%d] = %d\n", FD2,ast_completed[FD2],FD2,rcv_pending[FD2],FD2,probeCache[FD2]); } if (FD2 == -1 ) { while (!ast_completed[FD1]) { if (debug > 7) fprintf(stderr,"In LP_C_waitForMsg in if with one FD\n"); SYS$HIBER(); } } else { while (!ast_completed[FD1] && !ast_completed[FD2]) { if (debug > 7) fprintf(stderr,"In LP_C_waitForMsg in if with two FDs\n"); SYS$HIBER(); } } if (debug > 7) { fprintf(stderr,"In LP_C_waitForMsg following return from HIBER\n"); fprintf(stderr," ast_completed[%d] = %d, rcv_pending[%d] = %d, probeCache[%d] = %d\n", FD1,ast_completed[FD1],FD1,rcv_pending[FD1],FD1,probeCache[FD1]); fprintf(stderr," ast_completed[%d] = %d, rcv_pending[%d] = %d, probeCache[%d] = %d\n", FD2,ast_completed[FD2],FD2,rcv_pending[FD2],FD2,probeCache[FD2]); } /* * After returning from the sys$hiber, update the probeCache. */ if (ast_completed[FD1]) probeCache[FD1] = TRUE; if (FD2 >= 0 && ast_completed[FD2]) probeCache[FD2] = TRUE; if (debug > 7) { fprintf(stderr,"Exiting LP_C_waitForMsg\n"); fprintf(stderr," ast_completed[%d] = %d, rcv_pending[%d] = %d, probeCache[%d] = %d\n", FD1,ast_completed[FD1],FD1,rcv_pending[FD1],FD1,probeCache[FD1]); fprintf(stderr," ast_completed[%d] = %d, rcv_pending[%d] = %d, probeCache[%d] = %d\n", FD2,ast_completed[FD2],FD2,rcv_pending[FD2],FD2,probeCache[FD2]); }#endif VMS return;}/* * L P _ C _ w a i t F o r R e p l y * * Called from user code when the code needs to wait for a specific reply * from the server. LP_C_waitForReply repeatedly calls LP_C_recv and checks * to see if the received message is the one we are waiting for. If the * message is the one we are waiting for, then LP_C_waitForReply returns * after copying the message fields into its arguments. If the message does * not arrive, then we wait forever. * * Inputs: int ServerFD incoming FD * OtherFD outgoing FD * Opcode, ID, Length; Data standard frame * int dproc() callback procedure * Outputs: Opcode, Length, Data * Returns: True if successful, False if end of file * Side Effects: reads and removes messages from server sockete * until it finds one matching "ID". If messages * appear on client sockets while waiting, those * messages are properly dispatched. */int LP_C_waitForReply(ServerFD, OtherFD, Opcode, ID, Length, Data, dproc) int ServerFD,OtherFD; char *Opcode; int ID, *Length; char *Data; int (*dproc)();{ int MesgID,Status;#ifdef VMS if (debug > 7) fprintf(stderr,"Entering LP_C_waitForReply, ast_completed[%d] = %d\n", ServerFD, ast_completed[ServerFD]);#endif VMS MesgID = -1; /* Impossible value for a message ID */ while (MesgID != ID) { if (debug>7) fprintf(stderr,"%s %s: waiting for message %d\n", progName, LPStime(), ID); LP_C_waitForMsg(ServerFD,OtherFD); if (LP_C_probe(ServerFD)) { Status = LP_C_recv(ServerFD, Opcode, &MesgID, Length, Data); if (Status < 0) {#ifdef VMS if (debug > 7) fprintf(stderr,"Exiting LP_C_waitForReply via status < 0, ast_completed[%d] = %d\n", ServerFD,ast_completed[ServerFD]);#endif VMS return(FALSE); } if (MesgID == ID && (!strcmp(Opcode,OP_REPLY) || !strcmp(Opcode,OP_NAK)) ) {#ifdef VMS if (debug > 7) fprintf(stderr,"Exiting LP_C_waitForReply via MesgID check, ast_completed[%d] = %d\n", ServerFD,ast_completed[ServerFD]);#endif VMS return(TRUE); } if ( dproc != 0) { (*dproc)(TRUE, Opcode, MesgID, *Length, Data); } } if (LP_C_probe(OtherFD)) { if (debug>7) fprintf(stderr,"%s %s: input on otherFD while waiting.\n", progName, LPStime()); Status = LP_C_recv(OtherFD, Opcode, &MesgID, Length, Data); if (Status < 0) return(FALSE); if ( (dproc) != 0) { (*dproc)(FALSE, Opcode, MesgID, *Length, Data); } } }#ifdef VMS if (debug > 7) fprintf(stderr,"Exiting LP_C_waitForReply, ast_completed[%d] = %d\n", ServerFD, ast_completed[ServerFD]);#endif VMS return(TRUE); /* in theory this is unreachable */}/* * * L P _ C _ s e n d * * This routine composes and sends a message to the print server. The * message format is specified by the "Print Server Protocol". * * Inputs: ServerFD (integer) FD to send to * Opcode (string) opcode * mdata (string) what to send * ID (integer) message number, or zero * count (int) byte count, or zero * Outputs: none * Returns: ID (integer) generated message number * * If the byte count is zero, then we use strlen() to count bytes. If it * is nonzero, then the data can contain nulls. */int SequenceID=0; /* integer sequence ID number */int LP_C_send(ServerFD, Opcode, mdata, ID, mlen)int ServerFD;char *Opcode, *mdata;int ID;{ char packetBuffer[2*DECNET_MAX_FRAME]; char *ic,*jc; static int pow10[10]= {1,1,10,100,1000,10000,100000,1000000,10000000,100000000}; int nlen,tlen,i,n,r; int fixedLength; /* size of fixed part of packet */ int packetLength;#ifdef VMS int WriteStatus; unsigned short iosb[4];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -