stew@harvard.ARPA (Stew Rubenstein) (03/01/85)
Here is my version of macget and macput for VMS. To unpack this, just cut at the dotted line and execute the remainder of the file as a DCL command procedure. This works under Version 3.* of VMS. It should work under Version 4 as well, but some improvements will be possible; I will post again if there is enough interest. Stew Rubenstein Harvard University Chemical Labs 12 Oxford St. Cambridge, MA 02138 rubenstein@harvard.arpa {ihnp4,seismo,ut-sally}!harvard!rubenstein ------------------------------- Cut Here ----------------------------- $ ! This is a DCL command procedure. Unpack with DCL, not sh! $ COPY SYS$INPUT: 00README.TXT $ DECK/DOLLAR=">> End <<" Here is the VMS version of macget and macput. This program was originally written by Dave Johnson at Brown University, and was modified for VMS and the Vax-11 C compiler by Stewart Rubenstein at Harvard University. It may be used and distributed but not sold for profit. This file should be unpacked by executing it as a command procedure. It will create the files 00README.TXT (this file), MACGET.C, MACGET.HLP, MACGETPUT.H, MACPUT.C, MACPUT.HLP, MAKE.COM, RDT.C and TTYIO.MAR. The command procedure MAKE.C will compile and link both MACGET and MACPUT. Please send comments, bug reports, etc to: Stew Rubenstein rubenstein@harvard.arpa {ihnp4, seismo, ut-sally}!harvard!rubenstein >> End << $ COPY SYS$INPUT: MACGET.C $ DECK/DOLLAR=">> End <<" #include stdio #include signal #include setjmp #include ctype #include "macgetput.h" struct macheader mh; struct filenames files; int mode, txtmode; int pre_beta; /* -o flag; for compatibility with MacTerminal Version -0.15X */ char tmpname[16]; int lastack; char buf[DATABYTES]; /* * macget -- receive file from macintosh using xmodem protocol * Dave Johnson, Brown University Computer Science * Stew Rubenstein, Harvard University Chemical Labs * * (c) 1984 Brown University * (c) 1985 President and Fellows of Harvard College * may be used but not sold without permission * * created ddj 5/22/84 * revised ddj 6/29/84 -- added [-rdu] options * revised ddj 7/16/84 -- protocol changes for MacTerminal Beta Version 0.5X * revised ddj 7/31/84 -- pre-4.2 signal bugs fixed in timedout() * revised sdr 2/28/85 -- Converted to VMS Vax-11 C. */ char usage[] = "usage: \"macget [-o] [-rdu] [filename]\"\n"; main(ac, av) char **av; { char *name; mode = FULL; name = ""; ac--; av++; while (ac) { if (av[0][0] == '-') { switch (av[0][1]) { case 'r': mode = RSRC; break; case 'd': mode = DATA; break; case 'u': mode = TEXT; break; case 'o': pre_beta++; break; default: fprintf(stderr, usage); exit(1); } } else { name = av[0]; } ac--; av++; } setup_tty(); if (send_sync() == ACK) { txtmode = 0; recv_hdr(name); if (mode == TEXT) txtmode++; recv_file(files.f_data, mh.m_datalen, 1); txtmode = 0; recv_file(files.f_rsrc, mh.m_rsrclen, 0); } reset_tty(); } make_name(dest, type, name) /* * Construct a valid VMS file name. */ char *dest, *type, *name; { int i; char *dp, *np; for (dp = dest, np = name; dp - dest < 9 && *np != '\0'; np++) if (isalpha(*np)) *dp++ = *np; *dp++ = '.'; for (np = type, i = 0; i < 3 && *np != '\0'; np++) if (isalpha(*np)) { *dp++ = *np; ++i; } *dp = '\0'; } recv_hdr(name) char *name; { long get4(); int n; FILE *fp; char *np; strcpy(tmpname, TMPNAME); mktemp(tmpname); recv_file(tmpname, (long)DATABYTES, 1); fp = fopen(tmpname, "r"); if (fp == NULL) { perror("temp file"); cleanup(-1); } fread(buf, 1, DATABYTES, fp); fclose(fp); if (name && *name) { n = strlen(name); if (n > NAMEBYTES) n = NAMEBYTES; strncpy(mh.m_name, name, n); mh.m_name[n] = '\0'; } else { n = buf[H_NLENOFF] & BYTEMASK; if (n > NAMEBYTES) n = NAMEBYTES; strncpy(mh.m_name, buf + H_NAMEOFF, n); mh.m_name[n] = '\0'; } for (np = mh.m_name; *np; np++) if (*np == ' ') *np = '_'; if (mode == FULL) { make_name(files.f_info, "info", mh.m_name); rename(tmpname, files.f_info); tmpname[0] = '\0'; make_name(files.f_data, "data", mh.m_name); make_name(files.f_rsrc, "rsrc", mh.m_name); } else { unlink(tmpname); tmpname[0] = '\0'; switch (mode) { case RSRC: strcpy(files.f_data, "_NL:"); make_name(files.f_rsrc, "rsrc", mh.m_name); break; case DATA: make_name(files.f_data, "data", mh.m_name); strcpy(files.f_rsrc, "_NL:"); break; case TEXT: make_name(files.f_data, "text", mh.m_name); strcpy(files.f_rsrc, "_NL:"); break; } } strncpy(mh.m_type, buf + H_TYPEOFF, 4); strncpy(mh.m_author, buf + H_AUTHOFF, 4); if (pre_beta) { mh.m_datalen = get4(buf + H_OLD_DLENOFF); mh.m_rsrclen = get4(buf + H_OLD_RLENOFF); } else { mh.m_datalen = get4(buf + H_DLENOFF); mh.m_rsrclen = get4(buf + H_RLENOFF); mh.m_createtime = get4(buf + H_CTIMOFF); mh.m_modifytime = get4(buf + H_MTIMOFF); } } recv_file(fname, bytes, more) char *fname; long bytes; int more; { register int status, n; FILE *outf; int naks = 0; lastack = 0; outf = fopen(fname, "w"); if (outf == NULL) { perror(fname); cleanup(-1); } for (;;) { status = rec_read(buf, DATABYTES); switch (status) { case EOT: if (!pre_beta) tputc(ACK); if (more) tputc(NAK); fclose(outf); return; case ACK: tputc(ACK); naks = 0; n = (bytes > DATABYTES) ? DATABYTES : bytes; bytes -= n; fwrite(buf, n, 1, outf); break; case DUP: tputc(ACK); naks = 0; break; case NAK: purge(CHRTIMO); if (naks++ < RETRIES) { tputc(NAK); break; } /* fall through */ case CAN: tputc(CAN); fclose(outf); /* unlink fname? */ cleanup(-1); /* NOTREACHED */ } } } send_sync() { int c; for (;;) { c = tgetc(60); switch (c) { case ESC: break; case CAN: case EOT: case TMO: return c; default: continue; } c = tgetc(1); if (c != 'a') continue; tputc(ACK); return ACK; } } rec_read(buf, recsize) char buf[]; int recsize; { int c, rec, rec_bar, cksum; c = tgetc(SOHTIMO); switch (c) { case TMO: default: return NAK; case EOT: return EOT; case CAN: return CAN; case SOH: /* read header */ rec = tgetc(CHRTIMO); if (rec == TMO) return NAK; rec_bar = tgetc(CHRTIMO); if (rec_bar == TMO) return NAK; /* check header */ if (rec != MAXRECNO - rec_bar) return NAK; /* fill buffer */ cksum = tgetrec(buf, recsize, LINTIMO); if (cksum == TMO) return NAK; /* get checksum */ c = tgetc(CHRTIMO); if (c == TMO) return NAK; if (c != (cksum & BYTEMASK)) return NAK; /* check record number */ if (rec == lastack) return DUP; if (rec != ((lastack + 1) & MAXRECNO)) return CAN; else { lastack = rec; return ACK; } } /* NOTREACHED */ } tgetrec(buf, count, timeout) char *buf; int count, timeout; { char *bp; int c, i, cksum; cksum = 0; bp = buf; for (i = 0; i < count; i++) { timed_in(&c, &timeout); if (c < 0) return TMO; cksum += c; if (txtmode && c == '\r') c = '\n'; *(bp++) = c; } return cksum; } tgetc(timeout) int timeout; { int c; timed_in(&c, &timeout); if (c == -1) /* probably hung up or logged off */ return EOT; else return c & BYTEMASK; } tputc(c) char c; { out(&c); purge(); } setup_tty() { int cleanup(); raw_mode(); signal(SIGHUP, cleanup); signal(SIGINT, cleanup); signal(SIGQUIT, cleanup); signal(SIGTERM, cleanup); } cleanup(sig) int sig; { if (tmpname[0] != '\0') unlink(tmpname); reset_tty(); exit(sig); } long get4(bp) char *bp; { register int i; long value = 0; for (i = 0; i < 4; i++) { value <<= 8; value |= (*bp & BYTEMASK); bp++; } return value; } >> End << $ COPY SYS$INPUT: MACGET.HLP $ DECK/DOLLAR=">> End <<" macget - receive file from macintosh via xmodem/macterminal SYNOPSIS macget [ -rdu ] [ -o ] [file] DESCRIPTION Macget receives a file from a Macintosh running MacTerminal. The File Transfer settings should specify the "XModem" transfer method and a "MacTerminal" remote system. This program is designed for use with the 0.5 Beta and newer ver- sions of MacTerminal, but includes a compatibility option for the older -0.15X Almost-Alpha version. The optional file parameter specifies the name to use when creating the unix files, otherwise the Mac file name is used (with spaces converted to underscores). If none of the -rdu flags are specified, macget receives three files from the Mac: file.inf, file.dat, and file.rsr. This mode is useful for storing Mac files so they can be restored later using macput. The -r flag specifies resource mode. Only file.rsr will be created, from the Mac file's resource fork. The -d flag specifies data mode. Only file.dat will be created, containing the data fork of the Mac file. The -u flag requests unix mode, in which carriage returns are converted into unix newline characters, and the unix file file.text is created. Note -- this mode should also be used for VMS text files. The -o flag specifies "old" (version -0.15X) MacTerminal compatibility mode. You must manually disable XON/XOFF flow control in this version to perform file transfer; this is done automatically in the newer versions. AUTHOR Dave Johnson, Brown 7/25/84 >> End << $ COPY SYS$INPUT: MACGETPUT.H $ DECK/DOLLAR=">> End <<" #define TMPNAME "tmp:macXXXXXX" /* Mac time of 00:00:00 GMT, Jan 1, 1970 */ #define TIMEDIFF 0x7c25b080 #define RECORDBYTES 132 #define DATABYTES 128 #define NAMEBYTES 63 #define RETRIES 10 #define SOHTIMO 10 #define LINTIMO 20 #define CHRTIMO 1 #define ACKTIMO 10 #define MAXRECNO 0xff #define BYTEMASK 0xff #define TMO -1 #define DUP '\000' #define SOH '\001' #define EOT '\004' #define ACK '\006' #define NAK '\025' #define CAN '\030' #define EEF '\032' #define ESC '\033' #define H_NLENOFF 1 #define H_NAMEOFF 2 /* 65 <-> 80 is the FInfo structure */ #define H_TYPEOFF 65 #define H_AUTHOFF 69 #define H_LOCKOFF 81 #define H_DLENOFF 83 #define H_RLENOFF 87 #define H_CTIMOFF 91 #define H_MTIMOFF 95 #define H_OLD_DLENOFF 81 #define H_OLD_RLENOFF 85 #define TEXT 0 #define DATA 1 #define RSRC 2 #define FULL 3 /* In VMS version 4, we will be able to do something better. */ #ifdef vax11c # define rename(old, new) # define unlink(file) #else # ifdef NO_RENAME # define rename(old, new) link(old, new); unlink(old) # endif #endif struct macheader { char m_name[NAMEBYTES+1]; char m_type[4]; char m_author[4]; long m_datalen; long m_rsrclen; long m_createtime; long m_modifytime; }; struct filenames { char f_info[256]; char f_data[256]; char f_rsrc[256]; }; >> End << $ COPY SYS$INPUT: MACPUT.C $ DECK/DOLLAR=">> End <<" #include stdio #include signal #include setjmp #include types #include time #include timeb #include "macgetput.h" int mode, txtmode; int pre_beta; /* -o flag; for compatibility with MacTerminal Version -0.15X */ struct macheader mh; struct filenames files; int recno; char buf[DATABYTES]; /* * macput -- send file to macintosh using xmodem protocol * Dave Johnson, Brown University Computer Science * Stew Rubenstein, Harvard University Chemical Labs * * (c) 1984 Brown University * (c) 1985 President and Fellows of Harvard College * may be used but not sold without permission * * created ddj 6/17/84 * revised ddj 7/16/84 -- protocol changes for MacTerminal Beta Version 0.5X * revised ddj 7/31/84 -- pre-4.2 signal bugs fixed in timedout() * revised ddj 7/31/84 -- fixed timeout problem in initial handshake * revised sdr 2/28/85 -- Converted to VMS Vax-11 C */ char usage[] = "usage: \"macput [-o] [-rdu] [-t type] [-a author] [-n name] filename\"\n"; main(ac, av) char **av; { int n; char *filename; if (ac == 1) { fprintf(stderr, usage); exit(1); } mode = FULL; ac--; av++; while (ac) { if (av[0][0] == '-') { switch (av[0][1]) { case 'r': mode = RSRC; strncpy(mh.m_type, "APPL", 4); strncpy(mh.m_author, "CCOM", 4); break; case 'u': mode = TEXT; strncpy(mh.m_type, "TEXT", 4); strncpy(mh.m_author, "MACA", 4); break; case 'd': mode = DATA; strncpy(mh.m_type, "TEXT", 4); strncpy(mh.m_author, "????", 4); break; case 'n': if (ac > 1) { ac--; av++; n = strlen(av[0]); if (n > NAMEBYTES) n = NAMEBYTES; strncpy(mh.m_name, av[0], n); mh.m_name[n] = '\0'; break; } else goto bad_usage; case 't': if (ac > 1) { ac--; av++; strncpy(mh.m_type, av[0], 4); break; } else goto bad_usage; case 'a': if (ac > 1) { ac--; av++; strncpy(mh.m_author, av[0], 4); break; } else goto bad_usage; case 'o': pre_beta++; break; default: bad_usage: fprintf(stderr, usage); exit(1); } } else { filename = av[0]; } ac--; av++; } setup_tty(); find_files(filename, mode); if (mode != FULL) forge_info(); if (send_sync() == ACK) { txtmode = 0; send_file(files.f_info, 1); /* *** Needs to be converted. if (mode != FULL) unlink(files.f_info); */ if (mode == TEXT) txtmode++; send_file(files.f_data, 1); txtmode = 0; send_file(files.f_rsrc, 0); } reset_tty(); } find_files(filename, mode) char *filename; { int n, tdiff, fd, status; struct tm *tp; struct timeb tbuf; time_t mtime; sprintf(files.f_data, "%s.dat", filename); sprintf(files.f_rsrc, "%s.rsr", filename); if (mode == FULL) { sprintf(files.f_info, "%s.inf", filename); if ((fd = open(files.f_info, 0)) < 0) { perror(files.f_info); cleanup(-1); } close(fd); return; } else { strcpy(files.f_info, TMPNAME); mktemp(files.f_info); } if (mode == RSRC) { strcpy(files.f_data, "_NL:"); if ((fd = open(files.f_rsrc, 0)) < 0) { strcpy(files.f_rsrc, filename); if ((fd = open(files.f_rsrc, 0)) < 0) { perror(files.f_rsrc); cleanup(-1); } } mh.m_datalen = 0; mh.m_rsrclen = lseek(fd, 0, 2); close(fd); status = revdate(files.f_rsrc, (char *) 0, &mtime); } else { strcpy(files.f_rsrc, "_NL:"); if ((fd = open(files.f_data, 0)) < 0) { sprintf(files.f_data, "%s.txt", filename); if ((fd = open(files.f_data, 0)) < 0) { strcpy(files.f_data, filename); if ((fd = open(files.f_data, 0)) < 0) { perror(files.f_data); cleanup(-1); } } } mh.m_datalen = lseek(fd, 0, 2); mh.m_rsrclen = 0; close(fd); status = revdate(files.f_data, (char *) 0, &mtime); } if (!pre_beta && status) { ftime(&tbuf); tp = localtime(&tbuf.time); tdiff = TIMEDIFF - tbuf.timezone * 60; if (tp->tm_isdst) tdiff += 60 * 60; mh.m_createtime = mtime + tdiff; mh.m_modifytime = mtime + tdiff; } if (mh.m_name[0] == '\0') { n = strlen(filename); if (n > NAMEBYTES) n = NAMEBYTES; strncpy(mh.m_name, filename, n); mh.m_name[n] = '\0'; } } forge_info() { int n; char *np; FILE *fp; for (np = mh.m_name; *np; np++) if (*np == '_') *np = ' '; buf[H_NLENOFF] = n = np - mh.m_name; strncpy(buf + H_NAMEOFF, mh.m_name, n); strncpy(buf + H_TYPEOFF, mh.m_type, 4); strncpy(buf + H_AUTHOFF, mh.m_author, 4); if (pre_beta) { put4(buf + H_OLD_DLENOFF, mh.m_datalen); put4(buf + H_OLD_RLENOFF, mh.m_rsrclen); } else { put4(buf + H_DLENOFF, mh.m_datalen); put4(buf + H_RLENOFF, mh.m_rsrclen); put4(buf + H_CTIMOFF, mh.m_createtime); put4(buf + H_MTIMOFF, mh.m_modifytime); } fp = fopen(files.f_info, "w"); if (fp == NULL) { perror("temp file"); cleanup(-1); } fwrite(buf, 1, DATABYTES, fp); fclose(fp); } send_sync() { int c, i; for (i = 0; i < 3; i++) { tputc(ESC); tputc('a'); while ((c = tgetc(ACKTIMO)) != TMO) { switch (c) { case CAN: case EOT: case ACK: return c; default: continue; } } fprintf(stderr, "starting handshake timeout\r\n"); } fprintf(stderr, "giving up\r\n"); return CAN; } send_file(fname, more) char *fname; int more; { register int status, i, n; FILE *inf; inf = fopen(fname, "r"); if (inf == NULL) { perror(fname); cleanup(-1); } recno = 1; for (;;) { n = fread(buf, 1, DATABYTES, inf); if (n > 0) { for (i = 0; i < RETRIES; i++) { send_rec(buf, DATABYTES); status = tgetc(ACKTIMO); if (status != NAK) break; } if (status == NAK || status == CAN) { fclose(inf); cleanup(-1); /* NOTREACHED */ } } if (n < DATABYTES) { tputc(EOT); if (!pre_beta) { status = tgetc(ACKTIMO); } if (more) { status = tgetc(ACKTIMO); } return; } recno++; recno &= MAXRECNO; } } send_rec(buf, recsize) char buf[]; int recsize; { int i, cksum; char *bp; cksum = 0; bp = buf; for (i = 0; i < recsize; i++, bp++) { if (txtmode && *bp == '\n') *bp = '\r'; cksum += *bp; } tputc(SOH); tputc((char)recno); tputc((char)(MAXRECNO - recno)); tputrec(buf, recsize); tputc((char)cksum); } tgetc(timeout) int timeout; { int c; timed_in(&c, &timeout); if (c == -1) /* probably hung up or logged off */ return EOT; else return c & BYTEMASK; } tputrec(buf, count) char *buf; int count; { int i, c; for (i = 0; i < count; i++) { c = buf[i]; out(&c); } flush(); } tputc(c) char c; { out(&c); flush(); } setup_tty() { int (*cleanup)(); raw_mode(); signal(SIGHUP, cleanup); signal(SIGINT, cleanup); signal(SIGQUIT, cleanup); signal(SIGTERM, cleanup); } cleanup(sig) int sig; { reset_tty(); exit(sig); } put4(bp, value) char *bp; long value; { register int i, c; for (i = 0; i < 4; i++) { c = (value >> 24) & BYTEMASK; value <<= 8; *bp++ = c; } } >> End << $ COPY SYS$INPUT: MACPUT.HLP $ DECK/DOLLAR=">> End <<" macput - send file to macintosh via modem7/macterminal SYNOPSIS macput file macput [ -rdu ] file [ -t type ] [ -a author ] [ -n name ] DESCRIPTION Macput sends a file to a Macintosh running MacTerminal. The File Transfer settings should specify the "XModem" transfer method and a "MacTerminal" remote system. This program is designed for use with the 0.5 Beta and newer versions of MacTerminal, but includes a compatibility option for the older -0.15X Almost-Alpha version. If none of the -rdu flags are specified, macput sends three files to the mac: file.inf, file.dat, and file.rsr. This is useful for returning files to the mac which were stored using macget. The -r flag specifies resource mode. Either file.rsr or file will be sent to the Mac, along with a forged .inf file and an empty .dat file. The file sent becomes the resource fork of the Mac file. The -d flag specifies data mode. Either file.dat, file.text or file will be sent to the Mac, along with a forged .inf file and an empty .rsr file. The file sent becomes the data fork of the Mac file. The -u flag requests unix mode, which is the same as data mode mode except unix newline characters are converted into carriage returns. This mode should also be used for transferring VMS text files. The -o flag specifies "old" (version -0.15X) MacTerminal compatibility mode. You must manually disable XON/XOFF flow control in this version to perform file transfer; this is done automatically in the newer versions. The remaining options serve to override the default file type, author, and file name to be used on the Mac. The default type and author for resource mode are "APPL" and "CCOM". data mode defaults are "TEXT", "????", and unix mode defaults are "TEXT" and "MACA". BUGS Doesn't work over flow controlled communication lines, or when using rlogin. Doesn't set the bundle bit on resource files, to incorporate any icons into the Desk Top. Use setfile to set the bundle bit. FEATURES Properly initializes the Creation Date. AUTHOR Dave Johnson, Brown 7/25/84 >> End << $ COPY SYS$INPUT: MAKE.COM $ DECK/DOLLAR=">> End <<" $ cc macput, macget, rdt $ macro ttyio $ link macput, rdt, ttyio $ link macget, ttyio >> End << $ COPY SYS$INPUT: RDT.C $ DECK/DOLLAR=">> End <<" #module revdate /* REVDATE(FILE, DFILE, RDT) returns the revision time and date for the specified vms file. FILE is the vms file specification string, DFILE is the default filename string (may be (char *) 0) and RDT is returned with the time in unix format (seconds since 00:00:00, January 1, 1970). The value of the function is 1 if successful, 0 if any errors encountered. (c) Stew Rubenstein, Harvard Chemical Labs, February, 1985 May be used but not sold for profit without written permission from the author. */ #include rms #include types typedef struct { unsigned a : 32; unsigned b : 32; } quad; int revdate(file, dfile, rdt) char *file, *dfile; time_t *rdt; { struct FAB fab; struct RAB rab; struct XABDAT xab; int status; long int hsecs, hnano; fab = cc$rms_fab; rab = cc$rms_rab; xab = cc$rms_xabdat; rab.rab$l_fab = &fab; fab.fab$l_xab = &xab; fab.fab$l_fna = file; fab.fab$b_fns = strlen(file); if (dfile != 0) { fab.fab$l_dna = dfile; fab.fab$b_dns = strlen(dfile); } status = sys$open(&fab); /* vms_to_unix_time(&xab.xab$q_rdt, rdt); */ lib$ediv(&1000000000, &xab.xab$q_rdt, &hsecs, &hnano); hsecs = hsecs - 35067168; /* Number of hundreds of secs from */ /* Nov 17, 1858 to Jan 1, 1970 */ *rdt = hsecs * 100 + hnano / 10000000; if (status == RMS$_NORMAL) status = sys$close(&fab); return status == RMS$_NORMAL; } >> End << $ COPY SYS$INPUT: TTYIO.MAR $ DECK/DOLLAR=">> End <<" .TITLE TTYIO -- Subroutines for simple terminal I/O ; This file supplies seven subroutines for terminal I/O. They are: ; ; IN(character.wl.r) ; Read one character. ; OUT(character.rl.r) ; Write one character (buffered). ; TIMED_IN(character.wl.r, seconds.rl.r) ; Read one character with timeout. If none are available within ; SECONDS seconds, then the value returned is -1. ; PURGE() ; Clean out any characters waiting in the input buffer. ; FLUSH() ; Actually write characters which have been buffered with OUT. ; RAW_MODE() ; Set the terminal to PASSALL mode. ; RESET_TTY() ; Reset the terminal to what it was before calling RAW_MODE. .MACRO MOVDSC SOURCE, DEST MOVAL SOURCE, R0 MOVZBL (R0)+, R1 PUSHL R0 PUSHL R1 MOVL SP, DEST .ENDM .PSECT $LOCAL, PIC, WRT, NOEXE, CON, LONG, NOSHR OUTPTR: .ADDRESS OUTBUF TTIOSB: .BLKL 2 TTYCHN: .BLKW 1 TTMODE: .BLKQ 1 BUFF: .BLKB 10 OUTBUF: .BLKB 256 ENDBUF: DEVNAM: .ASCIC /TT/ .PSECT $CODE NOWRT, EXE, SHR, CON, PIC .ENTRY TIMED_IN, 0 ; SUBROUTINE TIMED_IN(CHAR, TIME) ;++ ; TIMED_IN reads a single character from the grpahics terminal. ; If no such character is available within TIME seconds, -1 is ; returned. ;-- CALLS #0, FLUSH CLRL @4(AP) $QIOW_S CHAN=TTYCHN, - IOSB=TTIOSB, - FUNC=#IO$_READVBLK!IO$M_NOECHO!IO$M_TIMED, - P1=@4(AP), - P2=#1, - P3=@8(AP) CMPW TTIOSB, #SS$_TIMEOUT BNEQ 1$ MCOML #0, @4(AP) 1$: RET .ENTRY PURGE, 0 ; SUBROUTINE PURGE ;++ ; PURGE clears the input buffer of the graphics terminal. ;-- TSTW TTYCHN BNEQ 1$ BSBW GETTRM 1$: $QIOW_S CHAN=TTYCHN, - FUNC=#IO$_READVBLK!IO$M_NOECHO!IO$M_TIMED!IO$M_PURGE, - P1=BUFF, - P2=#1, - P3=#0 RET .ENTRY IN,0 ; SUBROUTINE IN(CHAR) ;++ ; IN reads a single character from the terminal and returns it in CHAR. ;-- CALLS #0, FLUSH $QIOW_S CHAN=TTYCHN, - FUNC=#IO$_READVBLK!IO$M_NOECHO!IO$M_NOFILTR, - P1=@4(AP), - P2=#1 ; CMPB @4(AP), #3 ; Is it a Ctrl-C? ; BEQL 1$ RET ;1$: $Exit_S #1 .ENTRY OUT,0 ; SUBROUTINE OUT(CHAR) ;++ ; OUT writes a single character, CHAR, to the terminal. ; Actually, the characters are buffered locally, and then sent ; out by a call to FLUSH, IN or GETLN. OUT is used for character ; output in graphics mode. ;-- MOVB @4(AP), @OUTPTR INCL OUTPTR MOVAL ENDBUF, R0 CMPL OUTPTR, R0 BNEQ 1$ CALLS #0, FLUSH 1$: RET .ENTRY FLUSH,^M<R2> ; SUBROUTINE FLUSH ;++ ; FLUSH writes out the characters accumulated with OUT to the terminal. ;-- MOVAL OUTBUF, R0 SUBL3 R0, OUTPTR, R2 BEQL 1$ TSTW TTYCHN BNEQ 2$ BSBW GETTRM 2$: $QIOW_S CHAN=TTYCHN, - FUNC=#IO$_WRITEVBLK!IO$M_NOFORMAT, - P1=OUTBUF, - P2=R2 MOVAL OUTBUF, OUTPTR 1$: RET GETTRM: MOVDSC DEVNAM, R2 $ASSIGN_S DEVNAM=(R2), CHAN=TTYCHN BLBS R0, 1$ $EXIT_S R0 1$: ADDL #8, SP RSB .ENTRY RAW_MODE, ^M<R2> ; SUBROUTINE RAW_MODE ;++ ; Puts the terminal in passall mode. ;-- TSTW TTYCHN BNEQ 1$ BSBW GETTRM 1$: $QIOW_S CHAN=TTYCHN, - FUNC=#IO$_SENSEMODE, - P1=TTMODE BISL3 #TT$M_EIGHTBIT!TT$M_PASSALL, TTMODE+4, -(SP) MOVL TTMODE, -(SP) MOVL SP, R2 $QIOW_S CHAN=TTYCHN, - FUNC=#IO$_SETMODE, - P1=(R2) RET .ENTRY RESET_TTY, 0 ; SUBROUTINE RESET_TTY ;++ ; Resets the terminal to the modes in effect before the call to RAW_MODE. ;-- $QIOW_S CHAN=TTYCHN, - FUNC=#IO$_SETMODE, - P1=TTMODE RET .END >> End << $ WRITE SYS$OUTPUT "That's all!" $ EXIT -- ----------------------- Stew Rubenstein UUCP: ihnp4!harvard!stew Harvard Chemistry ARPA: stew@harvard