|
|
1.1 root 1: /*
2: * This file implements functions used by both server and daemon
3: * for the XNS courier library
4: */
5:
6: /*
7: $Log: lookahead.c,v $
8: * Revision 2.1 86/11/19 06:24:48 jqj
9: * Per Ed Flint: in LookAheadCallMsg, don't decrement byteswanted when
10: * skipping non-RPC packets.
11: *
12: * Revision 2.0 85/11/21 07:22:10 jqj
13: * 4.3BSD standard release
14: *
15: * Revision 1.4 85/09/28 06:54:25 jqj
16: * 1/ 4.3 version.
17: * 2/ fix bug in error reporting -- it had always reported NoSuchVersionNumber
18: * even when NoSuchProgram was appropriate.
19: *
20: */
21:
22: #ifndef lint
23: static char rcsid[] = "$Header: lookahead.c,v 2.1 86/11/19 06:24:48 jqj Exp $";
24: #endif
25:
26: #include <stdio.h>
27: #include <sys/time.h>
28: #include <sys/types.h> /* for xn.h */
29: #include <sys/socket.h>
30: #include <sys/uio.h>
31: #include <netns/ns.h> /* for XNS addresses and courierconnectin.h */
32: #include <netns/idp.h>
33: #include <netns/sp.h> /* for spphdr */
34: #include "courier.h"
35: #include "realcourierconnection.h"
36: #include "courierdb.h"
37: #ifndef COURLIB
38: #define COURLIB "/usr/new/lib/xnscourier"
39: #endif
40:
41: #define MAKEVEC(idx, addr, len) our_iovec[idx].iov_base = (caddr_t)addr;\
42: our_iovec[idx].iov_len = len;
43:
44: #if DEBUG
45: extern int CourierServerDebuggingFlag;
46: #endif
47:
48: extern CourierConnection *_serverConnection;
49: extern Unspecified tid;
50:
51: int
52: LookAheadCallMsg(progptr, versionptr, skippedwords)
53: LongCardinal *progptr;
54: Cardinal *versionptr;
55: Unspecified skippedwords[];
56: /* Returns number of words set in skippedwords i.e. from packets we
57: * had to read to get to the program/version pair. Sets *progptr
58: * to the program number, and *versionptr to the version number.
59: */
60: /* Returns -1 if timeout expired. SPP connection is closed. */
61: {
62: register CourierConnection *f = _serverConnection;
63: static struct timeval timeout = {90,0}; /* 90sec. timeout */
64: int fdmask,
65: count,
66: byteswanted,
67: bytesread;
68: struct sphdr hdrbuf;
69: Unspecified databuf[MAXWORDS];
70: Unspecified *bp;
71: Cardinal msgtype;
72: Unspecified msgtid;
73: static Cardinal ourversion = COURIERVERSION;
74: Cardinal versionl, versionh;
75: static struct iovec our_iovec[3];
76: static struct msghdr ourmsg = {0, 0, our_iovec, 3, 0, 0};
77:
78: fdmask = 1<<(f->fd);
79: count = 0;
80: bytesread = 0;
81: byteswanted = 14; /* CverL, CverH, CALL, tid, Prg1, Prg2, Ver */
82: MAKEVEC(0, &hdrbuf, sizeof(struct sphdr));
83: MAKEVEC(1, skippedwords, byteswanted);
84: MAKEVEC(2, databuf, SPPMAXDATA);
85: /* wantversion =df need to read a courier version # from stream */
86: if (f->state != wantversion) {
87: /* pretend we've gotten a version */
88: bp = skippedwords;
89: bp += externalize_Cardinal(&ourversion, bp);
90: bp += externalize_Cardinal(&ourversion, bp);
91: bytesread += 4;
92: byteswanted -= 4;
93: our_iovec[1].iov_len -= 4;
94: our_iovec[1].iov_base += 4;
95: /* tell other routines there is a version */
96: f->state = wantversion;
97: }
98: if (select(f->fd+1,&fdmask,(int*)NULL,(int*)NULL,&timeout) <= 0) {
99: (void) sppclose(f->fd);
100: f->state = closed;
101: return(-1);
102: }
103: while (byteswanted > 0) {
104: count = recvmsg(f->fd, &ourmsg, MSG_PEEK)
105: - sizeof(struct sphdr);
106: if (count < 0 || hdrbuf.sp_dt == SPPSST_END) {
107: (void) sppclosereply(f->fd);
108: f->state = closed;
109: return(-1);
110: }
111: if (hdrbuf.sp_dt != SPPSST_RPC &&
112: (bytesread > 0 || count != 4)) {
113: /* throw away bad packets */
114: (void) readv(f->fd, our_iovec, 3);
115: continue; /* don't decrement byteswanted */
116: }
117: else if (count <= byteswanted) {
118: /* actually read the packet we peeked */
119: count = readv(f->fd, our_iovec, 3) -
120: sizeof(struct sphdr);
121: bytesread += count;
122: our_iovec[1].iov_len -= count;
123: our_iovec[1].iov_base += count;
124: }
125: byteswanted -= count;
126: }
127: bp = skippedwords;
128: bp += internalize_Cardinal(&versionl, bp);
129: bp += internalize_Cardinal(&versionh, bp);
130: if (versionl > COURIERVERSION || versionh < COURIERVERSION) {
131: (void) sppclose(f->fd);
132: f->state = closed;
133: return(-1);
134: /*NOTREACHED*/
135: }
136: /*
137: * note we haven't actually read the packet containing the
138: * remote procedure number, though we may have PEEKed it.
139: */
140: bp += internalize_Cardinal(&msgtype, bp);
141: if (msgtype != CALL) {
142: SendRejectMessage(unspecifiedError, 0, NULL);
143: (void) sppclose(f->fd);
144: f->state = closed;
145: return(-1);
146: /*NOTREACHED*/
147: }
148: bp += internalize_Unspecified(&msgtid, bp);
149: bp += internalize_LongCardinal(progptr, bp);
150: bp += internalize_Cardinal(versionptr, bp);
151: return(bytesread/sizeof(Unspecified));
152: /* all that work, and we have to do it over again */
153: }
154:
155: ExecCourierProgram(programnum, versionnum, skipcount, skippedwords)
156: LongCardinal programnum;
157: Cardinal versionnum;
158: int skipcount;
159: Unspecified skippedwords[];
160: /*
161: * Exec the appropriate courier program, passing it asciized skippedwords
162: * in the argument list.
163: * Does not return unless the exec failed or the server was not found.
164: * If the server cannot be EXECed, then the appropriate message is sent
165: * back on the wire and the current message is flushed.
166: */
167: {
168: struct courierdbent *cdbent;
169: char *argv[12];
170: int i, argc;
171: extern char *malloc();
172: char tmpbuf[1024];
173:
174: cdbent = getcourierservice(programnum, versionnum);
175: if (cdbent != NULL &&
176: (cdbent->cr_serverbin == NULL || *cdbent->cr_serverbin == '\0')) {
177: sprintf(tmpbuf,"%s/%s%dd",
178: COURLIB,
179: cdbent->cr_programname, cdbent->cr_version);
180: if (access(tmpbuf,1) == 0)
181: cdbent->cr_serverbin = tmpbuf;
182: }
183: if (cdbent == NULL || cdbent->cr_serverbin == NULL ||
184: *cdbent->cr_serverbin == '\0') {
185: register Cardinal curval;
186: Cardinal range[2];
187: range[0] = 077777; range[1] = curval = 0;
188: setcourierdbent();
189: while ((cdbent = getcourierdbent()) != NULL) {
190: if (cdbent->cr_programnumber != programnum) continue;
191: curval = cdbent->cr_version;
192: if (curval < range[0]) range[0] = curval;
193: if (curval > range[1]) range[1] = curval;
194: }
195: Deallocate(ReadMessage(_serverConnection, NULL, 0));
196: /* flush message */
197: if (curval > 0)
198: SendRejectMessage(noSuchVersionNumber, 2, range);
199: else SendRejectMessage(noSuchProgramNumber, 0, NULL);
200: #if DEBUG
201: (void) fprintf(stderr, "xnscourierd: no program %d(%d)\n",
202: programnum, versionnum);
203: #endif
204: return; /* can't find server */
205: }
206: argc = 0;
207: argv[argc] = malloc(4); /* allow 3 digits per file descriptor */
208: sprintf(argv[argc++],"%d",(int)_serverConnection->fd);
209: for (i = 0; i < skipcount; i++) {
210: argv[argc] = malloc(8); /* allow 7 digits per Unspecified */
211: sprintf(argv[argc++],"%d",(int) skippedwords[i]);
212: }
213: argv[argc] = (char *) 0;
214: execv(cdbent->cr_serverbin, argv);
215: Deallocate(ReadMessage(_serverConnection, NULL, 0));/* flush message */
216: SendRejectMessage(unspecifiedError, 0, NULL);
217: #if DEBUG
218: (void) fprintf(stderr, "xnscourierd: can't exec %s\n",
219: cdbent->cr_serverbin);
220: #endif
221: return;
222: }
223:
224:
225: SendRejectMessage(rejecttype, nwords, arguments)
226: Cardinal rejecttype;
227: Cardinal nwords;
228: Unspecified *arguments;
229: {
230: #define REJECTHDRLEN 3
231: static Cardinal msgtype = REJECT;
232: Unspecified *bp, buf[REJECTHDRLEN];
233:
234: #if DEBUG
235: if (CourierServerDebuggingFlag)
236: fprintf(stderr, "[SendRejectMessage %d, length %d]\n",
237: rejecttype, nwords);
238: #endif
239: bp = buf;
240: bp += externalize_Cardinal(&msgtype, bp);
241: bp += externalize_Unspecified(&tid, bp);
242: bp += externalize_Cardinal(&rejecttype, bp);
243: CourierWrite(_serverConnection, (bp-buf), buf, nwords, arguments);
244: }
245:
246:
247: SendAbortMessage(errorvalue, nwords, arguments)
248: LongCardinal errorvalue;
249: Cardinal nwords;
250: Unspecified *arguments;
251: /* note that arguments does NOT include the error value */
252: {
253: #define ABORTHDRLEN 3
254: Cardinal shorterror;
255: static Cardinal msgtype = ABORT;
256: Unspecified *bp, buf[ABORTHDRLEN];
257:
258: #if DEBUG
259: if (CourierServerDebuggingFlag)
260: fprintf(stderr, "[SendAbortMessage %d %d]\n",
261: errorvalue, nwords);
262: #endif
263: bp = buf;
264: bp += externalize_Cardinal(&msgtype, bp);
265: bp += externalize_Unspecified(&tid, bp);
266: shorterror = (Cardinal) (errorvalue - ERROR_OFFSET);
267: bp += externalize_Cardinal(&shorterror, bp);
268: CourierWrite(_serverConnection, (bp-buf), buf, nwords, arguments);
269: }
270:
271: /*ARGSUSED*/
272: NoSuchProcedureValue(prog_name, proc)
273: String prog_name;
274: Cardinal proc;
275: {
276: SendRejectMessage(noSuchProcedureValue, 0, (Unspecified*) NULL);
277: #if DEBUG
278: if (CourierServerDebuggingFlag)
279: fprintf(stderr, "[NoSuchProcedureValue %d in %s]\n",
280: proc, prog_name);
281: #endif
282: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.