1 /* $Id: fileio.c,v 1.7 2001/03/02 08:47:04 amura Exp $ */
2 /*
3  * Name:	MG 2a401
4  *		Commodore Amiga file I/O.
5  * Last edit:	05-May-88 swalton@solar.stanford.edu
6  * Next-to-Last edit:	16-Dec-87 mic@emx.utexas.edu
7  * Created:	23-Jul-86 mic@emx.utexas.edu
8  *
9  * Read and write ASCII files. All of the low level file I/O
10  * knowledge is here.  Uses AmigaDOS standard I/O and does its
11  * own dynamic buffering; this seems to save about 2K worth
12  * of space in the executable image.
13  */
14 
15 /*
16  * $Log: fileio.c,v $
17  * Revision 1.7  2001/03/02 08:47:04  amura
18  * fix some bogus bugs
19  *
20  * Revision 1.6  2001/02/18 19:29:03  amura
21  * split dir.c to port depend/independ
22  *
23  * Revision 1.5  2000/12/28 07:26:50  amura
24  * suffix o is not search in filename complition
25  *
26  * Revision 1.4  2000/12/27 16:55:41  amura
27  * change d_makename() params for conservative reason, and bugfix in dires_()
28  *
29  * Revision 1.3  2000/12/21 16:54:20  amura
30  * fix usage of strncat()
31  *
32  * Revision 1.2  2000/12/14 18:07:52  amura
33  * filename length become flexible
34  *
35  * Revision 1.1.1.1  2000/06/27 01:48:01  amura
36  * import to CVS
37  *
38  * Revision 1.1  1999/05/21  00:58:37  amura
39  * Initial revision
40  *
41  */
42 
43 #include	"config.h"	/* Dec.15,1992 Add by H.Ohkubo */
44 #undef	TRUE
45 #undef	FALSE
46 #include	"def.h"
47 
48 #ifdef SUPPORT_ANSI
49 # include	<string.h>
50 # include	<stdlib.h>
51 # include	<exec/types.h>
52 #endif
53 #ifdef AMIGA_STDIO
54 # include	<stdio.h>
55 #endif
56 #include	<exec/memory.h>
57 #include	<libraries/dos.h>
58 #include	<libraries/dosextens.h>
59 #ifdef		USE_ARP
60 # include	"libraries/arpbase.h"
61 #else
62 # define FCHARS	32L
63 #endif
64 
65 #define	NIOBUF			4096
66 
67 extern ULONG			Rename(), UnLock(), Close(), FreeMem();
68 extern LONG			Write(), Read();
69 extern UBYTE			*AllocMem();
70 extern struct FileLock		*Lock();
71 extern struct FileHandle	*Open();
72 #ifdef	BUGFIX	/* Dec.17,1992 by H.Ohkubo */
73 extern LONG	Examine();
74 #endif
75 
76 #ifdef AMIGA_STDIO
77 static FILE	*ffp;
78 #else
79 static struct FileHandle *ffh = 0;
80 static UBYTE	*iobuf;
81 static int	ibufo, niobuf;
82 static LONG	iostat, access_mode;
83 #include	"zz_pointer.h"	/* Dec.20,1992 Add by H.Ohkubo */
84 extern	struct Window *EmW;
85 #endif
86 
87 #ifdef	MANX
88 extern char *strncpy(), *strncat(), *index(), *rindex();
89 #endif
90 #ifdef LATTICE
91  extern char *malloc() ;
92 #endif
93 #ifdef SUPPORT_ANSI
94 # define index	strchr
95 # define rindex	strrchr
96 #endif
97 
98 #ifdef AMIGA_STDIO
99 # define GETC(f)    getc(f)
100 # define PUTC(c,f)  putc(c,f)
101 # define FERROR(f)  ferror(f)
102 #else
103 # define GETC(f)    (ibufo == niobuf) ? FillBuf() : iobuf[ibufo++]
104 # define PUTC(c,f)  {if (niobuf == NIOBUF) FlushBuf(); iobuf[niobuf++] = c;}
105 # define FERROR(f)  (iostat < 0L)
106 #endif
107 
108 /*
109  * Open the Emacs internal file for reading.
110  */
ffropen(fn)111 ffropen(fn)
112 char	*fn;
113 #ifdef AMIGA_STDIO
114 {
115 	if ((ffp=fopen(fn, "r")) == NULL)
116 		return (FIOFNF);
117 	return (FIOSUC);
118 }
119 #else
120 {
121 	if ((iobuf = AllocMem((ULONG) NIOBUF, 0L)) == NULL)
122 		return (FIOERR);
123 
124 	if ((ffh = Open(fn, access_mode = MODE_OLDFILE)) == 0L) {
125 		FreeMem(iobuf, (ULONG) NIOBUF);
126 		return (FIOFNF);
127 	}
128 	ZZ_POINTER(EmW);	/* Dec.20,1992 Add by H.Ohkubo */
129 	ibufo = niobuf = 0;
130 	return (FIOSUC);
131 }
132 #endif
133 
134 /*
135  * Open a file for writing.  Return TRUE if all
136  * is well, and FALSE on error (cannot create).
137  */
138 
ffwopen(fn)139 ffwopen(fn)
140 char	*fn;
141 #ifdef AMIGA_STDIO
142 {
143 	if ((ffp=fopen(fn, "w")) == NULL) {
144 		ewprintf("Cannot open file for writing");
145 		return (FIOERR);
146 	}
147 	return (FIOSUC);
148 }
149 #else
150 {
151 	if ((iobuf = AllocMem((ULONG) NIOBUF, 0L)) == NULL)
152 		return (FIOERR);
153 	if ((ffh = Open(fn, access_mode = MODE_NEWFILE)) == 0L) {
154 		ewprintf("Cannot open file for writing");
155 		FreeMem(iobuf, (ULONG) NIOBUF);
156 		return (FIOERR);
157 	}
158 	niobuf = 0;
159 	iostat = NIOBUF;    /* pretend we wrote out a full buffer last time */
160 	ZZ_POINTER(EmW);	/* Dec.20,1992 Add by H.Ohkubo */
161 	return (FIOSUC);
162 }
163 #endif
164 
165 /*
166  * Close a file, flushing the output buffer.  Should look at
167  * the status.
168  */
ffclose()169 ffclose()
170 #ifdef AMIGA_STDIO
171 {
172 	(VOID) fclose(ffp);
173 	return (FIOSUC);
174 }
175 #else
176 {
177 	if (access_mode == MODE_NEWFILE)
178 		FlushBuf();
179 	if (ffh)
180 		(void) Close(ffh);
181 	if (iobuf)
182 		FreeMem(iobuf, (ULONG) NIOBUF);
183 	CLEAR_POINTER(EmW);	/* Dec.20,1992 add by H.Ohkubo */
184 	return (FIOSUC);
185 }
186 #endif
187 
188 /*
189  * Write a buffer to the already opened file. bp points to the
190  * buffer. Return the status. Check only at the newline and
191  * end of buffer.
192  */
ffputbuf(bp)193 ffputbuf(bp)
194 BUFFER *bp;
195 {
196     register char *cp;
197     register char *cpend;
198     register LINE *lp;
199     register LINE *lpend;
200 #ifdef	KANJI	/* Dec. 15, 1992 by H.Ohkubo */
201     register int  kfio;
202 # ifdef   AMIGA_STDIO
203 #   define  FFP		(ffp)
204 # else
205     My_FILE ffp;
206 #   define  FFP		(&ffp)
207 # endif
208 #endif	/* KANJI */
209 
210     lpend = bp->b_linep;
211 #ifdef	KANJI	/* Dec. 15, 1992 by H.Ohkubo */
212     if (bp->b_kfio == NIL)
213 	ksetbufcode(bp);		/* Set buffer local KANJI code.	*/
214     kfio  = bp->b_kfio;
215 # ifndef   AMIGA_STDIO
216     ffp.niobuf = &niobuf;
217     ffp.bufmax = NIOBUF;
218     ffp.iobuf = iobuf;
219 # endif
220 #endif	/* KANJI */
221     lp = lforw(lpend);
222     do {
223 	cp = &ltext(lp)[0];		/* begining of line	*/
224 	cpend = &cp[llength(lp)];	/* end of line		*/
225 	while(cp != cpend) {
226 #ifdef	KANJI	/* Dec. 15, 1992 by H.Ohkubo / 19 May 1999 by amura*/
227 	    kputc(*cp, FFP, kfio);
228 #else	/* NOT KANJI */
229 	    PUTC(*cp, FFP);
230 #endif	/* KANJI */
231 	    cp++;
232 	}
233 #ifdef	KANJI	/* Dec. 15, 1992 by H.Ohkubo */
234 	if (kfio == JIS) {
235 		kfselectcode(FFP, FALSE);
236 	}
237 #endif	/* KANJI */
238 	lp = lforw(lp);
239 	if(lp == lpend) break;		/* no implied newline on last line */
240 	PUTC('\n', ffp);
241     } while(!FERROR(ffp));
242     if(FERROR(ffp)) {
243 	ewprintf("Write I/O error");
244 	return FIOERR;
245     }
246     return FIOSUC;
247 }
248 
249 /*
250  * Read a line from a file, and store the bytes
251  * in the supplied buffer. Stop on end of file or end of
252  * line.  When FIOEOF is returned, there is a valid line
253  * of data without the normally implied \n.
254  */
ffgetline(buf,nbuf,nbytes)255 ffgetline(buf, nbuf, nbytes)
256 register char	*buf;
257 register int	nbuf;
258 register int	*nbytes;
259 {
260 	register int	c;
261 	register int	i;
262 
263 	i = 0;
264 	while((c = GETC(ffp))!=EOF && c!='\n') {
265 		buf[i++] = c;
266 		if (i >= nbuf) return FIOLONG;
267 	}
268 	if (c == EOF  && FERROR(ffp) != FALSE) {
269 		ewprintf("File read error");
270 		return FIOERR;
271 	}
272 	*nbytes = i;
273 	return c==EOF ? FIOEOF : FIOSUC;
274 }
275 
276 #ifndef	NO_BACKUP
277 /*
278  * Rename the current file into a backup copy,
279  * possibly after deleting the original file.
280  */
fbackupfile(fname)281 fbackupfile(fname)
282 char	*fname;
283 {
284 	struct FileLock *twiddle, *lock;
285 	char buffer[NFILEN];
286 
287 	(void) strncpy(buffer,fname,NFILEN - 1);
288 	(void) strcat(buffer,"~");
289 
290 	lock = Lock(fname,(ULONG)EXCLUSIVE_LOCK);/* does file exist?	*/
291 	if (!lock)
292 		return (FALSE);			/* nope, return error	*/
293 
294 	twiddle = Lock(buffer,(ULONG)EXCLUSIVE_LOCK);
295 	if (twiddle) {				/* delete old backup	*/
296 		UnLock(twiddle);		/* let it go		*/
297 		if (!DeleteFile(buffer)) {
298 			UnLock(lock);
299 			return (FALSE);
300 		}
301 		twiddle = NULL;
302 	}
303 	/* rename file to backup name (after unlocking the file)
304 	 */
305 	UnLock(lock);
306 	return (int) Rename(fname,buffer);
307 }
308 
309 #ifdef	BUGFIX	/* Dec.17,1992 Modified for AmigaDos by H.Ohkubo */
310 /*
311  * Get file mode of a file fn.
312  */
fgetfilemode(fn)313 fgetfilemode(fn)
314 char	*fn;
315 {
316 	struct FileLock	*lock;
317 	struct FileInfoBlock	*fib;
318 	int	retval = -1;
319 
320 	if ((lock = Lock(fn, SHARED_LOCK)) != NULL) {
321 		if ((fib = (struct FileInfoBlock *)
322 			AllocMem(sizeof(struct FileInfoBlock), MEMF_CHIP)) != NULL) {
323 			if (Examine(lock, fib) != NULL)
324 				retval = fib->fib_Protection;
325 			FreeMem(fib, sizeof(struct FileInfoBlock));
326 		}
327 		UnLock(lock);
328 	}
329 	return retval;
330 }
331 
332 /*
333  * Set file mode of a file fn to the specified mode.
334  */
335 VOID
fsetfilemode(fn,mode)336 fsetfilemode(fn, mode)
337 char	*fn;
338 int	mode;
339 {
340 	struct FileLock	*lock;
341 
342 	if ((lock = Lock(fn, EXCLUSIVE_LOCK)) != NULL) {
343 		SetProtection(fn, mode);
344 		UnLock(lock);
345 	}
346 }
347 #endif	/* BUGFIX */
348 #endif	/* NO_BACKUP */
349 
350 /* Dec.18,1992 Add by H.Ohkubo */
351 #ifdef	READONLY	/* 91.01.05  by S.Yoshida */
352 /*
353  * Check whether file is read-only of a file fn.
354  */
fchkreadonly(fn)355 fchkreadonly(fn)
356 char	*fn;
357 {
358 	struct Lock	*lock;
359 	struct FileInfoBlock	*fib;
360 	int	retval = FALSE;
361 
362 	if ((lock = (struct Lock*)Lock(fn, SHARED_LOCK)) != NULL) {
363 		if ((fib = (struct FileInfoBlock *)
364 			AllocMem(sizeof(struct FileInfoBlock), MEMF_CHIP)) != NULL) {
365 			if (Examine(lock, fib) != NULL)
366 				retval = (fib->fib_Protection & FIBF_DELETE);
367 			FreeMem(fib, sizeof(struct FileInfoBlock));
368 		}
369 		UnLock(lock);
370 	}
371 	return retval;
372 }
373 #endif	/* READONLY */
374 
375 #ifndef	NO_STARTUP
376 /*
377  * Return name of user's startup file.  On Amiga, make it
378  * .mg in the current directory, then s:.mg
379  */
380 
381 #ifdef	KANJI	/* Dec. 15, 1992 by H.Ohkubo */
382 static char startname[] = ".ng";
383 static char altstartname[] = "s:ng-startup";
384 #else	/* NOT KANJI */
385 static char startname[] = ".mg";
386 static char altstartname[] = "s:mg-startup";	/* .mg -> mg-startup by H.Ohkubo */
387 #endif	/* KANJI */
388 
389 char *
390 #ifdef	ADDOPT
startupfile(ngrcfile,suffix)391 startupfile(ngrcfile, suffix)
392 char* ngrcfile;
393 #else
394 startupfile(suffix)
395 #endif
396 char *suffix;
397 {
398 	struct FileLock *lock;
399 
400 #ifdef ADDOPT
401 	if (ngrcfile) {
402 		if (lock = Lock(ngrcfile,(ULONG)SHARED_LOCK)) {
403 			UnLock(lock);
404 			return(ngrcfile);
405 		}
406 	}
407 #endif
408 	if (lock = Lock(startname,(ULONG)SHARED_LOCK)) {
409 		UnLock(lock);
410 		return(startname);
411 	}
412 	if (lock = Lock(altstartname,(ULONG)SHARED_LOCK)) { /* alternate */
413 		UnLock(lock);
414 		return (altstartname);
415 	}
416 	return (NULL);
417 }
418 #endif	NO_STARTUP
419 
420 /*
421  * The string "fn" is a file name. Perform any required name adjustments,
422  * including conversion to a fully qualified path if NO_DIR isn't defined.
423  */
424 
425 #define MAX_ELEMS	  8		/* Maximum number of elements	*/
426 extern char MyDirName[];
427 
adjustname(fn)428 char *adjustname(fn)
429 register char	*fn;
430 {
431 #ifndef NO_DIR
432 	static char fnb[MAX_ELEMS*FCHARS + 1];
433 	struct FileLock *lock;
434 	long PathName();
435 	void TackOn();
436 	char *dup, *p;
437 
438 	if (!index(fn, ':')) {			/* no device		*/
439 		strcpy(fnb, MyDirName);
440 		TackOn(fnb, fn);
441 		if (!index(fn, '/'))		/* completely bare name */
442 			return fnb;
443 	} else
444 		strcpy(fnb, fn);
445 	/*
446 	 * Else fn has some path components in it.  We try to PathName
447 	 * the whole thing first, but since the file specified by fn
448 	 * may not exist, we PathName the leading part and TackOn the
449 	 * trailing part if it doesn't.
450 	 */
451 	if (lock = Lock(fnb, SHARED_LOCK)) {
452 		if (PathName(lock, fnb, (long) MAX_ELEMS) !=0) {
453 			UnLock(lock);
454 			return fnb;
455 		}
456 		ewprintf("adjustname: PathName() failed!");
457 		UnLock(lock);
458 		return fn;
459 	}
460 	if (!(p = rindex(fnb, '/')))
461 		p = index(fnb, ':');
462 	p++;
463 	dup = alloca(strlen(p) + 1);
464 	if (dup == NULL) {
465 	    ewprintf("adjustname: PathName() failed!");
466 	    return fn;
467 	}
468 	strcpy(dup, p);
469 	*p = '\0';
470 	if (lock = Lock(fnb, SHARED_LOCK)) {
471 		if (PathName(lock, fnb, (long) MAX_ELEMS) != 0) {
472 			UnLock(lock);
473 			TackOn(fnb, dup);
474 			return fnb;
475 		}
476 		ewprintf("adjustname: PathName() failed!");
477 		UnLock(lock);
478 	}
479 #endif
480 	return fn;				/* if all else fails	*/
481 }
482 
483 #ifndef	AMIGA_STDIO
484 /*
485  * Functions to read/write into the I/O buffer
486  */
487 
FlushBuf()488 int FlushBuf()
489 {
490 	if (niobuf > 0) {
491 		iostat = Write(ffh, iobuf, (ULONG) niobuf);
492 		niobuf = 0;
493 	}
494 }
495 
496 /*
497  * Fill up the input buffer and return the first character in it.
498  */
FillBuf()499 int FillBuf()
500 {
501 	if ((iostat = Read(ffh, iobuf, (ULONG) NIOBUF)) <= 0L)
502 		return (EOF);
503 	ibufo = 0;
504 	niobuf = (int) iostat;
505 	return (int) (iobuf[ibufo++]);
506 }
507 #endif /* not AMIGA_STDIO */
508 
509 #ifndef NO_DIRED
510 
511 #include "kbd.h"
512 
copy(frname,toname)513 copy(frname, toname)
514 char *frname, *toname;
515 {
516 #ifdef MANX
517 	return fexecl("copy", "copy", frname, toname, (char *) 0);
518 #else
519 # ifdef LATTICE
520 	int	error ;
521 	if (error = forkl("copy", "copy", frname, toname, (char *) 0, (char *) 0, 2))
522 		return error ;
523 	return (int) wait(2) ;
524 # else
525 	char buf[NFILEN*2];
526 	sprintf(buf, "copy <>NIL: from %s to %s", frname, toname);
527 	return system(buf);
528 # endif	/* LATTICE */
529 #endif	/* MANX	*/
530 }
531 
dired_(dirname)532 BUFFER *dired_(dirname)
533 char *dirname;
534 {
535     register BUFFER *bp;
536     char line[CMDLINELENGTH];
537     BUFFER *findbuffer();
538     char *tmpname, *mktemp();
539     int i;
540     VOID lfree();
541 
542     if((dirname = adjustname(dirname)) == NULL) {
543 	ewprintf("Bad directory name");
544 	return NULL;
545     }
546     if(!ffisdir(dirname)) {
547 	ewprintf("Not a directory: %s", dirname);
548 	return NULL;
549     }
550     if((bp = findbuffer(dirname)) == NULL) {
551 	ewprintf("Could not create buffer");
552 	return NULL;
553     }
554     bclear(bp);				/* clear out leftover garbage	*/
555     (void) strcpy(line, "list >");
556     (void) strncat(line, tmpname = mktemp("ram:mgXXX.XXX"),
557 		   sizeof(line)-strlen(line)-1);
558     (void) strncat(line, " \"", sizeof(line)-strlen(line)-1);
559     (void) strncat(line, dirname, sizeof(line)-strlen(line)-1);
560     (void) strncat(line, "\"", sizeof(line)-strlen(line)-1);
561     Execute(line, 0L, 0L);
562     if (ffropen(tmpname) != FIOSUC) {
563  	ewprintf("Can't open temporary dir file");
564  	return NULL;
565     }
566     if (ffgetline(line, sizeof(line), &i) != FIOSUC ||
567 	strncmp(line, "Directory", 9) != 0) {
568 	ffclose();
569 	DeleteFile(tmpname);
570 	ewprintf("No such directory: `%s'", dirname);
571     	return NULL;
572     }
573     line[0] = line[1] = ' ';
574     while (ffgetline(&line[2], sizeof(line)-3, &i) == FIOSUC) {
575 	line[i+2] = '\0';
576 	(VOID) addline(bp, line);
577     }
578     ffclose();
579     DeleteFile(tmpname);
580     bp->b_dotp = lforw(bp->b_linep);		/* go to first line */
581     if(bp->b_fname != NULL) free(bp->b_fname);
582     if((bp->b_fname=malloc(strlen(dirname)+1)) != NULL)
583 	(VOID) strcpy(bp->b_fname, dirname);
584 #ifdef EXTD_DIR
585     if(bp->b_cwd != NULL) free(bp->b_cwd);
586     bp->b_cwd = NULL;
587 #endif
588     if((bp->b_modes[0] = name_mode("dired")) == NULL) {
589 	bp->b_modes[0] = &map_table[0];
590 	ewprintf("Could not find mode dired");
591 	return NULL;
592     }
593     bp->b_nmodes = 0;
594     return bp;
595 }
596 
597 #if defined(LATTICE)||defined(_DCC)
598 char *
mktemp(pattern)599 mktemp(pattern)
600 char *pattern;
601 {
602 /* quick hack mktemp for this purpose only */
603 	register char		*name, *printo ;
604 	register unsigned short	counter = 0 ;
605 
606 	if ((name = malloc(strlen(pattern) + 5)) == NULL)
607 		panic("Manx sucks rocks!") ;
608 	(VOID) strcpy(name, pattern) ;
609 	printo = name + strlen(name) ;
610 	do
611 		(void) sprintf(printo, "%d", counter += 1) ;
612 		while (counter > 0 && access(name, 0) == 0) ;
613 	if (counter == 0) panic("Manx _really_ sucks!") ;
614 	return name ;
615 }
616 #endif
617 
618 #define LIST_LINE_LENGTH 58			/* Size of line from List */
619 
d_makename(lp,fn,buflen)620 d_makename(lp, fn, buflen)
621 register LINE *lp;
622 register char *fn;
623 {
624     register char *cp;
625     int n = 2, len;
626 
627     if(llength(lp) < LIST_LINE_LENGTH) return ABORT;
628     if(lgetc(lp, 2) == ':') return ABORT;	/* FileNote line	*/
629     len = strlen(curbp->b_fname) + llength(lp) - 41;
630     if (buflen <= len) return ABORT;
631     cp = fn;
632     (VOID) strcpy(cp, curbp->b_fname);
633     cp += strlen(cp);
634     if ((cp[-1] != ':') && (cp[-1] != '/'))	/* append '/' if needed	*/
635 	*cp++ = '/';
636     while (lgetc(lp, n) != ' ') {
637 	*cp++ = lgetc(lp, n);
638 	n++;
639     }
640     *cp = '\0';
641     for (n=34; n<llength(lp); n++)
642 	if (lgetc(lp,n) == ' ')
643 	    break;
644     for (; n<llength(lp); n++)
645 	if (lgetc(lp,n) != ' ')
646 	    break;
647     return strncmp(&lp->l_text[n], "Dir", 3) == 0;
648 }
649 
ffisdir(name)650 ffisdir(name)
651 char *name;
652 {
653     struct FileLock *lock;
654     struct FileInfoBlock *fib;
655     int result;
656 
657     if ((lock = Lock(name, ACCESS_READ)) == NULL)
658 	return FALSE;
659     if ((fib = (struct FileInfoBlock *)
660 #ifdef	BUGFIX	/* Dec.17,1992 by H.Ohkubo */
661 	   AllocMem((long)sizeof(struct FileInfoBlock),MEMF_CHIP))==NULL) {
662 #else	/* ORIGINAL Code */
663 	   AllocMem((long)sizeof(struct FileInfoBlock),MEMF_PUBLIC))==NULL) {
664 #endif
665 	UnLock(lock);
666 	return FALSE;
667     }
668 #ifdef	BUGFIX	/* Dec.17, 1992 by H.Ohkubo */
669     result = FALSE;
670     if (Examine(lock, fib) != NULL)
671 #endif
672     result = (fib->fib_DirEntryType > 0L) ? TRUE : FALSE;
673     FreeMem(fib,(long)sizeof(struct FileInfoBlock));
674     UnLock(lock);
675     return result;
676 }
677 
678 #endif	/* NO_DIRED */
679 
680 /* Dec.17,1992 Add by H.Ohkubo */
681 #ifndef NO_FILECOMP	/* 90.04.04  by K.Maeda */
682 
683 /* 89.11.20	Original code is for X68K (Human68K).
684  * 90.04.08	Modified for MS-DOS by S.Yoshida.
685  * 90.05.30	Debuged by A.Shirahashi.
686  * Dec.17,1992	Modified for AmigaDos by H.Ohkubo
687  * Find file names starting with name.
688  * Result is stored in *buf, got from malloc();
689  * Return the number of files found, or
690  * -1 of error occured.
691  */
692 
693 #define	MALLOC_STEP	256
694 
fffiles(name,buf)695 fffiles(name, buf)
696 char *name, **buf;
697 {
698 	char	pathbuf[NFILEN], tmpnam[NFILEN];
699 	char	*dirpart, *nampart;
700 	struct	Lock	*lock;
701 	struct	FileInfoBlock	*fib;
702 	int	n, len, size, dirpartlen, nampartlen;
703 	char	*buffer,*BaseName();
704 	void	TackOn();
705 
706 	if ((fib = (struct FileInfoBlock *)
707 	     AllocMem(sizeof(struct FileInfoBlock), MEMF_CHIP)) == NULL) {
708 		return -1;
709 	}
710 
711 	if (!index(name, ':')) {
712 		strcpy(pathbuf, MyDirName);
713 		TackOn(pathbuf, (*name) ? name : "dummy");
714 	}
715 	else {
716 		strcpy(pathbuf, name);
717 	}
718 	dirpart = BaseName(pathbuf);
719 	*dirpart = '\0';
720 	nampart = BaseName(name);
721 	nampartlen = strlen(nampart);
722 	dirpartlen = nampart - name;
723 
724 	if ((lock = (struct Lock*)Lock(pathbuf, SHARED_LOCK)) == NULL) {
725 		FreeMem(fib, sizeof(struct FileInfoBlock));
726 		return -1;
727 	}
728 	if (Examine(lock, fib) == NULL) {
729 		UnLock(lock);
730 		FreeMem(fib, sizeof(struct FileInfoBlock));
731 		return -1;
732 	}
733 	if ((buffer = malloc(MALLOC_STEP)) == NULL) {
734 		UnLock(lock);
735 		FreeMem(fib, sizeof(struct FileInfoBlock));
736 		return -1;
737 	}
738 	size = MALLOC_STEP;
739 	len = 0;
740 	n = 0;
741 
742 	while (ExNext(lock, fib)) {
743 		register int l;
744 
745 		if (Strncmp(nampart, fib->fib_FileName, nampartlen) != 0)
746 			continue;
747 		strncpy(tmpnam, name, dirpartlen);
748 		strcpy(tmpnam + dirpartlen, fib->fib_FileName);
749 		if (fib->fib_DirEntryType > 0) {
750 			strcat(tmpnam, "/");
751 		}
752 		l = strlen(tmpnam) + 1;
753 		if (l > 3 && (stricmp(&tmpnam[l-3],".O") == 0))
754 			continue;
755 		if (l + len >= size) {
756 				/* make room for double null */
757 			if ((buffer = realloc(buffer, size += MALLOC_STEP)) == NULL) {
758 				UnLock(lock);
759 				FreeMem(fib, sizeof(struct FileInfoBlock));
760 				return -1;
761 			}
762 		}
763 		strcpy(buffer + len, tmpnam);
764 		len += l;
765 		n++;
766 	}
767 
768 	UnLock(lock);
769 	FreeMem(fib, sizeof(struct FileInfoBlock));
770 
771 	*buf = buffer;
772 	buffer[len] = '\0';
773 	return(n);
774 }
775 #endif	/* NO_FILECOMP */
776 
777 
778 #ifdef	NEW_COMPLETE	/* Dec.17,1992 Add by H.Ohkubo */
779 char *
copy_dir_name(d,s)780 copy_dir_name (d, s)
781 char	*d;
782 char	*s;
783 {
784 	int	i;
785 	char *BaseName();
786 
787 	i = BaseName(s) - s;
788 	strncpy (d, s, i);
789 	d[i] = '\0';
790 	return (d);
791 }
792 #endif	/* NEW_COMPLETE */
793 
794 #ifndef USE_ARP
795 
796 /*
797  * Here are work-alikes for the few ARP commands now used by the
798  * Amiga version of mg.  These may go away if we require ARP in future.
799  */
800 #define	LOWER(c)	(ISUPPER(c) ? TOLOWER(c) : (c))	/* By H.Ohkubo */
801 
Strcmp(s1,s2)802 Strcmp(s1, s2)
803 register char *s1, *s2;
804 {
805 	while (LOWER(*s1) == LOWER(*s2)) {	/* tolower -> LOWER */
806 		if (*s1 == '\0')		/* Modified by H.Ohkubo */
807 			return 0;
808 		s1++; s2++;
809 	}
810 	return (LOWER(*s1) < LOWER(*s2) ? -1 : 1);
811 }
812 
Strncmp(s1,s2,n)813 Strncmp(s1, s2, n)	/* Dec.20,1992 By H.Ohkubo */
814 register char	*s1, *s2;
815 register int	n;
816 {
817 	int	c1, c2;
818 
819 	while (n > 0 && *s1 != '\0' && *s2 != '\0') {
820 		c1 = LOWER(*s1);
821 		c2 = LOWER(*s2);
822 		if (c1 != c2)
823 			return c1 < c2 ? -1 : 1;
824 		s1++; s2++; n--;
825 	}
826 	if (n == 0)
827 		return 0;
828 	else
829 		return c1 < c2 ? -1 : 1;
830 }
831 
832 /*
833  * This PathName function shamelessly stolen from the Matt Dillon Shell.
834  * It is a slight mod of that program's get_pwd routine, from comm1.c.
835  */
836 long
PathName(flock,pwdstr,nentries)837 PathName(flock, pwdstr, nentries)
838 struct Lock *flock;
839 long nentries;
840 char *pwdstr;
841 {
842    char *ptr;
843    char *name;
844    int err=0;
845 
846    struct FileLock *lock, *newlock, *ParentDir(), *DupLock();
847    long Examine();
848    struct FileInfoBlock *fib;
849    int i, len, n;
850 
851    lock = DupLock(flock);
852    n = nentries * FCHARS + 1;
853 
854    fib = (struct FileInfoBlock *)AllocMem((long)sizeof(struct FileInfoBlock),
855 #ifdef	BUGFIX	/* Dec. 17, 1992 by H.Ohkubo */
856 					MEMF_CHIP);
857 #else	/* ORIGINAL Code */
858    					  MEMF_PUBLIC);
859 #endif
860    pwdstr[i = n-1] = '\0';
861 
862    while (lock) {
863       newlock = ParentDir(lock);
864       if (!Examine(lock, fib)) ++err;
865       name = fib->fib_FileName;
866       if (*name == '\0')	    /* HACK TO FIX RAM: DISK BUG */
867 	 name = "RAM";
868       len = strlen(name);
869       if (newlock) {
870 	 if (i == n-1) {
871 	    i -= len;
872 	    bcopy(name, pwdstr + i, len);
873 	 } else {
874 	    i -= len + 1;
875 	    bcopy(name, pwdstr + i, len);
876 	    pwdstr[i+len] = '/';
877 	 }
878       } else {
879 	 i -= len + 1;
880 	 bcopy(name, pwdstr + i, len);
881 	 pwdstr[i+len] = ':';
882       }
883       UnLock(lock);
884       lock = newlock;
885    }
886    FreeMem(fib, (long)sizeof(struct FileInfoBlock));
887    bcopy(pwdstr + i, pwdstr, n - i);
888    if (err) return(0L);
889    return((long) n - i - 1);
890 }
891 
TackOn(path,file)892 void TackOn(path, file)
893 char *path, *file;
894 {
895 	if (*file != '\0') {
896 		if (path[strlen(path)-1] != ':')
897 			strcat(path, "/");
898 		strcat(path, file);
899 	}
900 }
901 
902 #ifdef	NEW_COMPLETE	/* Dec.20,1992 by H.Ohkubo */
903 char *
BaseName(pathname)904 BaseName(pathname)
905 char	*pathname;
906 {
907 	char	*cp, *dirpart;
908 
909 	dirpart = NULL;
910 	for (cp = pathname; *cp; cp++) {
911 		if (*cp == '/' || (dirpart == NULL && *cp == ':')) {
912 			dirpart = cp;
913 		}
914 	}
915 	if (dirpart)
916 		++dirpart;
917 	else
918 		dirpart = pathname;
919 
920 	return dirpart;
921 }
922 #endif	/* NEW_COMPLETE */
923 #endif	/* USE_ARP */
924 
925 #ifdef	AUTOSAVE
926 VOID
autosave_name(buff,name,buflen)927 autosave_name(buff, name, buflen)
928 char* buff;
929 char* name;
930 {
931     strcpy(buff, name);
932     if (strlen(name)) {
933 	char *fn = rindex(name, '/');
934 	if (fn == NULL)
935 	    fn = rindex(name, ':');
936 	if (fn == NULL){
937 	    fn = buff;
938 	} else {
939 	    fn++;
940 	}
941 	strcpy(&buff[strlen(buff)-strlen(fn)], "#");
942 	strcat(buff, fn);
943 	strcat(buff, "#");
944     }
945 }
946 #endif	/* AUTOSAVE */
947