This is aosvs.c in view mode; [Download] [Up]
/* * aosvs.c - AOS/VS & MV/UX version of the termio.c module * * The functions in this module deal with the O/S in reading/writing * characters from/to the screen. We also deal with various wiedness things * in dealing with the AOS/VS file system such as ACL's and elementsizes. * This has been written primarily for AOS/VS but should work for MV/UX as * well. No promises though. * * AOS/VS and MV/UX are products of Data General Corporation, Westboro MA. * * Authors: * Daniel Lawrence --- doing MicroEmacs... stuff copied into here... * Douglas Rady ------ most of the rest of the stuff here * Credits: * Michael Meissner -- beating Doug over the head with advice and info. * on AOS/VS "C" compiler. THANK YOU!!!!!!!!!! * Bill Benedetto * & friends ---- beta victims, bug finders/fixers * GNU --------------- inspiration, software tools, clean readable BSD * and USG code examples and interesting comments. * * Definition: uka = Unixly Known As * * Revision/Hack History * MicroEMACS v3.<9p,10> AOS/VS History * * 3.09.16.00 - 3.09.16.09 ??-???-?? dcr * Before written history. Suffice to say that .00 - .04 was just the * AOS/VS port from 3.8z, 3.9e, 3.9i and 3.9n with major cleaning up and * rewriting of the AOS/VS stuff. Sub-revisions 3.09.16.05 - 3.09.16.09 * being optimizations and various fixes. * Yawn... * * 3.09.16.10 25-Aug-88 dcr * Changed do_system_end() in aosvs.c to check for execution of a * macro as basis for not executing an mlreply("Continue") call. * Also fixed stime() in aosvs.c so it just plain worked. * #$&^@*&(+$#!!!! * Also added REPLYNL in estruct.h and made use of CR or NL in the * mlreply() routine in input.c compile time conditional. * * 3.09.16.11 13-Sep-88 dcr * Start of written hisory. This is a momentous event in the course of * AOS/VS MicroEMACS history: doug writes some change doc.!!! Yeah!!! * Changed several functions to force the $builtin version as a trade of * more code size for more speed (usually defaulted to $builtin anyway...). * * 3.09.16.12 14-Sep-88 dcr * Recompiled with revision 4.00 of AOS/VS C. A miracle... * * 3.09.16.13 12-Oct-88 dcr * Changed to have the temporary file for pipecmd() be created in a system * wide temporary file directory known as :TMP, uka /tmp. You paranoids * can create :TMP as a CPD with max. size of 2048 blocks and an ACL of * +,WE and you should be able to relax a nibble. * Creates temp. file with ACL of username,OWAR * * 3.09.16.14 13-Oct-88 dcr * Put in MCA's hack to reduce memory consumption when VIEWing a file. * Modified lalloc() in line.c Test case of paru.h saved 27 2Kb pages. * * 3.10.00.00 09-Nov-88 dcr * Begin code porting for 3.10 BETA. * * 3.10.00.01 20-Dec-88 dcr * Implemented multi-language messages in aosvs.c per 3.10 BETA. * * 3.10.00.02 26-Dec-88 dcr * Tracked down some un-documented runtime optimizations and got * a working version. Also resolved timeset() references. * * 3.10.00.03 17-Jan-89 dcr * Cleaned up for shipping to Dan. Put in some missing code for input.c * * 3.10.00.04 17-Jan-89 dcr * Put in some optimizations regarding TTflush() and ostring() in the * bind.c, input.c and aosvs.c files. This freed 2Kb... but not for long. * * 3.10.00.05 17-Jan-89 dcr * Some memory optimization in exec.c and input.c for small regain. * * 3.10.00.06 - 3.10.00.27 02-Mar-89 - 10-Mar-89 dcr * Various changes. Cleaned up the AOS/VS changes in other modules so * we actually work right. Added conditionals for using either BSD or * USG console i/o (BSD doesn't seem to work). Reclaimed about 4Kb of * memory in various places and made some of these optimizations compile * time conditional. We are still using .890+ ms to start up intead of the * .520+ ms that we took with 3.9p. Not much hope there... but... * Various tweaks here and there. Added the skip of nulls when reading in * a file (most unpleasant results if we don't). Lost some memory to the * USG console i/o stuff. Threw out the BSD console i/o stuff, sigh.... * * 3.10.00.28 10-Mar-89 dcr * Stuck in the aosvs$unix_to_aosvs_path() routine to replace the code * in resolve_pathname(). The new routine does a fairly complete job of * converting Unix(tm) pathnames to AOS/VS format. It also handles the * Ms-Dog '\' path seperator. * * 3.10.00.29 16-Mar-89 dcr * Changed pathname expansion to be invisible to user. Required changes * to fileio.c to #if AOSVS replace the fopen() calls with our xxfopen() * call which does the pathname expansion. Allowed removal of all the * related to the EXPPATH define. Also changed several routines here. * Allows user to reference buffer & file names w/o "unexpanding" the * orginal pathname. * Diff'd & sent to Dan. * */ #nolist #include <stdio.h> /* get the usual */ #list #include "estruct.h" /* get the MicroEMACS stuff */ #ifdef AOSVS | MV_UX /* should this be done? */ #define dashertermdef 1 /* might not be used any more */ #nolist #include "edef.h" /* get the MicroEMACS extern's */ #include "elang.h" #list /* There is no kitchen sink in C so we can't include it. Maybe in C++... */ #nolist #include <paru.h> /* AOS/VS system mnemonics */ #include <sysid.h> /* AOS/VS system call mnemonics */ #include <packets/characteristics.h> /* sys call packet for terminal char.*/ #include <packets/create.h> /* sys call packet to create files */ #include <packets/filestatus.h> /* sys call packet to get file info */ #include <packets/misc.h> /* misc. sys call packets (?SYSPRV) */ /* And now... the Unix(tm) stuff... */ #include <fcntl.h> /* terminal file control stuff */ #include <signal.h> /* the signals... */ #include <termio.h> /* more terminal control stuff */ #list /* Variables!!! Functions!!! Externals!!!! */ struct termio old_in_termio; /* original stdin terminal characteristics */ struct termio new_in_termio; /* stdin characteristics to use inside */ int kbdpoll; /* type ahead polling flag */ int kbdflgs; /* saved keyboard fd flags */ int kbdqp; /* there is a char in kbdq */ char kbdq; /* char we've already read */ /* some D.G. supplied AOS/VS & MV/UX specific functions _toaos_fid() - changes UNIX(tm) pathname to AOS/VS pathname (Thank you!) traceback() - calls the ?SNAP LANG_RT routine for error traceback */ /*extern int _toaos_fid(char*, char* );*/ extern VOID traceback(int ); /* This is how we make an MV/Eclipse accumulator in C with almost all options. */ union accumulator { /* dearly beloved, we are gathered here...*/ unsigned long * ptr; /* pointer to unsigned long (generic) */ char * cptr; /* pointer to char */ unsigned int * pint; /* pointer to unsigned int */ unsigned short *psht; /* pointer to short */ unsigned long ulng; /* unsigned long */ signed long lng; /* signed long */ unsigned int uin; /* unsigned int */ signed int in; /* signed int */ unsigned short usht; /* unsigned short */ unsigned char chr; /* a char, unsigned of course!!! */ } ac0, ac1, ac2; /* our bountiful accumulators, sigh... */ P_CREATE create_pkt; /* file create system call packet */ P_FSTAT fstat_pkt; /* file status system call packet */ char acl_buf[ $MXACL ]; /* ACL buffer, gotta protect things... */ char *crt_eol="\013"; /* Dasher D2xx commands */ char *crt_eop="\014"; /* Dasher D2xx commands */ int dimsts, revsts; int su_mode; /* Superuser mode flag */ #define TLINE_LEN 512 char tline[TLINE_LEN]; /* command line for cli/shell/program calls */ extern VOID do_system(); /* calls the cli/shell/program */ extern VOID do_system_end(); /* cleans up after cli/shell/program calls */ extern VOID init_tline(); /* inits the command line for cli/shell... */ extern VOID ttputs(); extern VOID in_init(); extern FILE *ffp; /* file stream pointer used in fileio.c */ extern int vttidy(); /* MicroEMACS routine to tidy up the screen */ extern int aosvs$expand_pathname(); extern void aosvs$unix_to_aosvs_path(); #endif FILE *STDIN, *STDOUT; /* Needed since the array of files went away.*/ /* Of course, if _iob changes, we'll have to */ /* bend over since we use ->_file in _iob. */ static int mexist; /* is the mouse driver installed? */ static int nbuttons; /* number of buttons on the mouse */ static int oldbut; /* Previous state of mouse buttons */ /*------------------------------------------------------------------------------ * resolve_full_pathname(char*, char*) - resolves a filename or pathname to * full AOS/VS pathname via the ?GRNAME system call. If the file does not * exsist then the current working directory is assumed by AOS/VS. * * Returns FIOSUC if from_path is found or FIOFNF if it isn't found. */ int resolve_full_pathname(from_path, to_path) char *from_path, *to_path; /* resolve "from" pathname "to" pathname */ { if (aosvs$expand_pathname(from_path, to_path)) return(FIOFNF); return(FIOSUC); } /* * ffwopen() - AOS/VS specific version of the ffwopen() routine found in the * fileio.c source. This version will attempt to recreate the edit file * (if it exists) with the existing edit file ACL, elementsize, filetype and * recordsize parameters as determined via a ?FSTAT filestatus system call. * * Returns FIOSUC if file is opened or FIOERR if not opened. */ int ffwopen(bfilnam, sfilnam) char *bfilnam; /* buffer file name */ char *sfilnam; /* save file name or NULL */ { char bfnam[NFILEN], sfnam[NFILEN]; char *tptr; /* some initializations */ zero((char *) &create_pkt, sizeof(create_pkt)); zero((char *) &fstat_pkt, sizeof(fstat_pkt)); zero(acl_buf, $MXACL); strcpy(bfnam, bfilnam); if (sfilnam) { strcpy(sfnam, sfilnam); resolve_full_pathname(sfnam, sfnam); tptr = sfnam; } else { tptr = bfnam; } create_pkt.ctim = -1L; /* take default file creation time */ create_pkt.cacp = -1L; /* take default file creation acl */ create_pkt.cdel = -1L; /* take default file creation elementsize */ create_pkt.cmil = -1L; /* take default file creation max. index levels */ fstat_pkt.stim = -1L; fstat_pkt.sacp = -1L; /* attempt to get full AOS/VS pathname of the file */ if ((resolve_full_pathname(bfnam, bfnam)) == FIOFNF) { /* edit file found? */ /* bfnam not found, create one with default specs. */ create_pkt.cftyp_format = $ORDS; /* data sensitive record type */ create_pkt.cftyp_entry = $FTXT; /* text file type */ ac2.ptr = &create_pkt; ac1.lng = 0L; ac0.cptr = tptr; /* have AOS/VS attempt to create the file */ if (sys($CREATE, &ac0, &ac1, &ac2)) goto fubar; } else { /* bfnam found, get filestatus info. for recreation of bfnam */ ac2.ptr = &fstat_pkt; ac1.lng = 0L; ac0.cptr = bfnam; /* have AOS/VS attempt to get the file information for us */ if (sys($FSTAT, &ac0, &ac1, &ac2)) goto fubar; /* Get ACL of bfnam. If we can't get that then we get the default ACL and use that. */ ac0.cptr = bfnam; ac1.cptr = acl_buf; ac2.lng = 0L; if (sys($GACL, &ac0, &ac1, &ac2)) { /* try to get the file ACL */ /* can't get ACL of file, get default ACL */ ac0.lng = 0L; ac2.lng = 0L; ac1.cptr = acl_buf; sys($DACL, &ac0, &ac1, &ac2); /* try to get user default ACL */ } /* Delete sfnam file. We don't care about any errors on this. */ ac0.cptr = tptr; ac1.lng = 0L; ac2.lng = 0L; sys($DELETE, &ac0, &ac1, &ac2); /* delete it */ /* Set up the packet for the file create system call */ create_pkt.cftyp_format = fstat_pkt.styp_format; /* file format */ create_pkt.cftyp_entry = fstat_pkt.styp_type; /* file type */ create_pkt.ccps = fstat_pkt.scps; /* recordsize, if any */ create_pkt.cacp = acl_buf; /* acl buffer ptr */ create_pkt.cdeh = fstat_pkt.sdeh; /* element size */ create_pkt.cmil = fstat_pkt.smil; /* max. index level */ /* Make system call to create a file with supplied specs. */ ac2.ptr = &create_pkt; ac0.cptr = tptr; ac1.lng = 0L; if (sys($CREATE, &ac0, &ac1, &ac2)) /* attempt file create */ goto fubar; } if ((ffp = fopen(tptr, "a")) == NULL) goto fubar; #if ISADIR if (isadirectory(ffp)) { /* check to see if file is a directory */ mlwrite(TEXT216); /* bitch... */ ffclose(ffp); /* yes, close it and get out!!! */ return(FIOERR); /* actual checking code in O/S modules */ } #endif return(FIOSUC); /* Common error exit for all ffwopen() errors */ fubar: mlwrite(TEXT155); /* mlwrite("Cannot open file for writing");*/ return(FIOERR); } /* * unlink() - delete a file - called from writeout() in file.c * * This routine replaces the DG supplied unlink() since we don't use the * link() unlink() combination to rename files. Saves some memory. * */ int unlink(del_fnam) char *del_fnam; /* name of file to delete */ { char dtmp[NFILEN]; strcpy(dtmp, del_fnam); resolve_full_pathname(dtmp, dtmp); ac0.cptr = dtmp; ac1.lng = 0L; ac2.lng = 0L; if (sys($DELETE, &ac0, &ac1, &ac2)) /* attempt to delete it */ return(-1); /* normal error return */ return(0); /* normal okay return */ } /* * rename() - rename a file - called from writeout() in file.c */ int rename(from_nam, to_nam) char *from_nam; /* rename from name */ char *to_nam; /* rename to name */ { char ftmp[NFILEN], ttmp[NFILEN]; /* First we convert Unix(tm) or Ms-dog paths to Aos/Vs paths. Second we strip the actual filename from the "to" path by going to the end of the string and working our way backward until we find a pathname seperator which under AOS/VS is a colon (:). */ strcpy(ftmp, from_nam); strcpy(ttmp, to_nam); resolve_full_pathname(ftmp, ftmp); resolve_full_pathname(ttmp, ttmp); ac1.cptr = ttmp + (sizeof(char) * strlen(ttmp)); while ((ac1.cptr >= ttmp) && (*ac1.cptr != ':') && (*ac1.cptr != '=')) --ac1.cptr; ++ac1.cptr; /* move pointer from seperator to 1st char in filename */ ac0.cptr = ftmp; ac2.lng = 0L; if (sys($RENAME, &ac0, &ac1, &ac2)) /* attempt the rename */ return(-1); /* oops!!! */ return(0); /* okay... */ } /* * This function gets called just before we go back home to the command * interpreter. */ VOID ttclose() { fflush(stdout); fflush(stdin); ioctl(STDIN->_file, TCSETA, &old_in_termio); /* restore terminal settings */ fcntl(STDIN->_file, F_SETFL, kbdflgs); } /* * Write a character to the display. */ #if TTPUTC == 0 VOID ttputc(c) { putc(c, stdout); } #endif /* * Flush terminal buffer. Does real work where the terminal output is buffered * up. A no-operation on systems where byte at a time terminal I/O is done. */ #if TTFLUSH == 0 VOID ttflush() { fflush(stdout); } #endif unsigned int extcode(c) unsigned int c; { if ((c == 1 || c == 8 || c == 17 || c == 23) || (c >= 24 && c <=26) || (c >= 32 && c <= 110) || (c >= 112 && c <= 126)) /* 111 is mouse */ return((c & 255) | SPEC); return(c & 255); } /* input buffers and pointers */ #define IBUFSIZE 64 /* this must be a power of 2 */ unsigned char in_buf[IBUFSIZE]; /* input character buffer */ int in_next = 0; /* pos to retrieve next input character */ int in_last = 0; /* pos to place most recent input character */ VOID in_init() /* initialize the input buffer */ { in_next = in_last = 0; } int in_check() /* is the input buffer non-empty? */ { if (in_next == in_last) return(FALSE); else return(TRUE); } VOID in_put(event) int event; /* event to enter into the input buffer */ { in_buf[in_last++] = event; in_last &= (IBUFSIZE - 1); } int in_get() /* get an event from the input buffer */ { register int event; /* event to return */ event = in_buf[in_next++]; in_next &= (IBUFSIZE - 1); return(event); } #if MOUSE int checkmouse() { register int k; /* current bit/button of mouse */ register int event; /* encoded mouse event */ int newbut; /* new state of the mouse buttons */ int mousecol; /* current mouse column */ int mouserow; /* current mouse row */ int sstate; /* current shift key status */ /* check to see if any mouse buttons are different */ /* rg.x.ax = 3;*/ /* Get button status and mouse position */ /* int86(0x33, &rg, &rg);*/ /* newbut = rg.x.bx;*/ /* mousecol = rg.x.cx >> 3;*/ mouserow = rg.x.dx >> 3; /* get the shift key status as well */ sstate = 0; /* rg.h.ah = 2;*/ /* return current shift status */ /* int86(0x16, &rg, &rg);*/ /* sstate = rg.h.al;*/ for (k=1; k != (1 << nbuttons); k = k<<1) { /* For each button on the mouse */ if ((oldbut&k) != (newbut&k)) { /* This button changed, generate an event */ in_put(0); in_put(MOUS >> 8); in_put(mousecol); in_put(mouserow); event = ((newbut&k) ? 0 : 1); /* up or down? */ if (k == 2) /* center button? */ event += 4; if (k == 4) /* right button? */ event += 2; if (sstate & 3) /* shifted */ event += 'A'; else if (sstate & 4) /* controled? */ event += 1; else event += 'a'; /* plain */ in_put(event); oldbut = newbut; return(TRUE); } } return(FALSE); } #endif int doschar() { /* USG - SysV console i/o - From "C Users Journal", April 1989, Vol. 7, # 9 */ if(kbdqp) /* any typeahead known? */ kbdqp = FALSE; /* yes, clear flag & return typeahead char */ else { /* no typeahead. */ if (fcntl(STDIN->_file, F_SETFL, kbdflgs) < 0 && kbdpoll) return(FALSE); kbdpoll = FALSE; read(STDIN->_file, &kbdq, 1); /* wait and get a char */ } if (kbdq == '\036') { /* D.G. Dasher CRT function key lead-in? */ in_put(SPEC >> 8); /* ??? stash in the keyboard buffer stuff ??? */ return(0); } return (kbdq & 255); } /* * Read a character from the terminal, performing no editing and doing no echo * at all. */ int ttgetc() { /* return any keystrokes waiting in the type ahead buffer */ ttc: if (in_check()) return(in_get()); if (typahead()) return(doschar()); /* with no mouse, this is a simple get char routine */ if (mexist == FALSE || mouseflag == FALSE) return(doschar()); #if MOUSE /* turn the mouse cursor on */ /* rg.x.ax = 1;*/ /* Show Cursor */ /* int86(0x33, &rg, &rg);*/ /* loop waiting for something to happen */ while (TRUE) { if (typahead()) break; if (checkmouse()) break; } /* turn the mouse cursor back off */ /* rg.x.ax = 2;*/ /* Hide Cursor */ /* int86(0x33, &rg, &rg);*/ goto ttc: #endif /* MOUSE */ } #if TYPEAH /* typahead: Check to see if any characters are already in the keyboard buffer. Hurray for kludges!!! */ int typahead() { /* USG - SysV console i/o - From "C Users Journal", April 1989, Vol. 7, # 9 */ if (!kbdqp) { if (fcntl(STDIN->_file, F_SETFL, (kbdflgs | O_NDELAY)) < 0 && kbdpoll) return(FALSE); kbdpoll = TRUE; kbdqp = (1 == read(STDIN->_file, &kbdq, 1)); } return(kbdqp); } #endif /* TYPEAH */ /* Spawn: various DOS access commands for MicroEMACS ver 3.9e */ /* * Create a subjob with a copy of the command intrepreter in it. When the * command interpreter exits, mark the screen as garbage so that you do a full * repaint. Bound to "^X C". */ int spawncli(f, n) { register char *cp; /* don't allow this command if restricted */ if (restflag) return(resterr()); #if MV_UX TTflush(); TTclose(); /* stty to old settings */ if ((cp = getenv("SHELL")) != NULL && *cp != '\0') system(cp); else system("exec /bin/sh"); #endif #if AOSVS init_tline(); strcat(tline,"CHAIN/1=AB/2=AB,:CLI,EMACS_SET_CLI_PREFIX"); do_system(); #endif sleep(2); return(TRUE); } /* * Run a one-liner in a subjob. When the command returns, wait for a single * character to be typed, then mark the screen as garbage so a full repaint is * done. Bound to "C-X !". */ int spawn(f, n) { register int s; char line[NLINE]; /* don't allow this command if restricted */ if (restflag) return(resterr()); if ((s=mlreply("!", line, NLINE)) != TRUE) return (s); init_tline(); strcat(tline,line); do_system(); do_system_end(); return (TRUE); } /* * Run an external program with arguments. When it returns, wait for a single * character to be typed, then mark the screen as garbage so a full repaint is * done. Bound to "C-X $". */ int execprg(f, n) { register int s; char line[NLINE]; /* don't allow this command if restricted */ if (restflag) return(resterr()); if ((s=mlreply("!", line, NLINE)) != TRUE) return (s); strcpy(tline, line); do_system(); do_system_end(); return (TRUE); } /* * Pipe a one line command into a window * Bound to ^X @ * * This command REQUIRES a directory named :TMP or a link by that name to * another directory such as :SL_TEMPS. This diectory should have an * ACL of +,RWE which will allow all users to access it. This diectory is * where the output file for this command is placed. This was done because * the sons of MircoEMACS do not always have the same privileges. The file * is of the pathname :TMP:pid.MICRO_EMACS_COMMAND where "pid" is the PID * of the MicroEMACS process. Also note that this sort of follows the UNIX(tm) * convention for a common temporary file directory. * The temp. file is created with an ACL of username,OWAR * * See the THINGS_TO_DO.TXT for planned enhancements in this area. * */ int pipecmd(f, n) { register int s; /* return status from CLI */ register WINDOW *wp; /* pointer to new window */ register BUFFER *bp; /* pointer to buffer to zot */ char line[NLINE]; /* command line send to shell */ const char pipecmd_bname[] = "command"; char pipecmd_filnam[NFILEN] = ":tmp:"; /* must be AOS/VS format!!!! */ /* don't allow this command if restricted */ if (restflag) return(resterr()); /* get the users pid and build a pathname for our scratch file */ ac0.ulng = 0L; ac2.ulng = 0L; ac1.ulng = -1L; sys($PNAME, &ac0, &ac1, &ac2); /* get our PID */ itoa(ac1.in, line); strcat(pipecmd_filnam, line); /* build temp. filename */ strcat(pipecmd_filnam, ".micro_emacs_command"); zero((char *) &create_pkt, sizeof(create_pkt)); zero(acl_buf, $MXACL); ac2.cptr = &acl_buf; ac0.ulng = -1L; ac1.ulng = -1L; sys($GUNM, &ac0, &ac1, &ac2); /* get our user name */ ac0.cptr = &acl_buf[strlen(acl_buf)]; ac0.cptr++; *ac0.cptr = ($FACO | $FACW | $FACA | $FACR); /* specify the ACL */ ac0.cptr++; *ac0.cptr = '\000'; create_pkt.cacp = &acl_buf; /* load addr of temp file ACL */ create_pkt.ctim = -1L; create_pkt.cdel = -1L; create_pkt.cmil = -1L; create_pkt.cftyp_format = $ORDS; /* data sensitive */ create_pkt.cftyp_entry = $FTXT; /* TEXT file type */ ac2.ptr = &create_pkt; ac1.lng = 0L; ac0.cptr = &pipecmd_filnam; sys($CREATE, &ac0, &ac1, &ac2); /* have AOS/VS create the temp file */ /* get the command to pipe in */ if ((s=mlreply("@", line, NLINE)) != TRUE) return(s); /* get rid of the command output buffer if it exists */ if ((bp=bfind(pipecmd_bname, FALSE, 0)) != FALSE) { /* try to make sure we are off screen */ wp = wheadp; while (wp) { if (wp->w_bufp == bp) { onlywind(FALSE, 1); break; } wp = wp->w_wndp; } if (zotbuf(bp) != TRUE) return(FALSE); } s = 0; /* init. index into line */ init_tline(); strcat(tline,"LISTFILE,"); /* give CLI an @LIST to use */ strcat(tline,pipecmd_filnam); /* tack on the filename for @LIST */ strcat(tline,";"); /* separate the commands */ s = strpbrk(line,",; \t"); /* check for cmd line delimiters */ if (s) { /* find any? */ strncat(tline,line,(s-(int) &line));/* get whats before the delimeter*/ strcat(tline,"/L"); /* tack on "use @LIST file" switch */ strcat(tline,s); /* get the rest of the cmd line */ } else { /* no delimiers... */ strcat(tline,line); /* get the cmd line */ strcat(tline,"/L"); /* tack on "use @LIST file" switch*/ } strcat(tline,";BYE/L=@NULL"); /* tell CLI to die quietly */ do_system(); s = TRUE; /* split the current window to make room for the command output */ if (splitwind(FALSE, 1) == FALSE) goto fubar; /* and read the stuff in */ if (getfile(pipecmd_filnam, FALSE) == FALSE) goto fubar; /* make this window in VIEW mode, update all mode lines */ curwp->w_bufp->b_mode |= MDVIEW; wp = wheadp; while (wp) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } /* and get rid of the temporary file */ unlink(pipecmd_filnam); return(TRUE); fubar: unlink(pipecmd_filnam); return(FALSE); } /* * filter a buffer through an external DOS program * Bound to ^X # */ int filter(f, n) { mlwrite(TEXT217); /* mlwrite("[Not available yet under AOS/VS]");*/ sleep(1); return(FALSE); } /* return a system dependant string with the current time original version didn't work. modified idea of bill benedetto by doug rady. note the use of sys($ITIME, ...) instead of sys_itime() */ char *PASCAL NEAR timeset() { register char *sp; /* temp string pointer */ short int tvec[2]; extern char *dg_ctime(); ac0.ulng = 0L; ac1.ulng = 0L; ac2.ulng = 0L; sys($ITIME, &ac0, &ac1, &ac2); /* get system time */ tvec[0] = ac2.in; ac1.lng /= 32768L; tvec[1] = (int)(ac1.lng/2L); sp = dg_ctime(tvec); sp[ strlen(sp)-1 ] = NULL; return(sp); } VOID init_tline() { extern char *curdir(); tline[0] = '\000'; strcat(tline, "DIR,"); curdir(&tline[4]); strcat(tline, ";"); return; } VOID do_system() { movecursor(term.t_nrow, 0); /* Seek to last line. */ mlerase(); TTclose(); /* stty to old modes */ system(tline); TTkopen(); sgarbf = TRUE; } VOID do_system_end() { int s; if (clexec == TRUE) { mlputs(TEXT188); /* mlputs("[End]");*/ TTflush(); while ((s = tgetc()) != '\r' && s != ' ') ; } return; } /* Data General AOS/VS terminal handling routines Known types are: DASHER D2xx/4xx series - support primarily for D2xx series written by Doug Rady (based on ANSI.C and VMSVT.C) */ extern VOID ttopen(); extern VOID ttkopen(); extern VOID ttkclose(); extern VOID tteeol(); extern VOID tteeop(); extern VOID ttbeep(); extern VOID dashermove(); extern VOID ansimove(); extern VOID dasherrev(); extern VOID ansirev(); extern int ttcres(); #if COLOR extern VOID ttfcol(); extern VOID ttbcol(); #endif extern VOID dasherdim(); extern VOID ansidim(); extern VOID spal(); #define NROWS 24 /* normal # of screen rows */ #define MXROWS 24 /* max # of screen rows */ #define NCOLS 80 /* normal mode # of screen columns*/ #define MXCOLS 135 /* wide mode # of screen columns*/ #define MARGIN 4 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define NPAUSE 100 /* # times thru update to pause */ #define ESC 0x16 #define BEL 7 /* * Dispatch table. All the * hard fields just point into the * terminal I/O code. */ noshare TERM term = { MXROWS -1, NROWS -1, MXCOLS, NCOLS, MARGIN, SCRSIZ, NPAUSE, &ttopen, &ttclose, &ttkopen, &ttkclose, &ttgetc, #if TTPUTC == 0 &ttputc, #endif #if TTFLUSH == 0 &ttflush, #endif &dashermove, &tteeol, &tteeop, &ttbeep, &dasherrev, &ttcres, &dasherdim, #if COLOR &ttfcol, &ttbcol #endif }; /* dashermove - Move the cursor for DG Dasher */ VOID dashermove(row, col) { TTputc('\020'); TTputc(col); TTputc(row); } /* ansimove - Move the cursor for ANSI crt */ VOID ansimove(row, col) int row, col; { char rc_tmp[ 8 ]; ++row; ++col; ttputs("\033["); itoa(row, rc_tmp); ttputs(rc_tmp); TTputc(';'); itoa(col, rc_tmp); ttputs(rc_tmp); TTputc('H'); } /* * dasherrev - set the reverse video status for DG Dasher */ VOID dasherrev(status) int status; /* TRUE = reverse video, FALSE = normal video */ { if (status) ttputs("\036\104"); else ttputs("\036\105"); } /* * ansirev- set the reverse video status for ANSI crt */ VOID ansirev(status) int status; { if (dimsts) { if (status) { ttputs("\033[0;2;7m"); } else { ttputs("\033[0;2m"); } } else { if (status) { ttputs("\033[0;7m"); } else { ttputs("\033[0m"); } } if (status) revsts = TRUE; else revsts = FALSE; } /* * dasherdim - set the dim/bright video status for DG Dasher */ VOID dasherdim(status) int status; /* TRUE = dim video, FALSE = bright video */ { if (status) TTputc('\034'); else TTputc('\035'); } /* * ansidim - set the dim/bright video status for ANSI crt */ VOID ansidim(status) int status; { if (revsts) { if (status) { ttputs("\033[0;2;7m"); } else { ttputs("\033[0;7m"); } } else { if (status) { ttputs("\033[0;2m"); } else { ttputs("\033[0m"); } } if (status) dimsts = TRUE; else dimsts = FALSE; } /* ttcres - Change screen resolution (what resolution?) */ int ttcres() { return(TRUE); } VOID spal() /* change palette string */ { /* Does nothing here */ } #if COLOR /* ttfcol - Set the forground color (not implimented) */ VOID ttfcol() { } /* ttbcol - Set the background color (not implimented) */ VOID ttbcol() { } #endif /* COLOR */ /* tteeol - Erase to end of line */ VOID tteeol() { ttputs(crt_eol); } /* tteeop - Erase to end of page (clear screen) */ VOID tteeop() { ttputs(crt_eop); } /* ttbeep - Ring the bell */ VOID ttbeep() { TTputc('\007'); } VOID ttputs(str) char *str; { while(*str) { putc(*str, stdout); str++; } } /* ttopen() - open the terminal and change characteristics for our use */ VOID ttopen() { int sys_err; P_CHAR_EX crt_info; /* for ?GECHR system call */ /* set some traps */ signal(SIGTRAP, &traceback); signal(SIGIOT, &traceback); signal(SIGILL, &traceback); signal(SIGSEGV, &traceback); signal(SIGTERM, &traceback); /* signal(SIGINT, &traceback);*/ signal(SIGQUIT, &traceback); signal(SIGEMT, &traceback); signal(SIGFPE, &traceback); signal(SIGKILL, &traceback); signal(SIGBUS, &traceback); signal(SIGSYS, &traceback); signal(SIGTERM, &traceback); ac0.in = fchannel(stdout); /* make sure it is opened */ ac0.in = fchannel(stdin); /* make sure it is opened */ ac1.ulng = (BIT0 | (sizeof(crt_info)/2)); /* get characteristics flag */ ac2.ptr = (unsigned long*) &crt_info; sys_err = sys($GECHR, &ac0, &ac1, &ac2); /* ?GECHR system call */ /* copy the actual stdio pointer macro values into pointers */ STDIN = stdin; STDOUT = stdout; /* set LPP & CPL in case they aren't == defaults - idea from bill benedetto resetting the max. row value is condtional because some of us can display more than LPP lines on a screen. */ term.t_ncol = (short)crt_info.char_cpl; /* get CPL */ term.t_nrow = ((short)crt_info.char_lpp -1);/* get LPP */ if (term.t_nrow > term.t_mrow) /* only reset max. row if LPP is > */ term.t_mrow = term.t_nrow; /* default max. row */ #if XXCRT if (termcode == 0) { /* CRT type given on command line? */ /* nope, we must figure it out */ } switch (termcode) { case 0: /* Generic ANSI compliant */ crt_eol = "\033[K"; crt_eop = "\033[J"; term.t_move = &ansimove; term.t_rev = &ansirev; term.t_dim = &ansidim; /* term.t_getkey = &ansigetkey; */ break; case 1: /* DEC VT100 */ case 2: /* DEC VT100K */ crt_eol = "\033[K"; crt_eop = "\033[J"; term.t_move = &ansimove; term.t_rev = &ansirev; term.t_dim = &ansidim; /* term.t_getkey = &vt100getkey; */ break; case 4: /* DEC VT102 */ case 5: /* DEC VT102K */ crt_eol = "\033[K"; crt_eop = "\033[J"; term.t_move = &ansimove; term.t_rev = &ansirev; term.t_dim = &ansidim; crt_func = (INS_CHAR | INS_LINE | DEL_CHAR | DEL_LINE); /* term.t_getkey = &vt100getkey; */ break; case 7: /* DEC VT220 */ case 8: /* DEC VT220K */ crt_eol = "\033[K"; crt_eop = "\033[J"; term.t_move = &ansimove; term.t_rev = &ansirev; term.t_dim = &ansidim; /* term.t_getkey = &vt220getkey; */ break; case 6: /* D.G. Dasher D4xx */ crt_func = (INS_CHAR | INS_LINE | DEL_CHAR | DEL_LINE); break; case 3: /* D.G. Dasher D2xx */ default; } #else if ((crt_info.char_cdt != char_d2xx) /* is not CRT3 or D2xx ? and */ && (crt_info.char_cdt != char_d4xx)) { /* is not CRT6 or D4xx or D5xx ? */ crt_eol = "\033[K"; crt_eop = "\033[J"; term.t_move = &ansimove; term.t_rev = &ansirev; term.t_dim = &ansidim; } #endif /* XXCRT */ /* change terminal charactersitcs to Unix(tm) raw mode */ ioctl(STDIN->_file, TCGETA, &old_in_termio); /* save old settings */ new_in_termio.c_iflag = 0; /* setup new settings */ new_in_termio.c_oflag = 0; new_in_termio.c_lflag = 0; new_in_termio.c_cc[VTIME] = 0; new_in_termio.c_cc[VMIN] = 1; new_in_termio.c_line = BELL_LD; /* emulate unix(tm) line handling */ new_in_termio.c_cflag = old_in_termio.c_cflag; ioctl(STDIN->_file, TCSETA, &new_in_termio); kbdflgs = fcntl(STDIN->_file, F_GETFL, 0); dimsts = 0; revsts = 0; /* check for mouse here */ mexist = 0; nbuttons = 0; oldbut = 0; /* on all screens we are not sure of the initial position of the cursor */ ttrow = 999; ttcol = 999; /* assume terminal has following */ eolexist = TRUE; revexist = TRUE; strcpy(sres, "NORMAL"); /* here we lower the priority of this task so that the console reader task will always get control when we get a char. */ ac0.ulng = 0L; /* will get TID of this task */ ac1.ulng = 0L; /* will get task pri. this task */ ac2.ulng = 0L; /* who knows... */ sys($MYTID, &ac0, &ac1, &ac2); ac1.ulng = 100L; /* new task priority */ ac2.ulng = 0L; /* must be zero... */ sys($IDPRI, &ac1, &ac0, &ac2); /* do it!!! */ } /* open the keyboard */ VOID ttkopen() { /* activate the MircoEmacs console characteristics */ ioctl(STDIN->_file, TCSETA, &new_in_termio); fcntl(STDIN->_file, F_SETFL, kbdflgs); kbdqp = 0; kbdpoll = FALSE; kbdq = '\000'; in_init(); } VOID ttkclose() { } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif /* Change the current working directory */ PASCAL NEAR int chdirectory() { #if CHDIR /* include this code? */ /* don't allow this command if restricted */ if (restflag) return(resterr()); if ((ac0.in = mlreply("Directory: ", tline, NLINE)) != TRUE) return(ac0.in); ac0.in = chdir(tline); /* change the current working directory */ /* tell the story... success or failure */ if (ac0.in) { mlwrite("Error- directory not changed."); return(ac0.in); } else { mlwrite("Directory changed."); return(TRUE); } #endif } #if ORMDNI /* superuser on/off toggle routines to override those annoying ACLs usage: superuser_on(); or superuser_off(); */ int superuser_on() { int err; if (restflag) return(resterr()); ac0.lng = -1L; ac1.ulng = 0L; ac2.ulng = 0L; err = 0; if ((err = sys($SUSER, &ac0, &ac1, &ac2))) if (err = ERPRV) mlwrite("Error: you are not allowed use of superuser."); else mlwrite("Error turning superuser ON."); return(err); } int superuser_off() { int err; if (restflag) return(resterr()); ac0.ulng = 1L; ac1.ulng = 0L; ac2.ulng = 0L; err = 0; if ((err = sys($SUSER, &ac0, &ac1, &ac2))) mlwrite("Error turning superuser OFF."); return(err); } #endif #if ISADIR int isadirectory(fstream) FILE *fstream; { return(isadir(fstream->_file)); } #endif /****************************************************************************/ /* */ /* */ /* All aosvs$ library routines Copyright (c) 1989 by Douglas C. Rady */ /* */ /* */ /****************************************************************************/ /* aosvs$bsd_dir.h -- a replacement inlcude file under AOS/VS for: <dir.h> -- definitions for 4.2BSD-compatible directory access Taken from GNU's emacs/etc/ndir.h for porting GNU stuff to AOS/VS. All of the usual fields are defined but dd_buf is defined as a char* so we can pass a poniter to a template under AOS/VS. */ #ifndef DIRSIZ struct direct { /* data from readdir() */ long d_ino; /* inode number of entry */ unsigned short d_reclen; /* length of this record */ unsigned short d_namlen; /* length of string in d_name */ char d_name[$MXFN]; /* name of file */ }; #endif typedef struct { int dd_fd; /* file desc. - channel# under aos/vs */ int dd_loc; /* offset in block */ int dd_size; /* amount of valid data */ char *dd_buf; /* pointer to wildcard/template */ } DIR; /* stream data from opendir() */ /* set up the MV/Eclipse accumulators used by the aosvs$ routines */ $align(1) $low32k union aosvs$accumulator { /* dearly beloved, we are gathered here...*/ unsigned long * ptr; /* pointer to unsigned long */ char * cptr; /* pointer to char */ unsigned int * pint; /* pointer to unsigned int */ unsigned short *psht; /* pointer to short */ unsigned long ulng; /* unsigned long */ signed long lng; /* signed long */ unsigned int uin; /* unsigned int */ signed int in; /* signed int */ unsigned short usht; /* unsigned short */ unsigned char chr; /* a char, unsigned of course!!! */ } aosvs$ac0, aosvs$ac1, aosvs$ac2; /* our bountiful accumulators, sigh... */ /* aosvs$bsd_dir.c -- fake 4.2BSD directory access routines for AOS/VS System call city... */ P_GNFN aosvs$bsd_gnfn_pkt; /* aosvs$bsd_closedir */ void closedir(dir_stream) /* $name("aosvs$bsd_closedir") */ DIR *dir_stream; { aosvs$ac0.ulng = 0L; aosvs$ac2.ulng = 0L; aosvs$ac1.in = dir_stream->dd_fd; /* load channel number */ sys($GCLOSE, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2); } /* aosvs$bsd_opendir */ DIR *opendir(dir_name) /* name$("aosvs$bsd_opendir") */ char *dir_name; { #include "packets/block_io.h" P_GOPEN gopen_pkt; DIR *dir_stream; int err; char t_name[$MXPL]; err = 0; dir_stream = (DIR *) malloc(sizeof(DIR)); zero((char *) dir_stream, sizeof(DIR)); zero((char *) &aosvs$bsd_gnfn_pkt, sizeof(aosvs$bsd_gnfn_pkt)); zero((char *) &gopen_pkt, sizeof(gopen_pkt)); err = aosvs$expand_pathname(dir_name, t_name); aosvs$ac0.cptr = t_name; aosvs$ac1.lng = -1L; aosvs$ac2.ptr = &gopen_pkt; /* Try to ?GOPEN the file. */ if (err = sys($GOPEN, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2)) { free(dir_stream); /* Error Will Robinson! Error! Error! */ return(NULL); } /* Make sure it is some type of directory! */ if ((gopen_pkt.opty_type != $FDIR) && (gopen_pkt.opty_type != $FLDU) && (gopen_pkt.opty_type != $FCPD)) { /* AOS/VS 7.62 directory types. */ dir_stream->dd_fd = (int)gopen_pkt.opch; closedir(dir_stream); free(dir_stream); /* Error Will Robinson! Error! Error! */ return(NULL); } dir_stream->dd_fd = (int)gopen_pkt.opch; /* stash the channel number */ return(dir_stream); } /* aosvs$bsd_readdir */ struct direct *readdir(dir_stream) /* name$("aosvs$bsd_readdir") */ DIR *dir_stream; { struct direct *dptr; dptr = NULL; aosvs$ac0.in = 0; aosvs$ac1.in = dir_stream->dd_fd; /* load channel number */ dptr = (struct direct *) malloc(sizeof(struct direct)); zero((char *)dptr, sizeof(struct direct)); if (dir_stream->dd_loc) aosvs$bsd_gnfn_pkt.nfky = (short)dir_stream->dd_loc; else aosvs$bsd_gnfn_pkt.nfky = 0; if (dir_stream->dd_buf) /* if passed a template */ aosvs$bsd_gnfn_pkt.nftp = dir_stream->dd_buf; /* load it into packet */ else aosvs$bsd_gnfn_pkt.nftp = (char *) -1L; /* load default flag */ aosvs$bsd_gnfn_pkt.nfnm = dptr->d_name; /* load buffer ptr */ aosvs$ac2.ptr = &aosvs$bsd_gnfn_pkt; if (sys($GNFN, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2) == 0) { /* save the AOS/VS internal pointer */ dir_stream->dd_loc = (int) aosvs$bsd_gnfn_pkt.nfky; /* load the direct struct values */ dptr->d_ino = (long) aosvs$bsd_gnfn_pkt.nfky; /* fake an inode */ dptr->d_reclen = sizeof(struct direct); /* why? why not? */ dptr->d_namlen = strlen(dptr->d_name); /* handy to have */ return(dptr); } free(dptr); return(NULL); } /* aosvs$bsd_seekdir */ void seekdir(dir_stream, pos) /* name$("aosvs$bsd_seekdir") */ DIR *dir_stream; long pos; { dir_stream->dd_loc = (short)pos; } /* aosvs$bsd_telldir */ long telldir(dir_stream) /* name$("aosvs$bsd_telldir") */ DIR *dir_stream; { return(dir_stream->dd_loc); } /* aosvs$unix_to_aosvs_path.c -- convert a Unix(tm) pathname to a Aos/Vs pathname We also accept the Ms-Dos '\' seperator and convert it to the Unix(tm) '/' seperator. We do not deal with Ms-Dos device specifiers. The '\' is handled since most current Ms-Dos C compilers can deal with either '\' or '/'. usage: aosvs$unix_to_aosvs(u_path, a_path); where: data item name data type description ----------------------- ------------------ ----------------------------------- u_path char * char * of Unix(tm) pathname, end with null. a_path char * char * for Aos/Vs pathname, MUST be $MXPL in length. ------------------------------------------------------------------------------- edit history who mm/dd/yy rev # what..................................................... --- -------- ----- --------------------------------------------------------- dcr 01/27/89 01.00 birth, new life, creation... dcr 03/02/89 01.01 cleaned up, added internal temp. storage for path. dcr 03/02/89 01.02 added code to deal with Ms-Dog '\' seperator. dcr 03/02/89 01.03 added code to skip out if first char is legal Aos/Vs char. This makes us "just like" _toaos_fid(). */ void aosvs$unix_to_aosvs_path(u_path, a_path) char *u_path, *a_path; { extern int _toaos_fid(); /* Data General library routine */ /* local variables */ register char *up, *ap; register int dec1; char t_path[$MXPL], octal[4]; /* check for null ptrs... no tricks here please... */ if ((u_path == NULL) || (a_path == NULL)) return; /* copy to register vars. */ up = u_path; /* load ptr to Unix(tm) path */ ap = t_path; /* load ptr to temp. storage area */ zero(t_path, $MXPL); /* zero the temp. storage area */ /* to be "just like" DG's _toaos_fid() we skip out if the first char. is a legal Aos/Vs seperator. This is from page 2-1 of the "Using Specialized C Functions" manual, DG part number 093-000585-00. */ if ((*up == '^') || (*up == '@') || (*up == '=') || (*up == ':')) { strcpy(a_path, u_path); return; } /* step through the unix(tm) pathname and copy or translate bytes into the temp. storage area. */ while (*up) { /* better be NULL terminated!!! */ if ((*up == '$') || (*up == '?') || (*up == '\\') || (*up == '_') || ((*up >= '.') && (*up <= ':')) /* thank you ASCII */ || ((*up >= 'A') && (*up <= 'Z')) || ((*up >= 'a') && (*up <= 'z'))) { if (*up == '\\') { /* convert ms-dos '\' to unix(tm) '/' */ *ap++ = '/'; up++; continue; } *ap++ = *up++; continue; } dec1 = 0; zero(octal, 4); *ap++ = '?'; /* marker for octal replacement */ dec1 = (int)*up; otoa(dec1, octal); if (dec1 < 64) *ap++ = '0'; strcat(ap, octal); if (dec1 >= 64) ap++; ap++; ap++; up++; } *ap = NULL; /* go home... */ _toaos_fid(t_path, a_path); return; } /* aosvs$expand_pathname.c usage: err = aosvs$expand_pathname(c_path, x_path); where: data item name data type description ----------------------- ------------------ ----------------------------------- err int Error return, if any. c_path char * Current pathname. x_path char * Expanded pathname returned here. This must be at least $MXPL bytes. ------------------------------------------------------------------------------- edit history who mm/dd/yy rev # what..................................................... --- -------- ----- --------------------------------------------------------- dcr 03/02/89 01.00 birth, new life, creation... */ /* aosvs$expand_pathname.c usage: err = aosvs$expand_pathname(c_path, x_path); where: data item name data type description ----------------------- ------------------ ----------------------------------- err int Error return, if any. c_path char * Current pathname. x_path char * Expanded pathname returned here. This must be at least $MXPL bytes. ------------------------------------------------------------------------------- edit history who mm/dd/yy rev # what..................................................... --- -------- ----- --------------------------------------------------------- dcr 03/02/89 01.00 birth, new life, creation... */ int aosvs$expand_pathname(c_path, x_path) char *c_path, *x_path; { /* local variables */ char t_path[$MXPL]; /* things to do... */ zero(t_path, $MXPL); aosvs$unix_to_aosvs_path(c_path, t_path); aosvs$ac2.in = $MXPL; aosvs$ac0.cptr = t_path; aosvs$ac1.cptr = x_path; if (sys($GRNAME, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2)) if ((aosvs$ac0.in == ERFDE) || (aosvs$ac0.in == ERFDE)) strcpy(x_path, t_path); else return(1); return(0); } extern DIR *opendir(); extern struct direct *readdir(); extern long telldir(); extern void seekdir(); extern void closedir(); #define rewinddir( dirp ) seekdir( dirp, 0L ) #if COMPLET /* FILE Directory routines */ char gnfntmp[NFILEN]; /* wildcard template */ char gnfnpath[NFILEN]; /* path of file to find */ char gnfnrbuf[NFILEN]; /* return file buffer */ DIR *gnfndir; struct direct *gnfndirect; char PASCAL NEAR *getnfile(); /* do a template directory search (for file name completion) */ char *PASCAL NEAR getffile(fspec) char *fspec; /* pattern to match */ { register int index; /* index into various strings */ /* clean up from our last time in here... */ if (gnfndir) { closedir(gnfndir); free(gnfndir); } if (gnfndirect) free(gnfndirect); /* init. some things... */ zero(gnfnpath, NFILEN); zero(gnfnrbuf, NFILEN); zero(gnfntmp, NFILEN); gnfndir = NULL; gnfndirect = NULL; /* first parse the file path off the file spec */ strcpy(gnfnpath, fspec); index = strlen(gnfnpath) - 1; while (index >= 0 && (gnfnpath[index] != '/' && gnfnpath[index] != '\\' && gnfnpath[index] != ':')) --index; gnfnpath[index+1] = 0; if ((gnfndir = opendir(gnfnpath)) == NULL) return(NULL); /* build the wildcard or template to use in the lookup */ strcpy(gnfntmp, &fspec[index+1]); strcat(gnfntmp, "+"); gnfndir->dd_buf = gnfntmp; return(getnfile()); } char *PASCAL NEAR getnfile() { register int index; /* index into various strings */ zero(gnfnrbuf, NFILEN); /* init return buffer */ /* and call for the next file */ if ((gnfndirect = readdir(gnfndir)) == NULL) { closedir(gnfndir); free(gnfndir); gnfndir = NULL; return(NULL); } /* return the next file name! */ strcpy(gnfnrbuf, gnfnpath); strcat(gnfnrbuf, gnfndirect->d_name); mklower(gnfnrbuf); free(gnfndirect); gnfndirect = NULL; return(gnfnrbuf); } #else char *PASCAL NEAR getffile(fspec) char *fspec; /* file to match */ { return(NULL); } char *PASCAL NEAR getnfile() { return(NULL); } #endif FILE *xxfopen(fn, mode) /* expand a pathname and open it */ char *fn, *mode; { char tmppath[NFILEN]; /* temp. to hold expanded pathname */ strcpy(tmppath, fn); /* load passed pathname */ resolve_full_pathname(tmppath, tmppath); /* expand it... */ return(fopen(tmppath, mode)); /* try to open expanded pathname */ } #endif /* AOSVS */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.