1: # include "../../ingres.h" 2: # include "../../symbol.h" 3: # include "../../pipes.h" 4: # include "IIglobals.h" 5: 6: /* 7: ** Buffered Read From Pipe 8: ** 9: ** Reads from the pipe with the UNIX file descriptor `des' into 10: ** the buffer `buf'. `Mode' tells what is to be done. `Msg' is 11: ** the address of the input buffer, and `n' is the length of the 12: ** info. If `n' is zero, the data is assumed to be a null- 13: ** terminated string. 14: ** 15: ** `Buf' is defined in "../pipes.h" together with the modes. 16: ** The pipe should be written by wrpipe() to insure that the 17: ** pipe formats match. 18: ** 19: ** Modes: 20: ** 21: ** P_PRIME -- Primes the buffer. This involves cleaning out all 22: ** the header stuff so that a physical read is forced 23: ** on the next normal call to rdpipe(). It also resets 24: ** the error flag, etc. 25: ** 26: ** P_NORM -- This is the normal mode. If the buffer is empty, 27: ** it is filled from the pipe. `N' bytes are moved into 28: ** `msg'. If `n' is zero, bytes are moved into `msg' up 29: ** to and including the first null byte. The pipe is 30: ** read whenever necessary, so the size of the data 31: ** buffer (controlled by PBUFSIZ) has absolutely no 32: ** effect on operation. 33: ** 34: ** P_SYNC -- This mode reads the buffer, filling the pipe as 35: ** necessary, until an End Of Pipe (EOP) is encountered. 36: ** An EOP is defined as an empty buffer with a mode 37: ** ("hdrstat") of "END_STAT". Any data left in the pipe 38: ** is thrown away, but error messages are not. Anything 39: ** not already read by the user is read by P_SYNC, so if 40: ** you are not certain that you have already read the 41: ** previous EOP. 42: ** 43: ** P_EXECID -- The first (exec_id) field of the pipe buffer header 44: ** is read and returned. This is used (for instance) by 45: ** the DBU routines, which must get the exec_id, but must 46: ** not read the rest of the pipe in case they must overlay 47: ** themselves. It must ALWAYS be followed by a rdpipe of 48: ** mode P_FUNCID!! 49: ** 50: ** P_FUNCID -- The second through last bytes of the pipe are read 51: ** into the buffer, and the function code ("func_id") is 52: ** returned. This is the second half of a P_EXECID call. 53: ** 54: ** P_INT -- In the event of an interrupt, a wrpipe() call should 55: ** be made to all writable pipes of mode P_INT, and then 56: ** rdpipe() calls should be made on all readable pipes 57: ** of this mode. This clears out the pipe up until a 58: ** special type of pipe header ("SYNC_STAT") is read. It 59: ** is absolutely critical that this is called in conjunc- 60: ** tion with all other processes. This mode is used in 61: ** resyncpipes(), which performs all the correct calls 62: ** in the correct order. 63: ** 64: ** In all cases except P_INT mode, if an error is read from the 65: ** pipe it is automatically passed to proc_error(). This routine 66: ** is responsible for passing the error message to the next higher 67: ** process. 68: ** 69: ** If an end of file is read from the pipe, the end_job() routine 70: ** is called. This routine should do any necessary end of job 71: ** processing needed (closing relations, etc.) and return with 72: ** a zero value. 73: ** 74: ** Default proc_error() and end_job() routines exist in the 75: ** library, so if you don't want any extra processing, you can 76: ** just not bother to define them. 77: ** 78: ** In general, the number of bytes actually read is returned. If 79: ** you read an EOP, zero is returned. 80: */ 81: 82: IIrdpipe(mode, buf1, des, msg, n) 83: int mode; 84: char *msg; 85: int n; 86: int des; /* UNIX file descriptor for pipe */ 87: struct pipfrmt *buf1; 88: { 89: register int knt; 90: register int syncflg; 91: int i; 92: extern char *IIproc_name; 93: char *proc_name; 94: register struct pipfrmt *buf; 95: char *argv[10], args[512]; 96: char *ap; 97: int argc, err; 98: 99: # ifdef xATR1 100: proc_name = IIproc_name ? IIproc_name : ""; 101: # endif 102: 103: buf = buf1; 104: 105: # ifdef xATR1 106: if (IIdebug > 1) 107: printf("\n%s ent rdpipe md %d buf %u des %d\n", proc_name, mode, buf, des); 108: # endif 109: syncflg = 0; 110: switch (mode) 111: { 112: 113: case P_PRIME: 114: buf->pbuf_pt = buf->buf_len = buf->err_id = 0; 115: buf->hdrstat = NORM_STAT; 116: return (0); 117: 118: case P_NORM: 119: break; 120: 121: case P_SYNC: 122: syncflg++; 123: break; 124: 125: case P_EXECID: 126: if (read(des, &buf->exec_id, 1) < 1) 127: { 128: goto eoj; 129: } 130: # ifdef xATR3 131: if (IIdebug > 1) 132: printf("%s rdpipe ret %c\n", proc_name, buf->exec_id); 133: # endif 134: return (buf->exec_id); 135: 136: case P_FUNCID: 137: i = read(des, &buf->func_id, HDRSIZ+PBUFSIZ-1) + 1; 138: buf->pbuf_pt = -1; 139: goto chkerr; 140: 141: case P_INT: 142: syncflg--; 143: buf->hdrstat = NORM_STAT; 144: break; 145: 146: default: 147: IIsyserr("rdpipe: bad call %d", mode); 148: } 149: knt = 0; 150: if (buf->pbuf_pt < 0) 151: buf->pbuf_pt = 0; 152: 153: do 154: { 155: /* check for buffer empty */ 156: while (buf->pbuf_pt >= buf->buf_len || syncflg) 157: { 158: /* read a new buffer full */ 159: if (buf->hdrstat == LAST_STAT && syncflg >= 0) 160: { 161: goto out; 162: } 163: # ifdef xATR3 164: if (IIdebug > 1) 165: { 166: printf("%s rdng %d w len %d pt %d err %d sf %d\n", 167: proc_name, des, buf->buf_len, buf->pbuf_pt, buf->err_id, syncflg); 168: } 169: # endif 170: i = read(des, buf, HDRSIZ+PBUFSIZ); 171: if (i == 0) 172: { 173: eoj: 174: # ifdef xATR3 175: if (IIdebug > 1) 176: printf("%s rdpipe exit\n", proc_name); 177: # endif 178: if (syncflg < 0) 179: IIsyserr("rdpipe: EOF %d", des); 180: /* exit(end_job(buf, des)); */ 181: exit(-1); 182: } 183: buf->pbuf_pt = 0; 184: chkerr: 185: # ifdef xATR2 186: if (IIdebug > 1) 187: IIprpipe(buf); 188: # endif 189: if (i < HDRSIZ+PBUFSIZ) 190: IIsyserr("rdpipe: rd err buf %u des %d", buf, des); 191: if (buf->hdrstat == SYNC_STAT) 192: { 193: if (syncflg < 0) 194: return (1); 195: else 196: IIsyserr("rdpipe: unexpected SYNC_STAT"); 197: } 198: if (buf->err_id != 0 && syncflg >= 0) 199: { 200: # ifdef xATR2 201: if (IIdebug > 1) 202: printf("%s rdpipe err %d\n", proc_name, buf->err_id); 203: # endif 204: /* proc_error(buf, des); */ 205: /* The error parameters are read here 206: ** and put into an argv, argc structure 207: ** so that the user doesn't have to use 208: ** Ingres utilities to write an intelligent 209: ** error handler. 210: */ 211: ap = args; 212: argc = 0; 213: err = buf->err_id; 214: while (i = IIrdpipe(P_NORM,buf,des,ap,0)) 215: { 216: argv[argc++] = ap; 217: ap += i; 218: if (argc > 10 || (args - ap) >= 500) 219: IIsyserr("Too many error parameters!"); 220: } 221: IIerror(err, argc, argv); 222: # ifdef xATR3 223: if (IIdebug > 1) 224: printf("%s pe ret\n", proc_name); 225: # endif 226: buf->pbuf_pt = buf->buf_len; 227: buf->hdrstat = NORM_STAT; 228: } 229: if (buf->pbuf_pt < 0) 230: { 231: /* P_FUNCID mode */ 232: # ifdef xATR1 233: if (IIdebug > 1) 234: printf("%s rdpipe ret %c\n", 235: proc_name, buf->func_id); 236: # endif 237: return (buf->func_id); 238: } 239: } 240: /* get a byte of information */ 241: msg[knt++] = buf->pbuf[buf->pbuf_pt++]; 242: } while ((n == 0) ? (msg[knt-1]) : (knt < n)); 243: 244: out: 245: # ifdef xATR1 246: if (IIdebug > 1) 247: { 248: printf("%s rdpipe ret %d", proc_name, knt); 249: if (n == 0 && syncflg == 0) 250: printf(", str `%s'", msg); 251: printf("\n"); 252: } 253: # endif 254: return(knt); 255: }