]>
git.saurik.com Git - apple/shell_cmds.git/blob - path_helper/path_helper.c
2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
32 fprintf(stderr
, "usage: path_helper [-c | -s]");
36 // Append path segment if it does not exist. Reallocate
37 // the path buffer as necessary.
39 int append_path_segment(char** path
, const char* segment
) {
40 if (*path
== NULL
|| segment
== NULL
) return -1;
42 size_t pathlen
= strlen(*path
);
43 size_t seglen
= strlen(segment
);
45 if (seglen
== 0) return 0;
47 // Does the segment already exist in the path?
49 char* match
= strstr(*path
, segment
);
51 if ((match
== *path
|| match
[-1] == ':') &&
52 (match
[seglen
] == ':' || match
[seglen
] == 0)) {
55 match
= strstr(match
+1, segment
);
58 // size = pathlen + ':' + segment + '\0'
59 size_t size
= pathlen
+ seglen
+ 2;
60 *path
= reallocf(*path
, size
);
61 if (*path
== NULL
) return -1;
63 if (pathlen
> 0) strlcat(*path
, ":", size
);
64 strlcat(*path
, segment
, size
);
68 // Convert fgetln output into a sanitized segment
69 // escape quotes, dollars, etc.
70 char* read_segment(const char* line
, size_t len
) {
74 for (i
= 0; i
< len
; ++i
) {
76 if (c
== '\"' || c
== '\'' || c
== '$') {
81 size_t size
= len
+ escapes
+ 1;
83 char* segment
= calloc(1, size
);
84 if (segment
== NULL
) return NULL
;
86 for (i
= 0, j
= 0; i
< len
; ++i
, ++j
) {
88 if (c
== '\"' || c
== '\'' || c
== '$') {
91 } else if (c
== '\n') {
102 // Construct a path variable, starting with the contents
103 // of the given environment variable, adding the contents
104 // of the default file and files in the path directory.
106 char* construct_path(char* env_var
, char* defaults_path
, char* dir_path
) {
110 char* result
= calloc(sizeof(char), 1);
112 char* dirpathv
[] = { defaults_path
, dir_path
, NULL
};
113 fts
= fts_open(dirpathv
, FTS_PHYSICAL
| FTS_XDEV
, NULL
);
119 while ((ent
= fts_read(fts
)) != NULL
) {
120 // only interested in regular files, one level deep
121 if (ent
->fts_info
!= FTS_F
) {
122 if (ent
->fts_level
>= 1) fts_set(fts
, ent
, FTS_SKIP
);
126 FILE* f
= fopen(ent
->fts_accpath
, "r");
128 perror(ent
->fts_accpath
);
134 char* line
= fgetln(f
, &len
);
135 if (line
== NULL
) break;
136 char* segment
= read_segment(line
, len
);
138 append_path_segment(&result
, segment
);
145 // merge in any existing custom PATH elemenets
146 char* str
= getenv(env_var
);
147 if (str
) str
= strdup(str
);
149 char* sep
= strchr(str
, ':');
152 append_path_segment(&result
, str
);
168 int main(int argc
, char* argv
[]) {
169 int style
= STYLE_SH
;
171 if (argc
> 2) usage();
173 // default to csh style, if $SHELL ends with "csh".
174 char* shell
= getenv("SHELL");
176 char* str
= strstr(shell
, "csh");
177 if (str
) style
= STYLE_CSH
;
180 if (argc
== 2 && strcmp(argv
[1], "-c") == 0) style
= STYLE_CSH
;
181 if (argc
== 2 && strcmp(argv
[1], "-s") == 0) style
= STYLE_SH
;
183 char* path
= construct_path("PATH", "/etc/paths", "/etc/paths.d");
184 char* manpath
= NULL
;
186 // only adjust manpath if already set
187 int do_manpath
= (getenv("MANPATH") != NULL
);
189 manpath
= construct_path("MANPATH", "/etc/manpaths", "/etc/manpaths.d");
192 if (style
== STYLE_CSH
) {
193 printf("setenv PATH \"%s\";\n", path
);
194 if (do_manpath
) printf("setenv MANPATH \"%s\";\n", manpath
);
196 printf("PATH=\"%s\"; export PATH;\n", path
);
197 if (do_manpath
) printf("MANPATH=\"%s\"; export MANPATH;\n", manpath
);