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