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