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 = <ext(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