1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
3      Written by James Clark (jjc@jclark.com)
4 
5 This file is part of groff.
6 
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11 
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING.  If not, write to the Free Software
19 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <assert.h>
25 
26 #include "lib.h"
27 #include "searchpath.h"
28 
search_path(const char * envvar,const char * standard)29 search_path::search_path(const char *envvar, const char *standard)
30 {
31   char *e = envvar ? getenv(envvar) : 0;
32   if (e && standard) {
33     dirs = new char[strlen(e) + strlen(standard) + 2];
34     strcpy(dirs, e);
35     strcat(dirs, ":");
36     strcat(dirs, standard);
37   }
38   else
39     dirs = strsave(e ? e : standard);
40   init_len = dirs ? strlen(dirs) : 0;
41 }
42 
~search_path()43 search_path::~search_path()
44 {
45   if (dirs)
46     a_delete dirs;
47 }
48 
command_line_dir(const char * s)49 void search_path::command_line_dir(const char *s)
50 {
51   if (!dirs)
52     dirs = strsave(s);
53   else {
54     char *old = dirs;
55     unsigned old_len = strlen(old);
56     unsigned slen = strlen(s);
57     dirs = new char[old_len + 1 + slen + 1];
58     memcpy(dirs, old, old_len - init_len);
59     char *p = dirs;
60     p += old_len - init_len;
61     if (init_len == 0)
62       *p++ = ':';
63     memcpy(p, s, slen);
64     p += slen;
65     if (init_len > 0) {
66       *p++ = ':';
67       memcpy(p, old + old_len - init_len, init_len);
68       p += init_len;
69     }
70     *p++ = '\0';
71     a_delete old;
72   }
73 }
74 
open_file(const char * name,char ** pathp)75 FILE *search_path::open_file(const char *name, char **pathp)
76 {
77   assert(name != 0);
78   if (*name == '/' || dirs == 0 || *dirs == '\0') {
79     FILE *fp = fopen(name, "r");
80     if (fp) {
81       if (pathp)
82 	*pathp = strsave(name);
83       return fp;
84     }
85     else
86       return 0;
87   }
88   unsigned namelen = strlen(name);
89   char *p = dirs;
90   for (;;) {
91     char *end = strchr(p, ':');
92     if (!end)
93       end = strchr(p, '\0');
94     int need_slash = end > p && end[-1] != '/';
95     char *path = new char[(end - p) + need_slash + namelen + 1];
96     memcpy(path, p, end - p);
97     if (need_slash)
98       path[end - p] = '/';
99     strcpy(path + (end - p) + need_slash, name);
100 #if 0
101     fprintf(stderr, "trying `%s'\n", path);
102 #endif
103     FILE *fp = fopen(path, "r");
104     if (fp) {
105       if (pathp)
106 	*pathp = path;
107       else
108 	a_delete path;
109       return fp;
110     }
111     a_delete path;
112     if (*end == '\0')
113       break;
114     p = end + 1;
115   }
116   return 0;
117 }
118