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