1 /* $Id: fileio.c,v 1.2 2000/07/25 15:06:52 amura Exp $ */
2 /*
3  *		MS-DOS file I/O. (Tested only at MS-DOS 3.1)
4  *
5  *		I make this file from BSD UNIX fileio.c.
6  */
7 
8 /*
9  * $Log: fileio.c,v $
10  * Revision 1.2  2000/07/25 15:06:52  amura
11  * handle Kanji filename of initfile
12  *
13  * Revision 1.1.1.1  2000/06/27 01:47:58  amura
14  * import to CVS
15  *
16  */
17 /* 90.02.11	Modified for Ng 1.0 MS-DOS ver. by S.Yoshida */
18 
19 #include	"config.h"	/* 90.12.20  by S.Yoshida */
20 #include	"def.h"
21 #include	<dos.h>
22 #include	<ctype.h>	/* 90.05.30  Add by A.Shirahashi */
23 #include	<string.h>	/* 90.07.26  Add by N.Kamei */
24 
25 static	FILE	*ffp;
26 extern	char	*getenv(), *strncpy();
27 char	*adjustname();
28 char	*fftolower();	/* 90.07.01  Add by S.Yoshida */
29 
30 /*
31  * Open a file for reading.
32  */
ffropen(fn)33 ffropen(fn) char *fn; {
34 	char fns[NFILEN];
35 
36 	strcpy(fns, fn);
37 #ifdef KANJI
38 	bufetos(fns, strlen(fns)+1);
39 #endif
40 	if ((ffp=fopen(fns, "r")) == NULL)
41 		return (FIOFNF);
42 	return (FIOSUC);
43 }
44 
45 /*
46  * Open a file for writing.
47  * Return TRUE if all is well, and
48  * FALSE on error (cannot create).
49  */
ffwopen(fn)50 ffwopen(fn) char *fn; {
51 	char fns[NFILEN];
52 
53 	strcpy(fns, fn);
54 #ifdef KANJI
55 	bufetos(fns, strlen(fns)+1);
56 #endif KANJI
57 	if ((ffp=fopen(fns, "w")) == NULL) {
58 		ewprintf("Cannot open file for writing");
59 		return (FIOERR);
60 	}
61 	return (FIOSUC);
62 }
63 
64 /*
65  * Close a file.
66  * Should look at the status.
67  */
ffclose()68 ffclose() {
69 	(VOID) fclose(ffp);
70 	return (FIOSUC);
71 }
72 
73 /*
74  * Write a buffer to the already
75  * opened file. bp points to the
76  * buffer. Return the status.
77  * Check only at the newline and
78  * end of buffer.
79  */
ffputbuf(bp)80 ffputbuf(bp)
81 BUFFER *bp;
82 {
83     register char *cp;
84     register char *cpend;
85     register LINE *lp;
86     register LINE *lpend;
87 #ifdef	KANJI	/* 90.01.29  by S.Yoshida */
88     register int  kfio;
89 #endif	/* KANJI */
90 
91     lpend = bp->b_linep;
92 #ifdef	KANJI	/* 90.01.29  by S.Yoshida */
93     if (bp->b_kfio == NIL)
94 	ksetbufcode(bp);		/* Set buffer local KANJI code.	*/
95     kfio  = bp->b_kfio;
96 #endif	/* KANJI */
97     lp = lforw(lpend);
98     do {
99 	cp = &ltext(lp)[0];		/* begining of line	*/
100 	cpend = &cp[llength(lp)];	/* end of line		*/
101 	while(cp != cpend) {
102 #ifdef	KANJI	/* 90.01.29  by S.Yoshida */
103 	    kputc(*cp, ffp, kfio);
104 #else	/* NOT KANJI */
105 	    putc(*cp, ffp);
106 #endif	/* KANJI */
107 	    cp++;	/* putc may evalualte arguments more than once */
108 	}
109 #ifdef	KANJI	/* 90.01.29  by S.Yoshida */
110 	if (kfio == JIS) {
111 		kfselectcode(ffp, FALSE);
112 	}
113 #endif	/* KANJI */
114 	lp = lforw(lp);
115 	if(lp == lpend) break;		/* no implied newline on last line */
116 	putc('\n', ffp);
117     } while(!ferror(ffp));
118     if(ferror(ffp)) {
119 	ewprintf("Write I/O error");
120 	return FIOERR;
121     }
122     return FIOSUC;
123 }
124 
125 /*
126  * Read a line from a file, and store the bytes
127  * in the supplied buffer. Stop on end of file or end of
128  * line.  When FIOEOF is returned, there is a valid line
129  * of data without the normally implied \n.
130  */
ffgetline(buf,nbuf,nbytes)131 ffgetline(buf, nbuf, nbytes)
132 register char	*buf;
133 register int	nbuf;
134 register int	*nbytes;
135 {
136 	register int	c;
137 	register int	i;
138 
139 	i = 0;
140 	while((c = getc(ffp))!=EOF && c!='\n') {
141 		buf[i++] = c;
142 		if (i >= nbuf) return FIOLONG;
143 	}
144 	if (c == EOF  && ferror(ffp) != FALSE) {
145 		ewprintf("File read error");
146 		return FIOERR;
147 	}
148 	*nbytes = i;
149 	return c==EOF ? FIOEOF : FIOSUC;
150 }
151 
152 #ifndef NO_BACKUP
153 /*
154  * Rename the file "fname" into a backup
155  * copy. On Unix the backup has the same name as the
156  * original file, with a "~" on the end; this seems to
157  * be newest of the new-speak. The error handling is
158  * all in "file.c". The "unlink" is perhaps not the
159  * right thing here; I don't care that much as
160  * I don't enable backups myself.
161  */
fbackupfile(fn)162 fbackupfile(fn) char *fn; {
163 	register char	*nname;
164 	void		*malloc();	/* 90.03.27  by A.Shirahashi */
165 	char		*dotp;		/* 90.07.26  Add by N.Kamei */
166 	VOID		strmfe();	/* 90.07.26  Add by N.Kamei */
167 	char fns[NFILEN];
168 	char nnames[NFILEN];
169 
170 	if ((nname=malloc((unsigned)(strlen(fn)+4+1))) == NULL) {
171 					/* 90.07.26  1+1 -> 4+1 by N.Kamei */
172 		ewprintf("Can't get %d bytes", strlen(fn) + 4 +1);
173 		return (ABORT);
174 	}
175 /* 90.07.26  by N.Kamei
176    This is not good for MS-DOS.
177 	(VOID) strcpy(nname, fn);
178 	(VOID) strcat(nname, "~");
179  */
180 	strmfe(nname, fn, "bak");	/* 90.07.26  by N.Kamei */
181 	strcpy(nnames, nname);
182 	strcpy(fns, fn);
183 #ifdef KANJI
184 	bufetos(nnames, strlen(nnames)+1);
185 	bufetos(fns, strlen(fns)+1);
186 #endif KANJI
187 	(VOID) unlink(nnames);			/* Ignore errors.	*/
188 	if (rename(fns, nnames) < 0) {
189 		free(nname);
190 		return (FALSE);
191 	}
192 	free(nname);
193 	return (TRUE);
194 }
195 
196 /*
197  * 90.07.26  Add by N.Kamei.
198  * Add or replace file name extention to ext.
199  * strmfe() is a standard function of Lattice-C.
200  */
201 VOID
strmfe(newname,oldname,ext)202 strmfe(newname, oldname, ext)
203 char	*newname, *oldname, *ext;
204 {
205 	char	*tmp_p, *node_p;
206 
207 	strcpy(newname, oldname);
208 
209 	/* search nodename top */
210 	node_p	= newname;
211 	tmp_p	= strchr(node_p, '\\');
212 	while(tmp_p) {
213 		node_p	= &tmp_p[1];
214 		tmp_p	= strchr(node_p, '\\');
215 	}
216 
217 	tmp_p	= strrchr(node_p, '.');
218 	if (tmp_p)
219 		*tmp_p	= '\0';
220 	strcat(node_p, ".");
221 	strcat(node_p, ext);
222 }
223 
224 #ifdef	BUGFIX	/* 90.02.16  by S.Yoshida */
225 #ifndef	_SYS_STAT_H_
226 #if	!defined(__TURBOC__) || __TURBOC__ >= 0x0200
227 	/* 90.12.28  For Turbo-C 1.5 by Junn Ohta */
228 #include <sys/types.h>
229 #endif	/* __TURBOC__ */
230 #include <sys/stat.h>
231 #define	_SYS_STAT_H_
232 #endif	/* _SYS_STAT_H_ */
233 /*
234  * Get file mode of a file fn.
235  */
fgetfilemode(fn)236 fgetfilemode(fn)
237 char	*fn;
238 {
239 	struct	stat	filestat;
240 	char fns[NFILEN];
241 
242 	strcpy(fns, fn);
243 #ifdef KANJI
244 	bufetos(fns, strlen(fns)+1);
245 #endif KANJI
246 
247 	if (stat(fns, &filestat) == 0) {
248 		return(filestat.st_mode & 0x0fff);
249 	} else {
250 		return(-1);
251 	}
252 }
253 
254 /*
255  * Set file mode of a file fn to the specified mode.
256  */
257 VOID
fsetfilemode(fn,mode)258 fsetfilemode(fn, mode)
259 char	*fn;
260 int	mode;
261 {
262 	char fns[NFILEN];
263 
264 	strcpy(fns, fn);
265 #ifdef KANJI
266 	bufetos(fns, strlen(fns)+1);
267 #endif KANJI
268 	(VOID) chmod(fns, mode);
269 }
270 #endif	/* BUGFIX */
271 #endif
272 
273 #ifdef	READONLY	/* 91.01.05  by S.Yoshida */
274 #ifndef	_SYS_STAT_H_
275 #if	!defined(__TURBOC__) || __TURBOC__ >= 0x0200
276 	/* 90.12.28  For Turbo-C 1.5 by Junn Ohta */
277 #include <sys/types.h>
278 #endif	/* __TURBOC__ */
279 #include <sys/stat.h>
280 #define	_SYS_STAT_H_
281 #endif	/* _SYS_STAT_H_ */
282 /*
283  * Check whether file is read-only of a file fn.
284  */
fchkreadonly(fn)285 fchkreadonly(fn)
286 char	*fn;
287 {
288 	struct	stat	filestat;
289 	char fns[NFILEN];
290 
291 	strcpy(fns, fn);
292 #ifdef KANJI
293 	bufetos(fns, strlen(fns)+1);
294 #endif KANJI
295 
296 	if (stat(fns, &filestat) == 0) {
297 		return(!(filestat.st_mode & S_IWRITE));
298 	} else {
299 		return FALSE;
300 	}
301 }
302 #endif	/* READONLY */
303 
304 /*
305  * The string "fn" is a file name.
306  * Perform any required appending of directory name or case adjustments.
307  * If NO_DIR is not defined, the same file should be refered to even if the
308  * working directory changes.
309  */
310 #ifndef NO_DIR
311 extern char *wdir;
312 #endif
313 
adjustname(fn)314 char *adjustname(fn)
315 register char *fn;
316 {
317     register char *cp;
318     static char fnb[NFILEN];
319 
320     cp = fnb;
321     if (fn[1] == ':') {
322 	*cp++ = *fn++;
323 	*cp++ = *fn++;
324     }
325 #ifdef MSDOS
326 #ifdef HOMEDIR
327     else if (fn[0]=='~' && (fn[1]=='/' || fn[1]=='\\')) {
328     	strcpy(fnb, getenv("HOME"));
329     	while (*cp) {
330     		if (*cp == '/')
331     			*cp = '\\';
332     		cp++;
333     	}
334     	fn++;
335     }
336 #endif
337 #endif
338     switch(*fn) {
339 	case '/':
340 	    *fn = '\\';
341     	case '\\':
342 	    /* 91.01.21  Add following if() for bug fix. by S.Yoshida	*/
343 	    /* 		 This fix can consider that when current drive	*/
344 	    /*		 is "a:", "\file" and "a:\file" are same.	*/
345 	    if (cp == fnb) {
346 		    *cp++ = wdir[0];	/* Current drive name.	*/
347 		    *cp++ = wdir[1];	/* ':'			*/
348 	    }
349 	    *cp++ = *fn++;
350 	    break;
351 	default:
352 #ifndef	NO_DIR	/* 91.01.17  NODIR -> NO_DIR. by S.Yoshida */
353 	    if (cp == fnb || fnb[0] == wdir[0]) {
354 		(VOID) strcpy(fnb, wdir);
355 		cp = fnb + strlen(fnb);
356 	    } else {			/* Different drive. */
357 		int	drive;
358 		int	ndrive;
359 		char	*getcwd();
360 		drive = fnb[0];
361 		/* 90.07.01  Change from TOUPPER() to TOLOWER() */
362 		/*                                 by S.Yoshida */
363 		if (ISUPPER(drive)) {
364 			drive = TOLOWER(drive);
365 		}
366 		/* 90.07.01  Change from 'A' to 'a' by S.Yoshida */
367 		drive = drive - 'a' + 1;
368 #ifdef	__TURBOC__	/* 90.03.27  by A.Shirahashi */
369 		(void) setdisk(drive - 1);
370 #else	/* NOT __TURBOC__ */
371 		_dos_setdrive(drive, &ndrive);	/* Need MSC 5.1 */
372 #endif	/* __TURBOC__ */
373 		/* 90.07.01  Add fftolower() by S.Yoshida */
374 		if (!fftolower(getcwd(fnb, NFILEN - 1))) {
375 		    cp = fnb;
376 		    /* 90.07.01  Change from 'A' to 'a' by S.Yoshida */
377 		    *cp++ = drive + 'a' - 1;
378 		    *cp++ = ':';
379 		} else {
380 		    cp = fnb + strlen(fnb);
381 		}
382 		drive = wdir[0];	/* Reset to current drive. */
383 		/* 90.07.01  Change from TOUPPER() to TOLOWER() */
384 		/*                                 by S.Yoshida */
385 		if (ISUPPER(drive)) {
386 			drive = TOLOWER(drive);
387 		}
388 		/* 90.07.01  Change from 'A' to 'a' by S.Yoshida */
389 		drive = drive - 'a' + 1;
390 #ifdef	__TURBOC__	/* 90.03.27  by A.Shirahashi */
391 		(void) setdisk(drive - 1);
392 #else	/* NOT __TURBOC__ */
393 		_dos_setdrive(drive, &ndrive);	/* Need MSC 5.1 */
394 #endif	/* __TURBOC__ */
395 	    }
396 	    break;
397 #else
398 	    return fn;				/* punt */
399 #endif
400     }
401     if(cp != fnb && cp[-1] != '\\') *cp++ = '\\';
402     while(*fn) {
403     	switch(*fn) {
404 	    case '.':
405 		switch(fn[1]) {
406 	            case '\0':
407 		    	*--cp = '\0';
408 		    	return fnb;
409 		    case '/':
410 	    	    case '\\':
411 	    	    	fn += 2;
412 		    	continue;
413 		    case '.':
414 		    	if(fn[2]=='\\' || fn[2] == '/' || fn[2] == '\0') {
415 			    --cp;
416 			    while(cp > fnb && *--cp != '\\') {}
417 			    ++cp;
418 			    if(fn[2]=='\0') {
419 			        *--cp = '\0';
420 			        return fnb;
421 			    }
422 		            fn += 3;
423 		            continue;
424 		        }
425 		        break;
426 		    default:
427 		    	break;
428 	        }
429 		break;
430 	    case '/':
431 	    case '\\':
432 	    	fn++;
433 	    	continue;
434 	    default:
435 	    	break;
436 	}
437 	while(*fn && (*cp++ = *fn++) != '\\') {
438 	    /* 90.06.05  by S.Yoshida */
439 	    /* 90.06.08  by A.Shirahashi, convert to lower case */
440 	    if (ISUPPER(cp[-1])) {
441 		cp[-1] = TOLOWER(cp[-1]);
442 	    }
443 	    if (cp[-1] == '/') {
444 		cp[-1] = '\\';
445 		break;
446 	    }
447 	}
448     }
449     if(cp[-1]=='\\') {
450 	/* 91.01.16  bug fix for case only "a:\". by S.Yoshida */
451 	if (cp != &fnb[3] || fnb[1] != ':') {
452 	    --cp;
453 	}
454     }
455     *cp = '\0';
456     return fnb;
457 }
458 
459 #ifndef NO_STARTUP
460 #include <io.h>
461 /*
462  * Find a startup file for the user and return its name. As a service
463  * to other pieces of code that may want to find a startup file (like
464  * the terminal driver in particular), accepts a suffix to be appended
465  * to the startup file name.
466  */
467 char *
468 #ifdef	ADDOPT
startupfile(ngrcfile,suffix)469 startupfile(ngrcfile, suffix)
470 char* ngrcfile;
471 #else
472  startupfile(suffix)
473 #endif
474 char *suffix;
475 {
476 	register char	*file;
477 	static char	home[NFILEN];
478 	char		*getenv();
479 
480 	if ((file = getenv("NG")) == NULL) {
481 		if ((file = getenv("HOME")) == NULL) goto notfound;
482 	}
483 	if (strlen(file)+7 >= NFILEN - 1) goto notfound;
484 	(VOID) strcpy(home, file);
485 
486 #ifdef	ADDOPT
487 	if (!ngrcfile)
488 		ngrcfile = getenv("NGRC");
489 	if (ngrcfile)
490 	{
491 		if (access(ngrcfile, 0) == 0) {
492 			strncpy(home, ngrcfile, NFILEN);
493 			home[NFILEN-1] = '\0';
494 #ifdef	KANJI
495 			bufstoe(home, strlen(home)+1);
496 #endif
497 			return home;
498 		}
499 	/*
500 		strcat(home, "\\");
501 		strcat(home, ngrcfile);
502 		if (access(home, 0) == 0) {
503 #ifdef	KANJI
504 			bufstoe(home, strlen(home)+1);
505 #endif
506 			return home;
507 		}
508 		(VOID)strcpy(home, file);
509 	*/
510 	}
511 #endif
512 
513 #ifdef	KANJI	/* 90.02.10  by S.Yoshida */
514 	(VOID) strcat(home, "\\ng.ini");
515 #else	/* NOT KANJI */
516 	(VOID) strcat(home, "\\mg.ini");
517 #endif	/* KANJI */
518 	if (suffix != NULL) {
519 		(VOID) strcat(home, "-");
520 		(VOID) strcat(home, suffix);
521 	}
522 	if (access(home, 0) == 0) {
523 #ifdef	KANJI
524 		bufstoe(home, strlen(home)+1);
525 #endif
526 		return home;
527 	}
528 
529 notfound:
530 #ifdef	STARTUPFILE
531 	strcpy(home, STARTUPFILE);
532 	if (suffix != NULL) {
533 		(VOID) strcat(home, "-");
534 		(VOID) strcat(home, suffix);
535 	}
536 	if (access(home, 0) == 0) {
537 #ifdef	KANJI
538 		bufstoe(home, strlen(home)+1);
539 #endif
540 		return home;
541 	}
542 #endif
543 
544 	return NULL;
545 }
546 #endif
547 
548 #ifndef NO_DIRED
549 #include <process.h>
550 #ifdef	__TURBOC__	/* 90.03.27  by A.Shirahashi */
551 #include <dir.h>
552 #define	find_t ffblk
553 #define	_dos_findfirst(p,a,f)	findfirst(p,f,a)
554 #define	_dos_findnext(f)	findnext(f)
555 #define	_A_NORMAL	0
556 #define	_A_RDONLY	FA_RDONLY
557 #define	_A_SUBDIR	FA_DIREC
558 #define	_A_ARCH		FA_ARCH
559 #define	attrib		ff_attrib
560 #define	wr_date		ff_fdate
561 #define	wr_time		ff_ftime
562 /*#define size		ff_fsize*/ /* 90.05.30  remove by A.Shirahashi */
563 /*#define name		ff_name*/ /* 90.05.30  remove by A.Shirahashi */
564 #else	/* NOT __TURBOC__ */
565 #include <search.h>
566 #endif	/* __TURBOC__ */
567 #include "kbd.h"
568 
copy(frname,toname)569 copy(frname, toname)
570 char *frname, *toname;
571 {
572     char cmd[256];
573     char frnames[NFILEN];
574     char tonames[NFILEN];
575 
576     strcpy(frnames, frname);
577     strcpy(tonames, toname);
578 #ifdef KANJI
579     bufetos(frnames, strlen(frnames)+1);
580     bufetos(tonames, strlen(tonames)+1);
581 #endif
582 
583     sprintf(cmd, "copy %s %s", frnames, tonames);
584     return (system(cmd) == 0);
585 }
586 
dired_(dirname)587 BUFFER *dired_(dirname)
588 char *dirname;
589 {
590     register BUFFER *bp;
591     BUFFER *findbuffer();
592     char **files, **getfilelist();
593     int  numfiles;
594     int  i;
595 
596     if((dirname = adjustname(dirname)) == NULL) {
597 	ewprintf("Bad directory name");
598 	return NULL;
599     }
600     if(dirname[strlen(dirname)-1] != '\\') (VOID) strcat(dirname, "\\");
601     if((bp = findbuffer(dirname)) == NULL) {
602 	ewprintf("Could not create buffer");
603 	return NULL;
604     }
605     if(bclear(bp) != TRUE) return FALSE;
606     if ((files = getfilelist(&numfiles, dirname)) == NULL) {
607 	ewprintf("Could not get directory info");
608 	return NULL;
609     }
610     for (i = 0; i < numfiles; i++) {
611 	(VOID) addline(bp, files[i]);
612 	free(files[i]);
613     }
614     free(files);
615     bp->b_dotp = lforw(bp->b_linep);		/* go to first line */
616     (VOID) strncpy(bp->b_fname, dirname, NFILEN);
617 #ifdef EXTD_DIR
618     bp->b_cwd[0] = '\0';
619 #endif
620     if((bp->b_modes[0] = name_mode("dired")) == NULL) {
621 	bp->b_modes[0] = &map_table[0];
622 	ewprintf("Could not find mode dired");
623 	return NULL;
624     }
625     bp->b_nmodes = 0;
626     return bp;
627 }
628 
d_makename(lp,fn)629 d_makename(lp, fn)
630 register LINE *lp;
631 register char **fn;
632 {
633     register char *cp;
634     int len;
635 
636     if(llength(lp) <= 41) return ABORT;
637     len = strlen(curbp->b_fname) + llength(lp) - 41;
638     cp = malloc(len + 1);
639     if (cp) {
640       *fn = cp;
641       (VOID)strcpy(cp, curbp->b_fname);
642       cp += strlen(cp);
643       bcopy(&lp->l_text[41], cp, llength(lp) - 41);
644       cp[llength(lp) - 41] = '\0';
645       return lgetc(lp, 2) == 'd';
646     }
647     else {
648       return ABORT;
649     }
650 }
651 
652 char **
getfilelist(numfiles,dirname)653 getfilelist(numfiles, dirname)
654 int	*numfiles;
655 char	*dirname;
656 {
657 	char	**files;
658 	int	maxfiles;
659 	struct	find_t	fileinfo;
660 	int	i;
661 	char	filename[NFILEN];
662 #ifdef KANJI
663 	char	filenames[NFILEN];
664 #endif
665 	int	filelinecmp();
666 	void	*calloc(), *realloc();
667 	VOID	mkfileline();
668 
669 	if (strlen(dirname) + 4 > NFILEN) return(NULL);
670 	(VOID) strcpy(filename, dirname);
671 	(VOID) strcat(filename, "*.*");
672 
673 	maxfiles = 50;
674 	files = (char **)calloc(maxfiles, sizeof(char *));
675 	if (files == NULL) return(NULL);
676 
677 #ifdef KANJI
678 	strcpy(filenames, filename);
679 	bufetos(filenames, strlen(filenames) +1);
680 	if (_dos_findfirst(filenames, _A_NORMAL | _A_RDONLY | _A_SUBDIR,
681 			&fileinfo) == 0) {
682 #else /* not KANJI */
683 	if (_dos_findfirst(filename, _A_NORMAL | _A_RDONLY | _A_SUBDIR,
684 			&fileinfo) == 0) {
685 #endif /* KANJI */
686 		files[0] = (char *)calloc(80, 1);
687 		if (files[0] == NULL) {
688 			free(files);
689 			return(NULL);
690 		}
691 		mkfileline(files[0], &fileinfo);
692 		*numfiles = 1;
693 		while(_dos_findnext(&fileinfo) == 0) {
694 			if (*numfiles >= maxfiles) {
695 				files = (char **) realloc(files,
696 					sizeof(char *) * (maxfiles + 20));
697 				if (files == NULL) return(NULL);
698 				maxfiles += 20;
699 			}
700 			files[*numfiles] = (char *)calloc(80, 1);
701 			if (files[*numfiles] == NULL) {
702 				for (i = 0; i < *numfiles; i++) {
703 					free(files[i]);
704 				}
705 				free(files);
706 				return(NULL);
707 			}
708 			mkfileline(files[*numfiles], &fileinfo);
709 			(*numfiles)++;
710 		}
711 		qsort(files, *numfiles, sizeof (char *), filelinecmp);
712 		return(files);
713 	}
714 	return(NULL);
715 }
716 
717 VOID
mkfileline(line,info)718 mkfileline(line, info)
719 char	*line;
720 struct	find_t	*info;
721 {
722 	int	y;
723 
724 	line[0] = line[1] = ' ';
725 	line[2] = (info->attrib & _A_SUBDIR) ? 'd' : '-';
726 	line[3] = 'r';
727 	line[4] = (info->attrib & _A_RDONLY) ? '-' : 'w';
728 	line[5] = '-';
729 	line[6] = (info->attrib & _A_ARCH) ? 'a' : '-';
730 #ifdef __TURBOC__	/* 90.05.30  by A.Shirahashi */
731 	(VOID) sprintf(&line[7], "%15ld", info->ff_fsize);
732 #else
733 	(VOID) sprintf(&line[7], "%15ld", info->size);
734 #endif
735 	y = 1980 + ((info->wr_date >> 9) & 0x7f);
736 	y -= (y > 1999) ? 2000 : 1900;
737 	(VOID) sprintf(&line[22], "  %02d-%02d-%02d  %02d:%02d  ",
738 		y, (info->wr_date >> 5) & 0x0f, info->wr_date & 0x1f,
739 		(info->wr_time >> 11) & 0x1f, (info->wr_time >> 5) & 0x3f);
740 #ifdef __TURBOC__	/* 90.05.30  by A.Shirahashi */
741 	/* 90.07.01  Add fftolower() by S.Yoshida */
742 	(VOID) strcpy(&line[41], info->ff_name);
743 #else
744 	/* 90.07.01  Add fftolower() by S.Yoshida */
745 	(VOID) strcpy(&line[41], info->name);
746 #endif
747 #ifdef  KANJI
748 	(VOID) bufstoe(&line[41], strlen(&line[41])+1);
749 #endif /* KANJI */
750 	(VOID) fftolower(&line[41]);
751 }
752 
filelinecmp(x,y)753 filelinecmp(x, y)
754 char	**x, **y;
755 {
756 	register unsigned char	*xx, *yy;
757 
758 	xx = (unsigned char*)&(*x)[41];
759 	yy = (unsigned char*)&(*y)[41];
760 
761 	if (*xx != *yy) {		/* for "." ".." directories */
762 		if (*xx == '.') return -1;
763 		if (*yy == '.') return 1;
764 	  	return(*xx - *yy);
765 	}
766 
767 	if (*xx) {
768 		for (xx++, yy++; *xx && *xx == *yy; xx++, yy++) {}
769 	}
770 	return(*xx - *yy);
771 }
772 #endif
773 
774 #ifndef NO_DIRED	/* 91.01.15  by K.Maeda */
775 #ifndef	_SYS_STAT_H_
776 #if	!defined(__TURBOC__) || __TURBOC__ >= 0x0200
777 	/* 90.12.28  For Turbo-C 1.5 by Junn Ohta */
778 #include <sys/types.h>
779 #endif	/* __TURBOC__ */
780 #include <sys/stat.h>
781 #define	_SYS_STAT_H_
782 #endif	/* _SYS_STAT_H_ */
783 /*
784  * Check whether file "dn" is directory.
785  */
ffisdir(dn)786 ffisdir(dn)
787 char *dn;
788 {
789 	struct	stat	filestat;
790 	char dns[NFILEN];
791 
792 	strcpy(dns, dn);
793 #ifdef KANJI
794 	bufetos(dns, strlen(dns)+1);
795 #endif
796 
797 	if (stat(dns, &filestat) == 0) {
798 		return ((filestat.st_mode & S_IFMT) == S_IFDIR);
799 	} else {
800 		return FALSE;
801 	}
802 }
803 #endif /* NO_DIRED */
804 
805 #ifndef NO_FILECOMP	/* 90.04.04  by K.Maeda */
806 
807 /* 89.11.20	Original code is for X68K (Human68K).
808  * 90.04.08	Modified for MS-DOS by S.Yoshida.
809  * 90.05.30	Debuged by A.Shirahashi.
810  * Find file names starting with name.
811  * Result is stored in *buf, got from malloc();
812  * Return the number of files found, or
813  * -1 of error occured.
814  */
815 
816 #define	MALLOC_STEP	256
817 
fffiles(name,buf)818 fffiles(name, buf)
819 char *name, **buf;
820 {
821 	char	pathbuf[NFILEN], tmpnam[NFILEN];
822 #ifdef  KANJI
823 	char	pathbufs[NFILEN];
824 #endif
825 	char	*cp, *dirpart, *nampart;
826 	struct	find_t	fileinfo;
827 	int	n, len, size, dirpartlen, nampartlen;
828 	char	*buffer;
829 	void	*malloc(), *realloc();
830 
831 	strcpy(pathbuf, name);
832 	dirpart = NULL;
833 	for (cp = pathbuf; *cp; cp++) {
834 		if (*cp == '/') {
835 			*cp = '\\';
836 			dirpart = cp;
837 		} else if (*cp == '\\') {
838 			dirpart = cp;
839 		} else if (dirpart == NULL && *cp == ':') {
840 			dirpart = cp;
841 		}
842 	}
843 	if (dirpart) {
844 		*++dirpart = '\0';
845 		dirpartlen = dirpart - pathbuf;
846 	} else {
847 		strcpy(pathbuf, ".\\");	/* 90.05.30  by A.Shirahashi */
848 		dirpartlen = 0;
849 	}
850 	nampart = name + dirpartlen;
851 	nampartlen = strlen(nampart);
852 	for (cp = nampart; *cp; cp++) {		/* _dos_find*() return	*/
853 		/* 90.05.30  by A.Shirahashi: Use "toupper()". */
854 		/* 90.06.06  by S.Yoshida: Reused "TOUPPER()".  */
855 		/*			   And add "ISLOWER()". */
856 		if (ISLOWER(*cp)) {
857 			*cp = TOUPPER(*cp);	/* upper case name.	*/
858 		}
859 	}
860 
861 #ifndef	NEW_COMPLETE	/* 90.12.10    Sawayanagi Yosirou */
862 	(VOID) strcat(pathbuf, "*.*");
863 #ifdef KANJI
864 	strcpy(pathbufs, pathbuf);
865 	bufetos(pathbufs, strlen(pathbufs)+1);
866 	if (_dos_findfirst(pathbufs, _A_NORMAL | _A_RDONLY | _A_SUBDIR,
867 			&fileinfo) != 0) {
868 #else /* not KANJI */
869 	if (_dos_findfirst(pathbuf, _A_NORMAL | _A_RDONLY | _A_SUBDIR,
870 			&fileinfo) != 0) {
871 #endif /* KANJI */
872 		return (-1);
873 	}
874 #endif	/* NEW_COMPLETE */
875 
876 	buffer = malloc(MALLOC_STEP);
877 	if (buffer == NULL) {
878 		return (-1);
879 	}
880 	size = MALLOC_STEP;
881 	len = 0;
882 	n = 0;
883 
884 #ifdef	NEW_COMPLETE	/* 90.12.10    Sawayanagi Yosirou */
885 	(VOID) strcat(pathbuf, "*.*");
886 #ifdef KANJI
887 	strcpy(pathbufs, pathbuf);
888 	bufetos(pathbufs, strlen(pathbufs)+1);
889 	if (_dos_findfirst(pathbufs, _A_NORMAL | _A_RDONLY | _A_SUBDIR,
890 			&fileinfo) != 0) {
891 #else /* not KANJI */
892 	if (_dos_findfirst(pathbuf, _A_NORMAL | _A_RDONLY | _A_SUBDIR,
893 			&fileinfo) != 0) {
894 #endif /* KANJI */
895 		*buf = buffer;
896 		buffer[0] = '\0';
897 		return (0);
898 	}
899 #endif	/* NEW_COMPLETE */
900 
901 	do {
902 		register int l;
903 		char ff_namee[NFILEN];
904 
905 #ifdef __TURBOC__ /* 90.05.30  by A.Shirahashi */
906 		strcpy(ff_namee, fileinfo.ff_name);
907 #else
908 		strcpy(ff_namee, fileinfo.name);
909 #endif
910 		bufstoe(ff_namee, strlen(ff_namee)+1);
911 		if (strncmp(nampart, ff_namee, nampartlen) != 0)
912 			continue;		/* no-case-sensitive comparison */
913 		strncpy(tmpnam, pathbuf, dirpartlen);
914 
915 		strcpy(tmpnam + dirpartlen, ff_namee);
916 		if (fileinfo.attrib & _A_SUBDIR) {
917 			strcat(tmpnam, "\\");
918 		}
919 		l = strlen(tmpnam)+1;
920 		/* 90.05.30  by A.Shirahashi */
921 		if (l > 5 && (stricmp(&tmpnam[l-5],".OBJ") == 0 ||
922 			      stricmp(&tmpnam[l-5],".EXE") == 0 ||
923 			      stricmp(&tmpnam[l-5],".COM") == 0))
924 		/* 90.05.30  by A.Shirahashi */
925 			continue;
926 		if (l + len >= size) {
927 				/* make room for double null */
928 			if ((buffer = realloc(buffer, size += MALLOC_STEP)) == NULL) {
929 				return(-1);
930 			}
931 		}
932 		/* 90.06.08  by A.Shirahashi: from */
933                 for (cp = tmpnam; *cp; cp++) {
934                     if (ISUPPER(*cp)) {
935                         *cp = TOLOWER(*cp);
936                     }
937                 }
938 		/* 90.06.08  by A.Shirahashi: to */
939 		strcpy(buffer + len, tmpnam);
940 		len += l;
941 		n++;
942 	} while (_dos_findnext(&fileinfo) == 0);
943 
944 	*buf = buffer;
945 	buffer[len] = '\0';
946 	return(n);
947 }
948 #endif	/* NO_FILECOMP */
949 
950 /* 90.07.01  Add function to convert strings into lower case by S.Yoshida */
951 char	*
fftolower(name)952 fftolower(name)
953 char	*name;
954 {
955 	register char	*p;
956 
957 	if ((p = name) != NULL) {
958 		while(*p != '\0') {
959 			if (ISUPPER(*p)) {
960 				*p = TOLOWER(*p);
961 			}
962 			p++;
963 		}
964 	}
965 	return(name);
966 }
967 
968 #ifdef	NEW_COMPLETE	/* 90.12.10    Sawayanagi Yosirou */
969 char *
file_name_part(s)970 file_name_part (s)
971 char	*s;
972 {
973 	int	i;
974 
975 	for (i = strlen (s) - 1; i > 0; i--) {
976 		if (s[i - 1] == '/')
977 			break;
978 	}
979 	return (s + i);
980 }
981 
982 char *
copy_dir_name(d,s)983 copy_dir_name (d, s)
984 char	*d;
985 char	*s;
986 {
987 	int	i;
988 
989 	i = file_name_part (s) - s;
990 	strncpy (d, s, i);
991 	d[i] = '\0';
992 	return (d);
993 }
994 #endif	/* NEW_COMPLETE */
995