1: /* 2: * VMODEM 3: * VMS support for UMODEM and vvrb/vvsb programs 4: * 5: * Defined herein are some utility routines to make the UNIX 6: * program UMODEM run under VAX/VMS C: 7: * 8: * assign_channel Calls the VMS System Service $ASSIGN 9: * to assign a channel to a device. 10: * The routine currently has the device 11: * "TT" hardwired into it. 12: * gtty Gets terminal characteristics, almost 13: * like the UNIX GTTY system call. 14: * raw_read Reads characters from the terminal 15: * without any echoing or interpretation 16: * and with an optional timeout period. 17: * raw_write Writes a character to the terminal 18: * without any interpretation. 19: * raw_wbuf Writes a buffer to the terminal 20: * without any interpretation. 21: * stty Sets terminal characteristics, almost 22: * like the UNIX STTY system call. 23: * 24: * Some of the ideas used here were obtained from code written 25: * by Max Benson and Robert Bruccoleri. 26: * 27: * Walter Reiher 28: * Harvard University 29: * Department of Chemistry 30: * 12 Oxford Street 31: * Cambridge, MA 02138 32: * March 11, 1983 33: * 34: * Modified 4-20-88 Chuck Forsberg, Omen Technology INC 35: * 17505-V NW Sauvie IS RD Portland OR 97231 omen!caf 36: * Added primitives for for ZMODEM use. 37: */ 38: #include descrip 39: #include iodef 40: #include rms 41: #include ssdef 42: #include stdio 43: #include "vmodem.h" 44: 45: #define TRUE 1 46: #define FALSE 0 47: 48: static char tt_name[] = "TT"; 49: static short tt_chan = -1; /* Terminal channel number */ 50: 51: struct tt_io_iosb /* Terminal I/O IOSB */ 52: { 53: short status; 54: short byte_count; 55: short terminator; 56: short terminator_size; 57: }; 58: 59: 60: struct tt_io_tacf /* Terminal I/O type ahead */ 61: { 62: short byte_count; 63: char firstchar; 64: char something; 65: short whatever; 66: }; 67: 68: /* 69: * Terminator mask for PASSALL reads. 70: * Permits reads of all possible 8-bit characters. 71: */ 72: int t_mask[32] = { 73: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76: 0, 0 }; 77: 78: struct terminator_mask { 79: short size ; 80: short unused ; 81: int *mask ; 82: } 83: 84: termin_mask = { 32, 0, t_mask }; 85: 86: /* 87: * ASSIGN a channel to the logical name TT, which is usually 88: * the terminal. 89: */ 90: assign_channel() 91: { 92: int status; 93: $DESCRIPTOR(tt_descriptor, tt_name); 94: 95: if (tt_chan == -1) 96: status = sys$assign(&tt_descriptor, &tt_chan, 0, 0); 97: else 98: status = SS$_NORMAL; 99: 100: if (status != SS$_NORMAL || tt_chan == -1) 101: fatal("ASSIGN_CHANNEL: error in SYS$ASSIGN\n"); 102: 103: return; 104: } 105: 106: /* 107: * Gets terminal information from VMS. 108: */ 109: gtty(tt_characteristics) 110: struct tt_info *tt_characteristics; 111: { 112: int c; 113: int status; 114: extern unsigned Baudrate; 115: int speeds[] = { 2400, 50, 75, 110, 134, 150, 300, 600, 1200, 1800, 116: 2000, 2400, 3600, 4800, 7200, 9600, 19200 }; 117: 118: if (tt_chan == -1) 119: assign_channel(); 120: 121: status = sys$qiow(0, tt_chan, IO$_SENSEMODE, 122: &(tt_characteristics->dev_modes), NULL, 0, 123: &(tt_characteristics->dev_characteristics), 12, 124: 0, 0, 0, 0); 125: if (status != SS$_NORMAL || 126: tt_characteristics->dev_modes.status != SS$_NORMAL) 127: fatal("GTTY: sense mode QIO error return.\n"); 128: 129: c = tt_characteristics->dev_modes.t_speed % 17; 130: Baudrate = speeds[c]; 131: 132: return(status); 133: } 134: 135: /* 136: * Return the number of characters waiting in TTY input buffer 137: */ 138: rdchk() 139: { 140: int status; 141: struct tt_io_iosb iosb; 142: struct tt_io_tacf typeahead; 143: 144: status = sys$qiow(0, tt_chan, IO$_SENSEMODE|IO$M_TYPEAHDCNT, 145: &iosb, NULL, 0, 146: &typeahead, 0, 147: 0, 0, 0, 0); 148: 149: return(typeahead.byte_count); 150: } 151: 152: /* 153: * Read NCHAR characters from the terminal without echoing or 154: * interpretation. 155: * If the argument SECONDS is non-zero, use that as the 156: * timeout period in seconds for the read. 157: * 158: * Returns SS$_TIMEOUT in case of timeout or other error. 159: * Otherwise, returns the number of characters read. 160: */ 161: raw_read(nchar, charbuf, seconds) 162: char *charbuf; 163: int nchar; 164: unsigned seconds; 165: { 166: short function; 167: int status; 168: struct tt_io_iosb iosb; 169: 170: if (tt_chan == -1) 171: assign_channel(); 172: 173: function = IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR; 174: 175: if (seconds) 176: status = sys$qiow(0, tt_chan, function | IO$M_TIMED, 177: &iosb, NULL, 0, 178: charbuf, nchar, seconds, 179: &termin_mask, NULL, 0); 180: else 181: status = sys$qiow(0, tt_chan, function, 182: &iosb, NULL, 0, 183: charbuf, nchar, 0, 184: &termin_mask, NULL, 0); 185: 186: if (iosb.byte_count) 187: return iosb.byte_count; 188: return SS$_TIMEOUT; 189: } 190: 191: /* 192: * Writes a character to the terminal without echoing or 193: * interpretation. 194: */ 195: raw_write(c) 196: char c; 197: { 198: int status; 199: struct tt_io_iosb iosb; 200: 201: if (tt_chan == -1) 202: assign_channel(); 203: 204: status = sys$qiow(0, tt_chan, 205: IO$_WRITEVBLK | IO$M_CANCTRLO | IO$M_NOFORMAT, 206: &iosb, NULL, 0, 207: &c, 1, 0, 0, 0, 0); 208: 209: if (status != SS$_NORMAL || iosb.status != SS$_NORMAL) 210: fatal("RAW_WRITE: write QIO error return.\n"); 211: 212: return; 213: } 214: 215: /* 216: * Writes a buffer to the terminal without echoing or 217: * interpretation. 218: */ 219: raw_wbuf(nchar, charbuf) 220: char *charbuf; 221: int nchar; 222: { 223: int status; 224: struct tt_io_iosb iosb; 225: 226: if (tt_chan == -1) 227: assign_channel(); 228: 229: status = sys$qiow(0, tt_chan, 230: IO$_WRITEVBLK | IO$M_CANCTRLO | IO$M_NOFORMAT, 231: &iosb, NULL, 0, 232: charbuf, nchar, 0, 0, 0, 0); 233: 234: if (status != SS$_NORMAL || iosb.status != SS$_NORMAL) 235: fatal("RAW_WRITE: write QIO error return.\n"); 236: 237: return; 238: } 239: 240: /* 241: * Sets terminal information from VMS. 242: * Modified 12-85 Larry Farr/Chuck Forsberg to not use 243: * bad parity returned by VMS 4. 244: */ 245: stty(tt_characteristics) 246: struct tt_info *tt_characteristics; 247: { 248: short *f_ptr, /* *p_ptr, */ *s_ptr; 249: int status; 250: struct tt_mode_iosb iosb; 251: 252: if (tt_chan == -1) 253: assign_channel(); 254: 255: /* 256: * We do the following in order to get a full short, concatenating 257: * two adjacent chars: 258: */ 259: s_ptr = &(tt_characteristics->dev_modes.t_speed); /* Speeds */ 260: f_ptr = &(tt_characteristics->dev_modes.CR_fill); /* Fills */ 261: /* p_ptr = &(tt_characteristics->dev_modes.parity_flags); */ 262: 263: status = sys$qiow(0, tt_chan, IO$_SETMODE, 264: &iosb, NULL, 0, 265: &(tt_characteristics->dev_characteristics), 12, 266: /* *s_ptr, *f_ptr, *p_ptr, 0); */ 267: *s_ptr, *f_ptr, 0, 0); 268: if (status != SS$_NORMAL || iosb.status != SS$_NORMAL) 269: printf("STTY: set mode QIO returned %d\n", status); 270: 271: return(status); 272: }