📄 clnt_tty.c
字号:
/* clnt_tty.c - implements a serial line based, client side RPC *//* Copyright 1984-1994 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * Copyright (c) 1987 Wind River Systems, Inc. * Copyright (C) 1984, Sun Microsystems, Inc. * * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 *//*modification history--------------------01k,25jan99,elg Add Flow Control on Serial Backend (SPR 22159)01j,01jul98,c_s WindView 2 -> Tornado 2 Merge01i,12may98,nps cumulative patch merge01h,26aug97,pcn Fixed SPR #8979.01k,03mar98,c_c Removed strings.h for WIN32.01j,02mar98,pcn Removed warnings.01i,21jan98,c_c DLLized Target Server implementation. Got rid of EXT_FUNC refs.01h,26aug97,pcn Fixed SPR #8979.01g,21nov96,wmd fixed spr #7427 - wdbserial for AIX host.01f,19apr96,jco in routine clnttty_call, used __seterr_reply on Solaris 2.x hosts instead of _seterr_reply (spr 4780 and further 4751).01e,16jan96,elp adapted calls of dll external functions (changed wpwrLogErr in wpwrLogErr ...)01d,27jun95,tpr changed 38800 to 38400 in baudTable[].01c,09jun95,p_m changed __WIN32__ to WIN32.01b,01jun95,tpr cleaned up.01a,21apr95,ms hacked up version of clnt_udp.c for serial devices.*/#ifndef lint/* static char sccsid[] = "@(#)clnt_tty.c 1.1 86/02/03 Copyr 1984 Sun Micro"; */#endif/* * clnt_tty.c, Implements a UPD/IP based, client side RPC. * */#ifdef WIN32#define WIN32_LEAN_AND_MEAN 1#include <windows.h>#include <winbase.h>#include <winnt.h>#include <time.h>#include <process.h>#include "ttydev.h"#include "win32Serial.h"#else#ifdef RS6000_AIX4#include <sys/termio.h>#endif#ifdef PARISC_HPUX10#include <sys/termiox.h>#include <sys/modem.h>#endif /* PARISC_HPUX10 */#include <sys/tiuser.h>#include <strings.h>#endif /* WIN32 */#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <termios.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <rpc/rpc.h>#include <rpc/types.h>#include <rpc/xdr.h>#include <rpc/auth.h>#include <rpc/clnt.h>#include <rpc/rpc_msg.h>#include <rpc/pmap_clnt.h>#include "wdbP.h"#include "wpwrutil.h"/* externals */IMPORT bool_t xdr_opaque_auth (XDR *, struct opaque_auth *);IMPORT bool_t xdr_callhdr (XDR *, struct rpc_msg *);IMPORT bool_t xdr_replymsg (XDR *, struct rpc_msg *);#ifndef SUN4_SOLARIS2IMPORT void _seterr_reply (struct rpc_msg *, struct rpc_err *);#endif /* SUN4_SOLARIS2 *//* * TTY bases client side rpc operations */static enum clnt_stat clnttty_call ( CLIENT * cl, /* client handle */ u_long proc, /* procedure number */ xdrproc_t xargs, /* xdr routine for args */ caddr_t argsp, /* pointer to args */ xdrproc_t xresults, /* xdr routine for results */ caddr_t resultsp, /* pointer to results */ struct timeval utimeout /* seconds to wait before giving up - 4.0 */ );static void clnttty_abort ( CLIENT *h );static void clnttty_geterr ( CLIENT *cl, struct rpc_err *errp );static bool_t clnttty_control ( CLIENT *cl, int request, char *info );static void clnttty_destroy ( CLIENT *cl );static bool_t clnttty_freeres ( CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr );#ifdef WIN32HANDLE serialFd = 0;static struct opaque_auth _null_auth;/* static struct rpc_createerr rpc_createerr; */#define mem_alloc(bsize) malloc(bsize)#define mem_free(ptr, bsize) free(ptr)#endif /* WIN32 *//* * Other forward static function declarations */static int clnttty_send ( int fd, char * inBuf, int nBytes );static int clnttty_rcv ( int fd, char * buf, int nBytes );static int clnttty_open ( char * devName, int baudRate, BOOL hardFlowControl, struct timeval wait );/* locals */static struct clnt_ops tty_ops = { clnttty_call, clnttty_abort, clnttty_geterr, clnttty_freeres, clnttty_destroy, clnttty_control };/* * Private data kept per client handle */struct cu_data { int cu_fd; int seqNum; struct timeval cu_wait; struct timeval cu_total; struct rpc_err cu_error; XDR cu_outxdrs; u_int cu_xdrpos; u_int cu_sendsz; char *cu_outbuf; u_int cu_recvsz; char cu_inbuf[1]; };/* * default size fo send/rcv buffers */#define TTYMSGSIZE 1500/* * Create a TTY based client handle. * * wait is the amount of time used between retransmitting a call if * no response has been heard; retransmition occurs until the actual * rpc call times out. * * sendsz and recvsz are the maximum allowable packet sizes that can be * sent and received. */CLIENT * clnttty_bufcreate ( u_long program, u_long version, struct timeval wait, char * devName, int baudRate, BOOL hardFlowControl, u_int sendsz, u_int recvsz ) { CLIENT *cl; register struct cu_data * cu = NULL; struct timeval now; struct rpc_msg call_msg; cl = (CLIENT *)mem_alloc(sizeof(CLIENT)); if(cl == NULL) { wpwrLogErr ("clnttty_create: out of memory\n"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } sendsz = ((sendsz + 3) / 4) * 4; recvsz = ((recvsz + 3) / 4) * 4; cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz); if(cu == NULL) { wpwrLogErr ("clnttty_create: out of memory\n"); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } cu->cu_outbuf = &cu->cu_inbuf[recvsz];#ifndef WIN32 (void)gettimeofday(&now, (struct timezone *)0);#else { time_t time_val; (void)time(&time_val); now.tv_sec = time_val; now.tv_usec = 0; }#endif cl->cl_ops = &tty_ops; cl->cl_private = (caddr_t)cu; cu->seqNum = (getpid() << 16); cu->cu_wait = wait; cu->cu_total.tv_sec = -1; cu->cu_total.tv_usec = -1; cu->cu_sendsz = sendsz; cu->cu_recvsz = recvsz; call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec; call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = program; call_msg.rm_call.cb_vers = version; xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE); if(! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) { goto fooy; } cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs)); /* open the serial device */ cu->cu_fd = clnttty_open (devName, baudRate, hardFlowControl, wait); if(cu->cu_fd < 0) { wpwrLogErr ("clnttty_bufcreate can't open %s\n", devName); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } cl->cl_auth = authnone_create(); return (cl); fooy: if(cu) mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz); if(cl) mem_free((caddr_t)cl, sizeof(CLIENT)); return ((CLIENT *)NULL); }CLIENT * clnttty_create ( char * devName, int baudRate, BOOL hardFlowControl, u_long program, u_long version, struct timeval wait ) { return (clnttty_bufcreate (program, version, wait, devName, baudRate, hardFlowControl, TTYMSGSIZE, TTYMSGSIZE)); }static enum clnt_stat clnttty_call ( register CLIENT *cl, /* client handle */ u_long proc, /* procedure number */ xdrproc_t xargs, /* xdr routine for args */ caddr_t argsp, /* pointer to args */ xdrproc_t xresults, /* xdr routine for results */ caddr_t resultsp, /* pointer to results */ struct timeval utimeout/* seconds to wait before giving up - 4.0 */ ) { register struct cu_data *cu = (struct cu_data *)cl->cl_private; register XDR *xdrs; register int outlen; register int inlen;#ifndef WIN32 fd_set readFds; fd_set mask;#endif struct rpc_msg reply_msg; XDR reply_xdrs; struct timeval time_waited; bool_t ok; int nrefreshes = 2; struct timeval timeout; if(cu->cu_total.tv_usec == -1) { timeout = utimeout; } else { timeout = cu->cu_total; } time_waited.tv_sec = 0; time_waited.tv_usec = 0; call_again: xdrs = &(cu->cu_outxdrs); xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, cu->cu_xdrpos); /* * the transaction is the first thing in the out buffer */ (*(u_short *)(cu->cu_outbuf))++; if((! XDR_PUTLONG(xdrs, (long *)&proc)) || (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || (! (*xargs)(xdrs, argsp))) { return (cu->cu_error.re_status = RPC_CANTENCODEARGS); } outlen = (int)XDR_GETPOS(xdrs); send_again: if(clnttty_send (cu->cu_fd, cu->cu_outbuf, outlen) == 0) { cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTSEND); } /* * Hack to provide rpc-based message passing */ if(timeout.tv_sec == 0 && timeout.tv_usec == 0) { return (cu->cu_error.re_status = RPC_TIMEDOUT); } /* * sub-optimal code appears inside the loop because we have * some clock time to spare while the packets are in flight. * (We assume that this is actually only executed once.) */ reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = resultsp; reply_msg.acpted_rply.ar_results.proc = xresults;#ifndef WIN32 FD_ZERO (&mask); FD_SET (cu->cu_fd, &mask);#endif for(;;) {#ifndef WIN32 readFds = mask; switch(select (FD_SETSIZE, &readFds, (fd_set *)NULL, (fd_set *)NULL, &(cu->cu_wait)))#else switch(win32SerialSelect ((int)cu->cu_wait.tv_sec))#endif { case 0: time_waited.tv_sec += cu->cu_wait.tv_sec; time_waited.tv_usec += cu->cu_wait.tv_usec; while(time_waited.tv_usec >= 1000000) { time_waited.tv_sec++; time_waited.tv_usec -= 1000000; } if((time_waited.tv_sec < timeout.tv_sec) || ((time_waited.tv_sec == timeout.tv_sec) && (time_waited.tv_usec < timeout.tv_usec))) goto send_again; return (cu->cu_error.re_status = RPC_TIMEDOUT); /* * buggy in other cases because time_waited is not being * updated */ case -1: if(errno == EINTR) continue; cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } do { inlen = clnttty_rcv (cu->cu_fd, cu->cu_inbuf, cu->cu_recvsz); } while(inlen < 0 && (errno == EINTR)); if(inlen < 0) {#ifdef WIN32 if(errno == WSAEWOULDBLOCK)#else if(errno == EWOULDBLOCK)#endif continue; cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } if(inlen < (int) sizeof(u_long)) continue; /* see if reply transaction id matches sent id */ if(*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf))) continue; /* we now assume we have the proper reply */ break; } /* * now decode and validate the response */ xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE); ok = xdr_replymsg(&reply_xdrs, &reply_msg); /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */ if(ok) {#ifndef SUN4_SOLARIS2 _seterr_reply(&reply_msg, &(cu->cu_error));#else __seterr_reply(&reply_msg, &(cu->cu_error));#endif /* !SUN4_SOLARIS2 */ if(cu->cu_error.re_status == RPC_SUCCESS) { if(! AUTH_VALIDATE(cl->cl_auth, &reply_msg.acpted_rply.ar_verf)) { cu->cu_error.re_status = RPC_AUTHERROR; cu->cu_error.re_why = AUTH_INVALIDRESP; } if(reply_msg.acpted_rply.ar_verf.oa_base != NULL) { xdrs->x_op = XDR_FREE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -