home *** CD-ROM | disk | FTP | other *** search
- #include "jam.h"
- /*
- * Name: Mg 2a
- * MSDOS file I/O (TurboC 1.5)
- */
- #include <stdlib.h>
- #include <string.h>
-
- #ifdef SomeUnix /* hack, really UNIX but .... */
- # include "unistd.h"
- #endif
-
- #ifdef FAT /* DOS filesystem stuff */
- # include <io.h>
- # include <direct.h>
- extern BOOL no_write_cr; /* JAM */
- #endif
-
- #include "def.h"
- #include "keyname.h"
- #include <stdio.h>
- #include "kbd.h"
-
- static FILE *ffp;
- static BOOL doencrypt = FALSE;
- static void rn_(evalEnv, (char *src, char *dest));
-
- void setencryptstate(flag)
- BOOL flag;
- {
- #ifdef DOCRYPT
- doencrypt = flag;
- #endif
- }
- /*
- * Open a file for reading.
- */
- ffropen(fn)
- char *fn;
- {
- if ((ffp=fopen(fn, "rb")) == NULL)
- return (FIOFNF);
- return (FIOSUC);
- }
-
- /*
- * Open a file for writing.
- * Return TRUE if all is well, and
- * FALSE on error (cannot create).
- */
- ffwopen(fn)
- char *fn;
- {
- if ((ffp=fopen(fn, "wb")) == NULL) {
- ewprintf("Cannot open file for writing");
- return (FIOERR);
- }
- return (FIOSUC);
- }
-
- /*
- * Close a file.
- * Should look at the status.
- */
- ffclose()
- {
- (VOID) fclose(ffp);
- return (FIOSUC);
- }
-
- /*
- * Write a line to the already
- * opened file. The "buf" points to the
- * buffer, and the "nbuf" is its length, less
- * the free newline. Return the status.
- * Check only at the newline.
- */
- ffputline(buf, nbuf)
- register char buf[];
- int nbuf;
- {
- register int i;
- char c;
-
- for (i=0; i<nbuf; ++i)
- {
- c = (char)(buf[i] & 0xFF);
- #ifdef DOCRYPT
- if (doencrypt)
- docrypt(&c, 1);
- #endif
- putc(c, ffp);
- }
-
- #ifdef FAT
- if (!no_write_cr)
- putc('\r', ffp);
- #endif
- putc('\n', ffp);
- if (ferror(ffp) != FALSE) {
- ewprintf("Write I/O error");
- return (FIOERR);
- }
- 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)
- BUFFER *bp;
- {
- register char *cp;
- char c;
- register char *cpend;
- register LINE *lp;
- register LINE *lpend;
- register int count;
-
- lpend = bp->b_linep;
- lp = lforw(lpend);
- do {
- extern BOOL clearLineChange;
-
- if (clearLineChange)
- changelineflag(lp, FALSE);
-
- cp = <ext(lp)[0]; /* begining of line */
- cpend = &cp[llength(lp)]; /* end of line */
- count = 0;
- while(cp != cpend) {
- c = *cp++;
- #ifdef DOCRYPT
- if (doencrypt)
- docrypt(&c, 1);
- #endif
- putc(c, ffp);
- count++;
- }
- lp = lforw(lp);
-
- if(lp == lpend) /* no implied newline on last line */
- {
- break;
- }
-
- #ifdef FAT
- if (!no_write_cr)
- putc('\r', ffp);
- #endif
- putc('\n', ffp);
- } while(!ferror(ffp));
-
- if(ferror(ffp)) {
- 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. Don't get upset by files that don't have an end of
- * line on the last line; this seem to be common on CP/M-86 and
- * MS-DOS. Delete any CR followed by a NL: This is the normal
- * format for MS_DOS files, but also occurs when files are transferred
- * from VMS or MS-DOS to Unix.
- */
- ffgetline(buf, nbuf, nbytes)
- register char buf[];
- int nbuf;
- register int *nbytes;
- {
- register int c;
- register int i;
- char cc;
-
- i = 0;
- for (;;) {
- c = getc(ffp);
- rescan:
- if (c == '\r') { /* Delete any non-stray */
- c = getc(ffp); /* carriage returns. */
- if (c != '\n') {
- buf[i++] = '\r';
- if (i >= nbuf)
- return FIOLONG;
- goto rescan;
- }
- }
- if (c==EOF || c==(char)'\n') /* End of line. */
- break;
- cc = (char)c;
- #ifdef DOCRYPT
- if (doencrypt)
- docrypt(&cc, 1);
- #endif
- buf[i++] = (char)cc;
- if (i >= nbuf)
- return FIOLONG;
- }
- if (c == EOF && ferror(ffp) != FALSE) {
- ewprintf("File read error");
- return FIOERR;
- }
- *nbytes = i;
- return c==EOF ? FIOEOF : FIOSUC;
- }
-
- /*
- * Rename the file "fname" into a backup copy.
- * On Unix the backup has the same name as the
- * original file, with a "~" on the end - unfortunately
- * this does not map well to MS-DOS - the old .bak convention
- * is used.
- */
- fbackupfile(fname)
- char *fname;
- {
- register char *nname, *ptr;
- char *strchr();
- char *bak = ".bak";
-
- /* copy the name, allocating enough space for
- * backup extension and trailing NULL
- */
- if ((nname=malloc(strlen(fname)+strlen(bak)+1)) == NULL)
- return (ABORT);
- (void) strcpy(nname, fname);
- #ifdef FAT
- if ((ptr = strchr(nname, '.')) != 0)
- strcpy(ptr, bak);
- else
- #endif
- strcat(nname, bak);
- if (strcmp(fname, nname) == 0) {
- free(nname);
- return FALSE;
- }
- #ifdef FAT
- (void) unlink(nname); /* Ignore errors. */
- (void) rename(fname, nname);
- #else /* unix land, cp to backup name to preserve softlinked 'originals' */
- {
- char *cmd;
- static char *cpstr = "cp %s %s";
-
- cmd = malloc(strlen(cpstr) + strlen(fname) + strlen(nname) + 10);
- sprintf(cmd, cpstr, fname, nname);
- system(cmd);
- free(cmd);
- }
- #endif
- free(nname);
- return (TRUE);
- }
-
- /*
- * The string "fn" is a file name.
- * convert all filenames to lower case, and convert all '\\' characters
- * to forward slashes. This is simply my preference, uppercase and
- * back slashes are also viable.
- */
- /*ARGSUSED*/
- adjustnamecase(fn)
- register char *fn;
- {
- #ifdef FAT /* only OS currently supported which doesn't care */
- register char c;
-
- while ((c = *fn) != '\0') {
- if (ISUPPER(c))
- *fn = (char)TOLOWER(c);
- if (c=='/')
- *fn = BDC1;
- ++fn;
- }
- #endif
- return TRUE;
- }
-
-
- /*
- * Check first in startup directory, then local work dir, then
- * check env variable (order is probably wrong...)
- */
- char *startupfile(path)
- char *path;
- {
- register char *home = homedir;
- static char name[NFILEN];
- char thename[NFILEN];
- register int i;
- #define EXT ".st"
- BOOL success = FALSE;
-
- /* build start file name
- */
- #ifdef WINDOWED
- strcpy(thename, g_APPNAME);
- #else
- strcpy(thename, AppName);
- #endif
- strcat(thename, EXT);
- for (i = 0; thename[i]; i++)
- if (ISUPPER(thename[i]))
- thename[i] = (char)TOLOWER(thename[i]);
-
- /* file in home dir?
- */
- if (!success && home && *home)
- {
- name[0] = '\0';
- strcpy(name, home);
- i = strlen(name);
-
- if (i && (name[i-1] != BDC1))
- name[i++] = BDC1;
- name[i] = 0;
-
- strcat(name, thename);
- if (access(name, F_OK) == 0)
- success = TRUE;
- }
-
- /* file in startup dir?
- */
- if (!success && path)
- {
- strcpy(name, path);
- strcat(name, thename);
- if (access(name, F_OK) == 0)
- success = TRUE;
- }
-
- /* file in current dir?
- */
- if (!success && (access(thename, F_OK) == 0))
- {
- strcpy(name, thename);
- success = TRUE;
- }
-
- if (success)
- return (name);
- return NULL;
- }
-
-
- /*******************************************************************/
- /* new stuff between release 1a and 2a */
- /*******************************************************************/
-
- /* convert all filenames to a canonical format, which in the case of
- * MSDOS is X:/currentdir/filename. Note that each drive letter has
- * it's OWN current directory, so if the user specifies a drive letter,
- * we use that drive's current directory, not it's root.
- */
-
- /* MSC doesn't have getdrive and getcurdir routines; simulate them.
- * They are both pretty gross. Blame Microsoft
- *
- * (code moved to dos.c - JAM)
- */
-
- /* This DOS version of this code already does the right thing
- * for constructing full pathnames from partial ones; I need to
- * do special ughly stuff for UN*X systems, especially since I
- * add incremental saves and path preloading... JAM
- *
- * Note that this code does not check for overflow!
- */
- char *adjustname(fn)
- register char *fn;
- {
- register char *cp;
- #ifdef FAT
- static char fnb[NFILEN * 2];
-
- cp = fnb;
- /* handle A:foo\bar */
- if (fn[0] && fn[1] == ':') {
- *cp++ = *fn++;
- *cp++ = *fn++;
- *cp = '\0';
- adjustnamecase(fnb); /* force case to lower */
-
- if (*fn != '/' && *fn != BDC1) {
- *cp++ = BDC1;
- getcurdir((unsigned short)(fnb[0]-'a'+1), cp);
- cp = fnb + strlen(fnb);
- }
- else
- *cp++ = *fn++;
- }
- /* handle \foo\bar */
- else if (*fn == '/' || *fn == BDC1) {
- *cp++ = (char) (getdisk() + 'a');
- *cp++ = ':';
- *cp++ = BDC1; fn++;
- }
- else {
- strcpy(fnb, wdir);
- cp = fnb + strlen(fnb);
- }
-
- if(cp != fnb && cp[-1] != '/' && cp[-1] != BDC1)
- *cp++ = BDC1;
-
- /* at this point, we should have a drive, and at least a single */
- /* slash. Now copy over the rest of the filename, while handling */
- /* certain pathalogical cases */
-
- /* convert "//" to "/", "/./" to "/", and "/x/../" to "/" */
- while(*fn) {
- switch(*fn) {
- case '.':
- switch(fn[1]) {
- case '\0':
- *--cp = '\0';
- adjustnamecase(fnb);
- return fnb;
- case BDC1:
- fn += 2;
- continue;
- case '.':
- if(fn[2]=='/' || fn[2]==BDC1 || fn[2] == '\0') {
- --cp;
- while(cp > fnb && *--cp != '/' && *cp != BDC1)
- ;
- if (cp==fnb) cp += 2;
- ++cp;
- if(fn[2]=='\0') {
- *--cp = '\0';
- adjustnamecase(fnb);
- return fnb;
- }
- fn += 3;
- continue;
- }
- break;
- default:
- break;
- }
- break;
- case '/':
- case BDC1:
- fn++;
- continue;
- default:
- break;
- }
- while(*fn && (*cp++ = *fn++) != '/' && fn[-1] != BDC1)
- ;
- }
- if (cp != fnb + 3 && cp[-1]==BDC1)
- --cp;
- *cp = '\0';
- #else /* assuming UN*X here... */
- static char fnb[NFILEN * 2];
-
- if ((fn[0] == '~') && homedir && *homedir)
- {
- strcpy(fnb, homedir);
- strcat(fnb, &fn[1]); /* assuming ~/foo so / already there */
- }
- else if (fn[0] == '$') /* env variable */
- evalEnv(fn, fnb);
- else if (fn[0] == BDC1) /* full path assumed! */
- strcpy(fnb, fn);
- else
- {
- BUFFER temp;
- char buf[NFILEN];
- int i;
-
- memset(&temp, 0, sizeof(BUFFER));
- strcpy(temp.b_fname, fn); /* use dir code to expand path */
- if (switchdir(&temp)) /* if ok, use it else punt */
- {
- strcpy(fnb, dirpath());
- i = strlen(fn) - 1;
- while (i >= 0)
- if (fn[i] == BDC1) /* end of name */
- {
- i++;
- break;
- }
- else
- i--;
-
- if (i < 0)
- i = 0;
- strcat(fnb, &fn[i]);
- }
- else
- strcpy(fnb, fn);
- }
- #endif /* FAT */
- adjustnamecase(fnb);
- return fnb;
- }
-
- /* I completely re-hacked this code; it used to
- * spawn command.com to get the names. Now, it calls
- * an OS specific function which is in dos.c or unix.c.
- * Note that the unix version does a system call, but it's
- * much cleaner that this was, portable and the dos
- * version works on DOS, Windows, and NT! (JAM)
- */
- BUFFER *dired_(dirname)
- char *dirname;
- {
- register BUFFER *bp;
- int i;
- register char *s;
-
- if((dirname = adjustname(dirname)) == NULL) {
- ewprintf("Bad directory name");
- return NULL;
- }
-
- adjustnamecase(dirname);
- s = malloc(strlen(dirname) + 4);
- strcpy(s, dirname);
- i = strlen(s) - 1;
- if (s[i] != BDC1)
- {
- i++;
- s[i++] = BDC1;
- s[i] = '\0';
- }
-
- if (!(bp = bfind(s, TRUE)))
- {
- ewprintf("Could not create buffer");
- free(s);
- return NULL;
- }
- if(bclear(bp) != TRUE)
- {
- free(s);
- return FALSE;
- }
-
- GetDiskDirectory(bp, s);
-
- 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(DiredStr)) == NULL) {
- bp->b_modes[0] = &map_table[0];
- ewprintf(modeerr, DiredStr);
- free(s);
- return NULL;
- }
- bp->b_flag |= BFVIEW;
- bp->b_flag &= ~BFREVERT;
- bp->b_nmodes = 0;
- free(s);
- return bp;
- }
-
- /* This is special hack code to do my version of
- * file name auto-complete. (JAM)
- */
- int diredfiles_(f, n)
- int f, n;
- {
- register BUFFER *bp;
- char buffer[NFILEN * 4];
- char bname[NFILEN], dspec[NFILEN * 4];
- int i;
- BOOL found = FALSE;
-
- getcmdinput(buffer);
- adjustnamecase(buffer);
- #ifdef SomeUnix
- {
- char buf1[NFILEN * 4];
- evalEnv(buffer, buf1);
- strcpy(buffer, buf1);
- }
- #endif
- strcpy(bname, buffer);
-
- for (i = 0; i < (int)strlen(bname); i++)
- if (bname[i] == '*')
- {
- found = TRUE;
- break;
- }
- if (!found)
- #ifdef SomeUnix
- strcat(bname, "*");
- #else
- strcat(bname, "*.*");
- #endif
- strcpy(dspec, buffer);
-
- /* fixup buffer now so is real dir name
- */
- for (i = strlen(buffer)-1; i >= 0; i--)
- {
- if (buffer[i] == BDC1)
- break;
- buffer[i] = '\0';
- }
-
- /* make the buffer
- */
- if (!(bp = bfind(bname, TRUE)))
- {
- ewprintf("Could not create buffer");
- return FALSE;
- }
- if(bclear(bp) != TRUE)
- return FALSE;
- GetDiskDirectory(bp, dspec);
-
- bp->b_dotp = lforw(bp->b_linep); /* go to first line */
- (VOID) strncpy(bp->b_fname, buffer, NFILEN);
- if((bp->b_modes[0] = name_mode(DiredStr)) == NULL) {
- bp->b_modes[0] = &map_table[0];
- ewprintf(modeerr, DiredStr);
- return FALSE;
- }
- bp->b_nmodes = 0;
- bp->b_flag |= BFVIEW;
- return (popbuf(bp) ? TRUE : FALSE);
- }
-
- /* This is really ugly, but then so was the UNIX version!
- */
- /* This version knows that the dir buffer was built
- * via DOS/UN*X calls and word (foo.xxx) is the file name,
- * ie it is better than before because at least now line formatting
- * is controled OS-independent. - JAM
- */
- d_makename(lp, fn)
- LINE *lp;
- char *fn;
- {
- register int i, j;
- char c;
-
- /* buffer name not useful for filename
- * if not regular dir-built buffer
- */
- if ((curbp->b_flag & BFREVERT) == 0)
- {
- (VOID) strcpy(fn, curbp->b_fname);
-
- /* scrub the wildcard which may be here from diredfiles_
- */
- for (i = 0; fn[i]; i++)
- if (fn[i] == '*')
- {
- fn[i] = '\0'; /* should only be this one */
- break;
- }
- }
-
- else
- fn[0] = '\0';
-
- j = strlen(fn);
- if (j > 0)
- if (fn[j-1] != BDC1)
- fn[j++] = BDC1;
-
- /* find the word; if on space/tab, error and return\
- * else backup to word and then copy till work end
- */
- if (((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ') ||
- ( c == '\t'))
- {
- ewprintf("Cursor not on a filename.");
- return(ABORT);
- }
-
- /* backup to whitespace
- */
- for (i = curwp->w_doto; i >= 0; i--)
- {
- c = lgetc(lp, i);
- if ((c == ' ') || (c == '\t'))
- {
- i++;
- break;
- }
- }
-
- if ( i < 0)
- i = 0;
-
- for (; i < llength(lp); i++, j++)
- {
- fn[j] = lgetc(lp, i);
- if ((fn[j] == ' ') || (fn[j] == '\t'))
- break;
- }
- fn[j] = '\0';
-
- /*lowercase this
- */
- adjustnamecase(fn);
- return(0); /* DosGetDirectory returns NORMAL files only */
- }
-
- /* For some reason, this was a system call!
- */
- #if 0
- copy(frname, toname)
- char *frname, *toname;
- {
- FILE *in, *out;
- char c = ~EOF;
-
- in = fopen(frname, "rb");
- out = fopen(toname, "wb");
-
- if (in && out)
- {
- for (;c != EOF;)
- if ((c = (char)getc(in)) != EOF)
- putc(c, out);
- fclose(in);
- fclose(out);
- }
-
- return TRUE;
- }
- #endif
-
- BOOL fileisok(s)
- char *s;
- {
- return(access(s, F_OK) == 0);
- }
-
- #ifdef SomeUnix /* someday I might make this work for DOS! */
- static void evalEnv(s, d)
- char *s, *d;
- {
- char envvar[NFILEN], *p;
- int i;
-
- /* To get here means s[0] == $ so expand it out and
- * construct a useful name
- *
- * Collect env name up to standard delim (BDC1) or
- * EOF on string
- */
- for (i = 1; s[i] && (s[i] != BDC1); i++)
- envvar[i-1] = s[i];
- envvar[i-1] = 0;
-
- p = (char *)getenv(envvar);
- if (p && *p)
- {
- strcpy(d, p);
- strcat(d, &s[i]);
- }
- else
- strcpy(d, s); /* failure defaults to original */
- }
- #endif
-