home *** CD-ROM | disk | FTP | other *** search
- /*
- * Name: MG 2a401 Commodore Amiga file I/O. Last edit: 05-May-88
- * swalton@solar.stanford.edu Next-to-Last edit: 16-Dec-87
- * mic@emx.utexas.edu Created: 23-Jul-86 mic@emx.utexas.edu
- *
- * Read and write ASCII files. All of the low level file I/O knowledge is here.
- * Uses AmigaDOS standard I/O and does its own dynamic buffering; this seems
- * to save about 2K worth of space in the executable image.
- */
-
- #undef LATTICE
- #undef MANX
- #include "compiler.h"
- #include "no_backup.h"
- #include "no_startup.h"
- #include "no_dir.h"
- #include "no_dired.h"
-
- #ifdef LATTICE
- #include <stdlib.h>
- #include <string.h>
- #include <exec/types.h>
- #endif
- #include "use_arp.h"
- #include "foob.h"
- #include <exec/memory.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #ifdef USE_ARP
- #include <arpfunctions.h>
- #include <libraries/arpbase.h>
- #else
- #define FCHARS 32L
- #endif
-
- #ifdef LATTICE
- #include <proto/all.h>
- #else
- #include <functions.h>
- #endif
- #undef TRUE
- #undef FALSE
- #include "def.h"
- #include "line.h"
- #include "buffer.h"
-
- #ifdef ANSI
- #undef EOF
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #endif
-
- #ifndef NO_PROTO
- char *mktemp PROTO((char *));
- #endif
-
- #ifdef LATTICE
- #undef LATTICE
- #include <dos.h>
- #define isdirectory(x) (getfa(x) == 1)
- #endif
-
-
- #define NIOBUF 4096
-
- static VOID FlushBuf PROTO((VOID));
-
- static BPTR ffh = 0;
- static UBYTE *iobuf;
- static int ibufo, niobuf;
- static LONG iostat, access_mode;
- #ifdef MANX
- extern char *strncpy(), *strncat(), *index(), *rindex();
- #endif
-
- #ifdef LATTICE
- static void TackOn(char *path, char *file);
- #define index strchr
- #define rindex strrchr
- #endif
-
- #define getch() (ibufo == niobuf) ? FillBuf() : iobuf[ibufo++]
- #define putch(c) {if (niobuf == NIOBUF) FlushBuf(); iobuf[niobuf++] = c;}
-
- /*
- * Open the Emacs internal file for reading.
- */
- ffropen(fn)
- char *fn;
- {
- if ((iobuf = AllocMem((ULONG) NIOBUF, 0L)) == NULL)
- return (FIOERR);
-
- if ((ffh = Open(fn, access_mode = MODE_OLDFILE)) == 0L) {
- FreeMem(iobuf, (ULONG) NIOBUF);
- return (FIOFNF);
- }
- ibufo = niobuf = 0;
- return (FIOSUC);
- }
-
- /*
- * Open a file for writing. Return TRUE if all is well, and FALSE on error
- * (cannot create).
- */
-
- ffwopen(fn)
- char *fn;
- {
- if ((iobuf = AllocMem((ULONG) NIOBUF, 0L)) == NULL)
- return (FIOERR);
- if ((ffh = Open(fn, access_mode = MODE_NEWFILE)) == 0L) {
- ewprintf("Cannot open file for writing");
- FreeMem(iobuf, (ULONG) NIOBUF);
- return (FIOERR);
- }
- niobuf = 0;
- iostat = NIOBUF; /* pretend we wrote out a full buffer last
- * time */
- return (FIOSUC);
- }
-
- /*
- * Close a file, flushing the output buffer. Should look at the status.
- */
- ffclose()
- {
- if (access_mode == MODE_NEWFILE)
- FlushBuf();
- if (ffh)
- (void) Close(ffh);
- if (iobuf)
- FreeMem(iobuf, (ULONG) NIOBUF);
- return (FIOSUC);
- }
-
- /*
- * Write a buffer to the already opened file. bp points to the buffer. Return
- * the status. Check only at the newline and end of buffer.
- */
- ffputbuf(bp)
- struct buffer *bp;
- {
- register char *cp;
- register char *cpend;
- register struct line *lp;
- register struct line *lpend;
-
- lpend = bp->b_linep;
- lp = lforw(lpend);
- do {
- cp = <ext(lp)[0]; /* begining of line */
- cpend = &cp[llength(lp)]; /* end of line */
- while (cp != cpend)
- putch(*(cp++)); /* putch only evalutes its arg once */
- lp = lforw(lp);
- if (lp == lpend)
- break; /* no implied newline on last line */
- putch('\n');
- } while (iostat > 0L);
-
- if (iostat == -1L) {
- ewprintf("Write I/O error");
- return FIOERR;
- }
- return FIOSUC;
- }
-
- /*
- * Read a line from a file, and store the bytes in the supplied buffer. Stop
- * on end of file or end of line. When FIOEOF is returned, there is a valid
- * line of data without the normally implied \n.
- */
- ffgetline(buf, nbuf, nbytes)
- register char *buf;
- register int nbuf;
- register int *nbytes;
- {
- register int c;
- register int i;
-
- i = 0;
- while ((c = getch()) != EOF && (c & 0xFF) != '\n') {
- buf[i++] = c;
- if (i >= nbuf)
- return FIOLONG;
- }
- if (c == EOF && (iostat == -1L)) {
- ewprintf("File read error");
- return FIOERR;
- }
- *nbytes = i;
- return c == EOF ? FIOEOF : FIOSUC;
- }
-
- #ifndef NO_BACKUP
- #include "backup_suffix.h"
- /*
- * Rename the current file into a backup copy, possibly after deleting the
- * original file.
- */
- fbackupfile(fname)
- char *fname;
- {
- BPTR twiddle, lock;
- char buffer[NFILEN];
-
- if (!fname)
- return FALSE;
- (void) strncpy(buffer, fname, NFILEN - 1);
- (void) strcat(buffer, BACKUP_SUFFIX);
-
- lock = Lock(fname, (ULONG) EXCLUSIVE_LOCK); /* does file exist? */
- if (!lock)
- return (FALSE); /* nope, return error */
-
- twiddle = Lock(buffer, (ULONG) EXCLUSIVE_LOCK);
- if (twiddle) { /* delete old backup */
- UnLock(twiddle);/* let it go */
- if (!DeleteFile(buffer)) {
- UnLock(lock);
- return (FALSE);
- }
- twiddle = NULL;
- }
- /*
- * rename file to backup name (after unlocking the file)
- */
- UnLock(lock);
- return (int) Rename(fname, buffer);
- }
- #endif /* NO_BACKUP */
-
- #ifdef FOOB
- #define DEFAULT_FOOB (0L)
- FOOB
- getfoob(fname)
- char *fname;
- {
- struct FileInfoBlock *fib;
- BPTR lock;
- FOOB out;
-
- if (fname == NULL)
- return DEFAULT_FOOB;
- if ((lock = Lock(fname, ACCESS_READ)) == NULL) /* New file? */
- return DEFAULT_FOOB;
-
- if ((fib = (struct FileInfoBlock *)
- AllocMem(sizeof(struct FileInfoBlock), 0L)) == NULL) {
- ewprintf("Couldn't get %d bytes", sizeof(struct FileInfoBlock));
- UnLock(lock);
- return DEFAULT_FOOB;
- }
- if (Examine(lock, fib))
- out = fib->fib_Protection;
- else {
- ewprintf("Couldn't get protection bits for %s", fname);
- out = DEFAULT_FOOB;
- }
-
- UnLock(lock);
- FreeMem(fib, sizeof(struct FileInfoBlock));
- return out;
-
- }
-
- void
- putfoob(name, mask)
- char *name;
- FOOB mask;
- {
- SetProtection(name, mask & ~FIBF_ARCHIVE);
- }
- #endif
-
- #ifndef NO_STARTUP
- /*
- * Return name of user's startup file. On Amiga, make it .mg in the current
- * directory, then s:mg-startup
- */
-
- static char startname[] = ".mg";
- static char altstartname[] = "s:mg-startup";
-
- char *
- startupfile()
- {
- BPTR lock;
-
- if (lock = Lock(startname, (ULONG) SHARED_LOCK)) {
- UnLock(lock);
- return (startname);
- }
- if (lock = Lock(altstartname, (ULONG) SHARED_LOCK)) { /* alternate */
- UnLock(lock);
- return (altstartname);
- }
- return (NULL);
- }
- #endif /* NO_STARTUP */
-
- /*
- * The string "fn" is a file name. Perform any required name adjustments,
- * including conversion to a fully qualified path if NO_DIR isn't defined.
- */
-
- extern char *MyDirName;
-
- char *
- adjustname(fn)
- register char *fn;
- {
- #ifndef NO_DIR
- static char fnb[MAXPATH];
- BPTR lock;
- unsigned long PathName();
- void TackOn();
- char *dup, *p;
-
- if (!fn)
- return fn;
- if (!index(fn, ':')) { /* no device */
- strcpy(fnb, MyDirName);
- TackOn(fnb, fn);
- if (!index(fn, '/')) /* completely bare name */
- return fnb;
- } else
- strcpy(fnb, fn);
- /*
- * Else fn has some path components in it. We try to PathName the
- * whole thing first, but since the file specified by fn may not
- * exist, we PathName the leading part and TackOn the trailing part
- * if it doesn't.
- */
- if (lock = Lock(fnb, SHARED_LOCK)) {
- if (PathName(lock, fnb, (long) MAXPATH) != 0) {
- UnLock(lock);
- return fnb;
- }
- ewprintf("adjustname: PathName() failed!");
- UnLock(lock);
- return fn;
- }
- if (!(p = rindex(fnb, '/')))
- p = index(fnb, ':');
- p++;
- strcpy((dup = malloc(strlen(p) + 1)), p);
- *p = '\0';
- if (lock = Lock(fnb, SHARED_LOCK)) {
- if (PathName(lock, fnb, (long) MAXPATH) != 0) {
- UnLock(lock);
- TackOn(fnb, dup);
- free(dup);
- return fnb;
- }
- ewprintf("adjustname: PathName() failed!");
- UnLock(lock);
- }
- free(dup);
- #endif
- return fn; /* if all else fails */
- }
-
- /*
- * Functions to read/write into the I/O buffer
- */
-
- VOID
- FlushBuf()
- {
- if (niobuf > 0) {
- iostat = Write(ffh, iobuf, (long) niobuf);
- niobuf = 0;
- }
- }
-
- /*
- * Fill up the input buffer and return the first character in it.
- */
- int
- FillBuf()
- {
- if ((iostat = Read(ffh, iobuf, (long) NIOBUF)) <= 0L)
- return (EOF);
- ibufo = 0;
- niobuf = (int) iostat;
- return (int) (iobuf[ibufo++]);
- }
-
- #ifndef NO_DIRED
-
- #include "kbd.h"
-
- copy(frname, toname)
- char *frname, *toname;
- {
- #ifdef LATTICE
- int error;
- struct ProcID pid;
- if (error = forkl("copy", "copy", frname, toname, NULL, NULL, &pid))
- return error;
- return (int) wait(&pid);
- #else /* MANX (v3.6) or AZTEC (v5.0) */
- return fexecl("copy", "copy", frname, toname, (char *) 0);
- #endif
- }
-
- struct buffer *
- dired_(dirname)
- char *dirname;
- {
- register struct buffer *bp;
- char line[256];
- struct buffer *findbuffer();
- char *tmpname, *mktemp();
- int i;
- VOID lfree();
-
- if ((dirname = adjustname(dirname)) == NULL) {
- ewprintf("Bad directory name");
- return NULL;
- }
- if (!isdirectory(dirname)) {
- ewprintf("Not a directory: %s", dirname);
- return NULL;
- }
- if ((bp = findbuffer(dirname)) == NULL) {
- ewprintf("Could not create buffer");
- return NULL;
- }
- bclear(bp); /* clear out leftover garbage */
- (void) strcpy(line, "list >");
- (void) strncat(line, tmpname = mktemp("ram:mgXXX.XXX"), sizeof(line));
- (void) strncat(line, " \"", sizeof(line));
- (void) strncat(line, dirname, sizeof(line));
- (void) strncat(line, "\"", sizeof(line));
- Execute(line, 0L, 0L);
- if (ffropen(tmpname) != FIOSUC) {
- ewprintf("Can't open temporary dir file");
- return NULL;
- }
- if (ffgetline(line, sizeof(line), &i) != FIOSUC ||
- strncmp(line, "Directory", 9) != 0) {
- ffclose();
- DeleteFile(tmpname);
- ewprintf("No such directory: `%s'", dirname);
- return NULL;
- }
- line[0] = line[1] = ' ';
- while (ffgetline(&line[2], sizeof(line) - 3, &i) == FIOSUC) {
- line[i + 2] = '\0';
- (VOID) addline(bp, line);
- }
- ffclose();
- DeleteFile(tmpname);
- bp->b_dotp = lforw(bp->b_linep); /* go to first line */
- (VOID) strncpy(bp->b_fname, dirname, NFILEN);
- if ((bp->b_modes[0] = name_mode("dired")) == NULL) {
- bp->b_modes[0] = &map_table[0];
- ewprintf("Could not find mode dired");
- return NULL;
- }
- bp->b_nmodes = 0;
- return bp;
- }
-
- #ifndef MANX
- char *
- mktemp(pattern)
- char *pattern;
- {
- /* quick hack mktemp for this purpose only */
- register char *name, *printo;
- register unsigned short counter = 0;
-
- if (!pattern)
- return pattern;
- if ((name = malloc(strlen(pattern) + 5)) == NULL)
- panic("Manx sucks rocks!");
- (VOID) strcpy(name, pattern);
- printo = name + strlen(name);
- do
- (void) sprintf(printo, "%d", counter += 1);
- while (counter > 0 && access(name, 0) == 0);
- if (counter == 0)
- panic("Manx _really_ sucks!");
- return name;
- }
- #endif
-
- #define LIST_LINE_LENGTH 58 /* Size of line from List */
-
- int
- d_makename(lp, fn)
- register struct line *lp;
- register char *fn;
- {
- register char *cp;
- int n = 2;
-
- if (!fn)
- return 0;
- if (llength(lp) < LIST_LINE_LENGTH)
- return ABORT;
- if (lgetc(lp, 2) == ':')
- return ABORT; /* FileNote line */
- (VOID) strcpy(fn, curbp->b_fname);
- cp = fn + strlen(fn);
- if ((cp[-1] != ':') && (cp[-1] != '/')) /* append '/' if needed */
- *cp++ = '/';
- while (lgetc(lp, n) != ' ') {
- *cp++ = lgetc(lp, n);
- n++;
- }
- *cp = '\0';
- return strncmp(&lp->l_text[31], "Dir", 3) == 0;
- }
-
- #ifndef LATTICE
- static
- isdirectory(name)
- char *name;
- {
- long lock;
- struct FileInfoBlock *fib;
- int result;
-
- if ((lock = Lock(name, ACCESS_READ)) == NULL)
- return FALSE;
- if ((fib = (struct FileInfoBlock *)
- AllocMem((long) sizeof(struct FileInfoBlock), MEMF_PUBLIC)) == NULL) {
- UnLock(lock);
- return FALSE;
- }
- result = (fib->fib_DirEntryType > 0L) ? TRUE : FALSE;
- FreeMem(fib, (long) sizeof(struct FileInfoBlock));
- UnLock(lock);
- return result;
- }
- #endif
-
- #endif
-
- #ifndef USE_ARP
-
- /*
- * Here are work-alikes for the few ARP commands now used by the Amiga
- * version of mg. These may go away if we require ARP in future.
- */
-
- #ifndef LATTICE
- /* Changed because sysdef.h defines stricmp to be Strcmp for non-Lattice
- * compilers. This function is required for MANX3.6 and MANX5.0.
- */
- Strcmp(s1, s2)
- register char *s1, *s2;
- {
- while (tolower(*s1) == tolower(*s2)) {
- if (*s1 == '\0')
- return 0;
- s1++;
- s2++;
- }
- return (tolower(*s1) < tolower(*s2) ? -1 : 1);
- }
- #endif
- /*
- * This PathName function shamelessly stolen from the Matt Dillon Shell. It
- * is a slight mod of that program's get_pwd routine, from comm1.c.
- */
- unsigned long
- PathName(flock, pwdstr, n)
- BPTR flock;
- char *pwdstr;
- long n;
- {
- char *name;
- int err = 0;
-
- BPTR lock, newlock;
- struct FileInfoBlock *fib;
- int i, len, nentries;
-
- lock = DupLock(flock);
- nentries = n / FCHARS;
-
- fib = (struct FileInfoBlock *) AllocMem((long) sizeof(struct FileInfoBlock),
- MEMF_PUBLIC);
- pwdstr[i = n - 1] = '\0';
-
- while (lock) {
- newlock = ParentDir(lock);
- if (!Examine(lock, fib))
- ++err;
- name = fib->fib_FileName;
- #ifdef V11 /* Actuall, covers V12 also, but */
- if (*name == '\0') /* HACK TO FIX RAM: DISK BUG */
- name = "RAM";
- #endif
- len = strlen(name);
- if (newlock) {
- if (i == n - 1) {
- i -= len;
- movmem(name, pwdstr + i, len);
- } else {
- i -= len + 1;
- movmem(name, pwdstr + i, len);
- pwdstr[i + len] = '/';
- }
- } else {
- i -= len + 1;
- movmem(name, pwdstr + i, len);
- pwdstr[i + len] = ':';
- }
- UnLock(lock);
- lock = newlock;
- }
- FreeMem(fib, (long) sizeof(struct FileInfoBlock));
- movmem(pwdstr + i, pwdstr, n - i);
- if (err)
- return (0L);
- return ((unsigned long) n - i - 1);
- }
-
- static void
- TackOn(path, file)
- char *path, *file;
- {
- if (*file != '\0') {
- if (path[strlen(path) - 1] != ':')
- strcat(path, "/");
- strcat(path, file);
- }
- }
- #endif
-