1 /* $Id: fileio.c,v 1.1.1.1.2.1 2000/12/01 10:01:57 amura Exp $ */
2 /*
3 * sys V fileio.c
4 */
5
6 /*
7 * $Log: fileio.c,v $
8 * Revision 1.1.1.1.2.1 2000/12/01 10:01:57 amura
9 * fix problems open "/" and sybolic link directory
10 *
11 * Revision 1.1.1.1 2000/06/27 01:47:59 amura
12 * import to CVS
13 *
14 */
15 /* 90.01.29 Modified for Ng 1.0 by S.Yoshida */
16
17 #include "config.h" /* 90.12.20 by S.Yoshida */
18 #include "def.h"
19
20 static FILE *ffp;
21 extern char *getenv();
22 char *adjustname();
23
24 #ifdef SUPPORT_ANSI
25 #include <string.h>
26 #include <unistd.h>
27 #else
28 # ifndef strncpy
29 extern char *strncpy();
30 # endif
31 #endif
32 #include <sys/types.h>
33 #include <sys/wait.h>
34
35 /*
36 * Open a file for reading.
37 */
ffropen(fn)38 ffropen(fn) char *fn; {
39 if ((ffp=fopen(fn, "r")) == NULL)
40 return (FIOFNF);
41 return (FIOSUC);
42 }
43
44 /*
45 * Open a file for writing.
46 * Return TRUE if all is well, and
47 * FALSE on error (cannot create).
48 */
ffwopen(fn)49 ffwopen(fn) char *fn; {
50 if ((ffp=fopen(fn, "w")) == NULL) {
51 ewprintf("Cannot open file for writing");
52 return (FIOERR);
53 }
54 return (FIOSUC);
55 }
56
57 /*
58 * Close a file.
59 * Should look at the status.
60 */
ffclose()61 ffclose() {
62 (VOID) fclose(ffp);
63 return (FIOSUC);
64 }
65
66 /*
67 * Write a buffer to the already
68 * opened file. bp points to the
69 * buffer. Return the status.
70 * Check only at the newline and
71 * end of buffer.
72 */
ffputbuf(bp)73 ffputbuf(bp)
74 BUFFER *bp;
75 {
76 register char *cp;
77 register char *cpend;
78 register LINE *lp;
79 register LINE *lpend;
80 #ifdef KANJI /* 90.01.30 by S.Yoshida */
81 register int kfio;
82 #endif /* KANJI */
83
84 lpend = bp->b_linep;
85 #ifdef KANJI /* 90.02.07 by S.Yoshida */
86 if (bp->b_kfio == NIL)
87 ksetbufcode(bp); /* Set buffer local KANJI code. */
88 kfio = bp->b_kfio;
89 #endif /* KANJI */
90 lp = lforw(lpend);
91 do {
92 cp = <ext(lp)[0]; /* begining of line */
93 cpend = &cp[llength(lp)]; /* end of line */
94 while(cp != cpend) {
95 #ifdef KANJI /* 90.01.30 by S.Yoshida */
96 kputc(*cp, ffp, kfio);
97 #else /* NOT KANJI */
98 putc(*cp, ffp);
99 #endif /* KANJI */
100 cp++; /* putc may evalualte arguments more than once */
101 }
102 #ifdef KANJI /* 90.01.30 by S.Yoshida */
103 if (kfio == JIS) {
104 kfselectcode(ffp, FALSE);
105 }
106 #endif /* KANJI */
107 lp = lforw(lp);
108 if(lp == lpend) break; /* no implied newline on last line */
109 putc('\n', ffp);
110 } while(!ferror(ffp));
111 if(ferror(ffp)) {
112 ewprintf("Write I/O error");
113 return FIOERR;
114 }
115 return FIOSUC;
116 }
117
118 /*
119 * Read a line from a file, and store the bytes
120 * in the supplied buffer. Stop on end of file or end of
121 * line. When FIOEOF is returned, there is a valid line
122 * of data without the normally implied \n.
123 */
ffgetline(buf,nbuf,nbytes)124 ffgetline(buf, nbuf, nbytes)
125 register char *buf;
126 register int nbuf;
127 register int *nbytes;
128 {
129 register int c;
130 register int i;
131
132 i = 0;
133 while((c = getc(ffp))!=EOF && c!='\n') {
134 buf[i++] = c;
135 if (i >= nbuf) return FIOLONG;
136 }
137 if (c == EOF && ferror(ffp) != FALSE) {
138 ewprintf("File read error");
139 return FIOERR;
140 }
141 *nbytes = i;
142 return c==EOF ? FIOEOF : FIOSUC;
143 }
144
145 #ifndef NO_BACKUP
146 /*
147 * Rename the file "fname" into a backup
148 * copy. On Unix the backup has the same name as the
149 * original file, with a "~" on the end; this seems to
150 * be newest of the new-speak. The error handling is
151 * all in "file.c". The "unlink" is perhaps not the
152 * right thing here; I don't care that much as
153 * I don't enable backups myself.
154 */
fbackupfile(fn)155 fbackupfile(fn) char *fn; {
156 register char *nname;
157
158 if ((nname=malloc((unsigned)(strlen(fn)+1+1))) == NULL) {
159 ewprintf("Can't get %d bytes", strlen(fn) + 1);
160 return (ABORT);
161 }
162 (void) strcpy(nname, fn);
163 (void) strcat(nname, "~");
164 (void) unlink(nname); /* Ignore errors. */
165 if (rename(fn, nname) < 0) {
166 free(nname);
167 return (FALSE);
168 }
169 free(nname);
170 return (TRUE);
171 }
172
173 #ifdef BUGFIX /* 90.02.14 by S.Yoshida */
174 #ifndef _SYS_STAT_H_
175 #include <sys/stat.h>
176 #define _SYS_STAT_H_
177 #endif /* _SYS_STAT_H_ */
178 /*
179 * Get file mode of a file fn.
180 */
fgetfilemode(fn)181 fgetfilemode(fn)
182 char *fn;
183 {
184 struct stat filestat;
185
186 stat(fn, &filestat);
187 return(filestat.st_mode & 0x0fff);
188 }
189
190 /*
191 * Set file mode of a file fn to the specified mode.
192 */
fsetfilemode(fn,mode)193 fsetfilemode(fn, mode)
194 char *fn;
195 int mode;
196 {
197 chmod(fn, mode);
198 }
199 #endif /* BUGFIX */
200 #endif
201
202 #ifdef READONLY /* 91.01.05 by S.Yoshida */
203 #ifndef _SYS_STAT_H_
204 #include <sys/stat.h>
205 #define _SYS_STAT_H_
206 #endif /* _SYS_STAT_H_ */
207 /*
208 * Check whether file is read-only of a file fn.
209 */
fchkreadonly(fn)210 fchkreadonly(fn)
211 char *fn;
212 {
213 struct stat filestat;
214
215 if (stat(fn, &filestat) == 0) {
216 return(!(filestat.st_mode & S_IWRITE));
217 } else {
218 return FALSE;
219 }
220 }
221 #endif /* READONLY */
222
223 /*
224 * The string "fn" is a file name.
225 * Perform any required appending of directory name or case adjustments.
226 * If NO_DIR is not defined, the same file should be refered to even if the
227 * working directory changes.
228 */
229 #ifdef SYMBLINK
230 #ifndef BUGFIX /* 90.02.15 by S.Yoshida: Previously included. */
231 #include <sys/types.h>
232 #endif /* BUGFIX */
233 #ifndef _SYS_STAT_H_ /* 90.02.15 by S.Yoshida */
234 #include <sys/stat.h>
235 #define _SYS_STAT_H_
236 #endif /* _SYS_STAT_H_ */
237 #ifndef MAXLINK
238 #define MAXLINK 8 /* maximum symbolic links to follow */
239 #endif
240 #endif
241 #include <pwd.h>
242 #ifndef NO_DIR
243 extern char *wdir;
244 #endif
245
adjustname(fn)246 char *adjustname(fn)
247 register char *fn;
248 {
249 register char *cp;
250 static char fnb[NFILEN];
251 struct passwd *pwent, *getpwnam();
252 #ifdef SYMBLINK
253 struct stat statbuf;
254 int i, j;
255 char linkbuf[NFILEN];
256 #endif
257
258 switch(*fn) {
259 case '/':
260 cp = fnb;
261 *cp++ = *fn++;
262 break;
263 case '~':
264 fn++;
265 if(*fn == '/' || *fn == '\0') {
266 (VOID) strcpy(fnb, getenv("HOME"));
267 cp = fnb + strlen(fnb);
268 if(*fn) fn++;
269 break;
270 } else {
271 cp = fnb;
272 while(*fn && *fn != '/') *cp++ = *fn++;
273 *cp = '\0';
274 if((pwent = getpwnam(fnb)) != NULL) {
275 (VOID) strcpy(fnb, pwent->pw_dir);
276 cp = fnb + strlen(fnb);
277 break;
278 } else {
279 fn -= strlen(fnb) + 1;
280 /* can't find ~user, continue to default case */
281 }
282 }
283 default:
284 #ifndef NODIR
285 strcpy(fnb, wdir);
286 cp = fnb + strlen(fnb);
287 break;
288 #else
289 return fn; /* punt */
290 #endif
291 }
292 if(cp != fnb && cp[-1] != '/') *cp++ = '/';
293 while(*fn) {
294 switch(*fn) {
295 case '.':
296 switch(fn[1]) {
297 case '\0':
298 *--cp = '\0';
299 return fnb;
300 case '/':
301 fn += 2;
302 continue;
303 case '.':
304 if(fn[2]=='/' || fn[2] == '\0') {
305 #ifdef SYMBLINK
306 cp[-1] = '\0';
307 for(j = MAXLINK; j-- &&
308 lstat(fnb, &statbuf) != -1 &&
309 (statbuf.st_mode&S_IFMT) == S_IFLNK &&
310 (i = readlink(fnb, linkbuf, sizeof linkbuf))
311 != -1 ;) {
312 if(linkbuf[0] != '/') {
313 --cp;
314 while(cp > fnb && *--cp != '/') {}
315 ++cp;
316 (VOID) strncpy(cp, linkbuf, i);
317 cp += i;
318 } else {
319 (VOID) strncpy(fnb, linkbuf, i);
320 cp = fnb + i;
321 }
322 if(cp[-1]!='/') *cp++ = '\0';
323 else cp[-1] = '\0';
324 }
325 cp[-1] = '/';
326 #endif
327 --cp;
328 while(cp > fnb && *--cp != '/') {}
329 ++cp;
330 if(fn[2]=='\0') {
331 *--cp = '\0';
332 return fnb;
333 }
334 fn += 3;
335 continue;
336 }
337 break;
338 default:
339 break;
340 }
341 break;
342 case '/':
343 fn++;
344 continue;
345 default:
346 break;
347 }
348 while(*fn && (*cp++ = *fn++) != '/') {}
349 }
350 if((cp-1)!=fnb && cp[-1]=='/') --cp;
351 *cp = '\0';
352 return fnb;
353 }
354
355 #ifndef NO_STARTUP
356 #include <sys/file.h>
357 #ifndef F_OK
358 #define F_OK 04 /* for stupid Sys V */
359 #endif
360
361 /*
362 * Find a startup file for the user and return its name. As a service
363 * to other pieces of code that may want to find a startup file (like
364 * the terminal driver in particular), accepts a suffix to be appended
365 * to the startup file name.
366 */
367 char *
368 #ifdef ADDOPT
startupfile(ngrcfile,suffix)369 startupfile(ngrcfile, suffix)
370 char* ngrcfile;
371 #else
372 startupfile(suffix)
373 #endif
374 char *suffix;
375 {
376 register char *file;
377 static char home[NFILEN];
378 char *getenv();
379
380
381 #ifdef ADDOPT
382 if (ngrcfile == NULL)
383 ngrcfile = getenv("NGRC");
384 if (ngrcfile != NULL)
385 if (access(ngrcfile, F_OK) == 0) return ngrcfile;
386 #endif
387 if ((file = getenv("HOME")) == NULL) goto notfound;
388 if (strlen(file)+7 >= NFILEN - 1) goto notfound;
389 (VOID) strcpy(home, file);
390 #ifdef KANJI /* 90.02.10 by S.Yoshida */
391 (VOID) strcat(home, "/.ng");
392 #else /* NOT KANJI */
393 (VOID) strcat(home, "/.mg");
394 #endif /* KANJI */
395 if (suffix != NULL) {
396 (VOID) strcat(home, "-");
397 (VOID) strcat(home, suffix);
398 }
399 if (access(home, F_OK) == 0) return home;
400
401 notfound:
402 #ifdef STARTUPFILE
403 file = STARTUPFILE;
404 if (suffix != NULL) {
405 (VOID) strcpy(home, file);
406 (VOID) strcat(home, "-");
407 (VOID) strcat(home, suffix);
408 file = home;
409 }
410 if (access(file, F_OK ) == 0) return file;
411 #endif
412
413 return NULL;
414 }
415 #endif
416
417 #ifndef NO_DIRED
418 #include "kbd.h"
419
copy(frname,toname)420 copy(frname, toname)
421 char *frname, *toname;
422 {
423 int pid;
424 int status;
425
426 #ifdef BUGFIX /* 91.01.11 by Y.Kaneko */
427 if((pid = fork()) == 0) {
428 #else /* ORIGINAL */
429 if(pid = fork()) {
430 if(pid == -1) return -1;
431 #endif /* BUGFIX */
432 execl("/bin/cp", "cp", frname, toname, (char *)NULL);
433 _exit(1); /* shouldn't happen */
434 }
435 #ifdef BUGFIX /* 91.01.11 by Y.Kaneko */
436 if(pid == -1) return -1;
437 #endif /* BUGFIX */
438 while(wait(&status) != pid)
439 ;
440 return status == 0;
441 }
442
dired_(dirname)443 BUFFER *dired_(dirname)
444 char *dirname;
445 {
446 register BUFFER *bp;
447 char line[256];
448 BUFFER *findbuffer();
449 FILE *dirpipe;
450 FILE *popen();
451
452 if((dirname = adjustname(dirname)) == NULL) {
453 ewprintf("Bad directory name");
454 return NULL;
455 }
456 #ifdef BUGFIX /* 90.02.06 by S.Yoshida */
457 if(dirname[strlen(dirname)-1] != '/') (VOID) strcat(dirname, "/");
458 #endif /* BUGFIX */
459 if((bp = findbuffer(dirname)) == NULL) {
460 ewprintf("Could not create buffer");
461 return NULL;
462 }
463 if(bclear(bp) != TRUE) return FALSE;
464 #ifdef EXTD_DIR
465 strncpy(bp->b_cwd, dirname, NFILEN);
466 ensurecwd();
467 #endif
468 #ifdef BUGFIX /* 91.02.04 by M.Oki */
469 (VOID) strcpy(line, "/bin/ls -al ");
470 (VOID) strcpy(&line[12], dirname);
471 #else /* ORIGINAL */
472 (VOID) strcpy(line, "ls -al ");
473 (VOID) strcpy(&line[7], dirname);
474 #endif /* BUGFIX */
475 if((dirpipe = popen(line, "r")) == NULL) {
476 ewprintf("Problem opening pipe to ls");
477 return NULL;
478 }
479 line[0] = line[1] = ' ';
480 while(fgets(&line[2], 254, dirpipe) != NULL) {
481 line[strlen(line) - 1] = '\0'; /* remove ^J */
482 (VOID) addline(bp, line);
483 }
484 if(pclose(dirpipe) == -1) {
485 ewprintf("Problem closing pipe to ls");
486 return NULL;
487 }
488 bp->b_dotp = lforw(bp->b_linep); /* go to first line */
489 (VOID) strncpy(bp->b_fname, dirname, NFILEN);
490 if((bp->b_modes[0] = name_mode("dired")) == NULL) {
491 bp->b_modes[0] = &map_table[0];
492 ewprintf("Could not find mode dired");
493 return NULL;
494 }
495 bp->b_nmodes = 0;
496 return bp;
497 }
498
d_makename(lp,fn)499 d_makename(lp, fn)
500 register LINE *lp;
501 register char **fn;
502 {
503 char* cp;
504 int l,l1,len;
505 char c;
506
507 /* '56' is a magic number and is not correct always */
508
509 if ( llength( lp ) <= 56 ) {
510 return ABORT ;
511 }
512 l = llength(lp);
513
514 if (lgetc(lp, 2) == 'l') {
515 do {
516 while (l > 2 && lgetc(lp, l) != ' ')
517 l--;
518 if (bcmp(lp->l_text + l - 3, " -> ", 4) == 0)
519 break;
520 l--;
521 } while (l > 2);
522 }
523 else {
524 do {
525 while (l > 2 && lgetc(lp, l)!=' ')
526 l--;
527 l1 = l;
528 while (l > 2 && lgetc(lp, l)==' ')
529 l--;
530 while (l > 2 && (c=lgetc(lp, l))!=' ') {
531 if (c!=':' && (c<'0'&&c>'9')) {
532 break;
533 }
534 l--;
535 }
536 } while (l > 2 && c != ' ');
537 l = l1;
538 }
539 if (l <= 2)
540 return ABORT;
541 l++;
542
543 len = llength(lp) - l + 1;
544 cp = malloc(len + strlen(curbp->b_fname) + 1);
545 if (cp) {
546 *fn = cp;
547 strcpy(cp, curbp->b_fname);
548 cp += strlen(cp);
549 bcopy(lp->l_text + l, cp, len);
550 cp[len-1] = '\0';
551 #ifdef SYMBLINK
552 if (lgetc(lp, 2) == 'l')
553 return ffisdir(curbp->b_fname);
554 #endif
555 return lgetc(lp, 2) == 'd';
556 }
557 else {
558 return ABORT;
559 }
560 }
561
562 /*
563 * I, a System V novice, could only figure out how to do unlinkdir()
564 * and rename() as exec's of the appropriate functions. So sue me.
565 * --Stephen Walton, December 1987
566 *
567 * Now, SystemV has rmdir (form Release3) and rename (form Release 4).
568 * I rewrite Ng use them.
569 * --amura, 03 Apr 2000
570 */
571
572 #ifdef SVR2
unlinkdir(f)573 unlinkdir(f) /* System V Release 2 don't have rmdir(2)? */
574 char *f;
575 {
576 int status, pid, wpid;
577
578 if ((pid = fork()) == 0)
579 execl("/bin/rmdir", "rmdir", f, (char *)NULL);
580 else if (pid > 0)
581 while ((wpid = wait(&status)) && wpid != pid)
582 ;
583 else
584 return FALSE;
585 return status == 0;
586 }
587 #endif
588
589 #ifndef SVR4
rename(f1,f2)590 rename(f1, f2) /* System V Release 2/3 don't have rename(2)? */
591 char *f1, *f2;
592 {
593
594 int status, pid, wpid;
595
596 if ((pid = fork()) == 0)
597 execl("/bin/mv", "mv", f1, f2, (char *)NULL);
598 else if (pid > 0)
599 while ((wpid = wait(&status)) && wpid != pid)
600 ;
601 else
602 return FALSE;
603 return status == 0;
604 }
605 #endif /* SVR4 */
606 #endif /* NO_DIRED */
607
608 #ifndef NO_DIRED /* 91.01.15 by K.Maeda */
609 #ifndef _SYS_STAT_H_
610 #include <sys/stat.h>
611 #define _SYS_STAT_H_
612 #endif /* _SYS_STAT_H_ */
613 /*
614 * Check whether file "dn" is directory.
615 */
ffisdir(dn)616 ffisdir(dn)
617 char *dn;
618 {
619 struct stat filestat;
620
621 if (stat(dn, &filestat) == 0) {
622 return ((filestat.st_mode & S_IFMT) == S_IFDIR);
623 } else {
624 return FALSE;
625 }
626 }
627 #endif /* NO_DIRED */
628
629 #ifndef NO_FILECOMP /* 90.04.04 by K.Maeda */
630 #ifndef SVR2 /* 91.01.29 SVR3 or later. by S.Yoshida */
631 #include <dirent.h> /* 90.07.16 <sys/dir.h> -> <dirent.h> by Y.Nimura */
632 #else /* SVR2 */
633 #include <sys/dir.h>
634 #include <fcntl.h>
635 #endif /* SVR2 */
636
637 /* 89.11.20 Original code is for X68K (Human68K).
638 * 90.07.05 Modified for System V UNIX by S.Yoshida
639 * This routine may be compiled only in SysV Rel 3 or later.
640 * 90.07.16 Debuged by Y.Nimura.
641 * 91.01.29 Debug for SysV Rel 2. by S.Yoshida
642 * Find file names starting with name.
643 * Result is stored in *buf, got from malloc();
644 * Return the number of files found, or
645 * -1 of error occured.
646 */
647
648 #define MALLOC_STEP 256
649
fffiles(name,buf)650 fffiles(name, buf)
651 char *name, **buf;
652 {
653 char pathbuf[128], tmpnam[128];
654 char *cp, *dirpart, *nampart;
655 #ifndef SVR2 /* 91.01.29 SVR3 or later. by S.Yoshida */
656 /* 90.07.16 direct -> dirent by Y.Nimura */
657 DIR *dp;
658 register struct dirent *dirent;
659 #else /* SVR2 */
660 int dp;
661 struct direct dirbuf;
662 register struct direct *dirent = &dirbuf;
663 #endif /* SVR2 */
664 int n, len, size, dirpartlen, nampartlen;
665 char *buffer;
666 struct stat st;
667
668 strcpy(pathbuf, name);
669 dirpart = NULL;
670 for (cp = pathbuf; *cp; cp++) {
671 if (*cp == '/')
672 dirpart = cp;
673 }
674 if (dirpart) {
675 *++dirpart = '\0';
676 dirpartlen = dirpart-pathbuf;
677 } else {
678 strcpy(pathbuf, "./");
679 dirpartlen = 0;
680 }
681 nampart = name + dirpartlen;
682 nampartlen = strlen(nampart);
683
684 #ifndef NEW_COMPLETE /* 90.12.10 Sawayanagi Yosirou */
685 #ifndef SVR2 /* 91.02.04 SVR3 or later. by Y.Nimura */
686 if ((dp = opendir(pathbuf)) == NULL)
687 #else /* SVR2 */
688 if ((dp = open(pathbuf,O_RDONLY)) < 0)
689 #endif /* SVR2 */
690 return -1;
691 #endif /* NOT NEW_COMPLETE */
692
693 buffer = malloc(MALLOC_STEP);
694 if (buffer == NULL)
695 return -1;
696 size = MALLOC_STEP;
697 len = 0; n = 0;
698
699 #ifdef NEW_COMPLETE /* 90.12.10 Sawayanagi Yosirou */
700 #ifndef SVR2 /* 91.02.04 SVR3 or later. by Y.Nimura */
701 if ((dp = opendir(pathbuf)) == NULL) {
702 #else /* SVR2 */
703 if ((dp = open(pathbuf,O_RDONLY)) < 0) {
704 #endif /* SVR2 */
705 *buf = buffer;
706 buffer[0] = '\0';
707 return 0;
708 }
709 #endif /* NEW_COMPLETE */
710
711 #ifndef SVR2 /* 91.02.04 SVR3 or later. by Y.Nimura */
712 while ((dirent = readdir(dp)) != NULL) {
713 #else /* SVR2 */
714 while (read(dp,dirent,sizeof(struct direct)) == sizeof(struct direct)) {
715 #endif /* SVR2 */
716 register int l;
717 #ifdef SVR2 /* 91.02.04 by Y.Nimura */
718 if (dirent->d_ino == 0) continue;
719 #endif /* SVR2 */
720 if (strncmp(nampart, dirent->d_name, nampartlen) != 0)
721 goto nomatch; /* case-sensitive comparison */
722 strncpy(tmpnam, pathbuf, dirpartlen);
723 strcpy(tmpnam+dirpartlen, dirent->d_name);
724 if (stat(tmpnam, &st) < -1) goto nomatch;
725 if ((st.st_mode & S_IFMT)==S_IFDIR)
726 strcat(tmpnam, "/");
727 l = strlen(tmpnam)+1;
728 if (l > 3 && tmpnam[l-3] == '.' && tmpnam[l-2] == 'o')
729 goto nomatch;
730 if (l+len >= size) {
731 /* make room for double null */
732 if ((buffer = realloc(buffer, size += MALLOC_STEP)) == NULL)
733 return -1;
734 }
735 strcpy(buffer+len, tmpnam);
736 len += l;
737 n++;
738 nomatch:;
739 }
740 #ifndef SVR2 /* 91.02.04 SVR3 or later. by Y.Nimura */
741 closedir(dp);
742 #else /* SVR2 */
743 close(dp);
744 #endif /* SVR2 */
745
746 *buf = buffer;
747 buffer[len] = '\0';
748 return n;
749 }
750 #endif
751
752 #ifdef NEW_COMPLETE /* 90.12.10 Sawayanagi Yosirou */
753 char *
file_name_part(s)754 file_name_part (s)
755 char *s;
756 {
757 int i;
758
759 for (i = strlen (s); i > 0; i--)
760 {
761 if (s[i - 1] == '/')
762 break;
763 }
764 return (s + i);
765 }
766
767 char *
copy_dir_name(d,s)768 copy_dir_name (d, s)
769 char *d;
770 char *s;
771 {
772 int i;
773
774 i = file_name_part (s) - s;
775 strncpy (d, s, i);
776 d[i] = '\0';
777 return (d);
778 }
779 #endif /* NEW_COMPLETE */
780