this repo has no description
1/*
2This file is part of Darling.
3
4Copyright (C) 2017-2020 Lubos Dolezel
5
6Darling is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11Darling is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with Darling. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include <stdio.h>
21#include <getopt.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25#include <errno.h>
26#include <sys/stat.h>
27#include "xcselect.h"
28
29void printUsage(void);
30void doReset(void);
31void doSwitch(const char* path);
32void doPrintManPaths(void);
33
34int main(int argc, const char** argv)
35{
36 if (argc == 1)
37 {
38 fprintf(stderr, "xcode-select: error: no command option given\n");
39 printUsage();
40 }
41 else if (argc == 2 || argc == 3)
42 {
43 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
44 {
45 printUsage();
46 }
47 else if (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-version") == 0)
48 {
49 printf("xcode-select for Darling, version 1.0\n");
50 }
51 else if (strcmp(argv[1], "-p") == 0 || strcmp(argv[1], "--print-path") == 0 || strcmp(argv[1], "-print-path") == 0)
52 {
53 char path[1024];
54 bool is_cmd_line;
55
56 if (xcselect_get_developer_dir_path(path, sizeof(path), &is_cmd_line))
57 {
58 printf("%s\n", path);
59 }
60 else
61 {
62 fprintf(stderr, "xcode-select: error: unable to get active developer directory\n");
63 return 1;
64 }
65 }
66 else if (strcmp(argv[1], "--show-manpaths") == 0)
67 {
68 doPrintManPaths();
69 }
70 else if (strcmp(argv[1], "--install") == 0)
71 {
72 if (access("/Library/Developer/CommandLineTools/usr/lib/libxcrun.dylib", F_OK) == 0)
73 {
74 fprintf(stderr, "xcode-select: error: command line tools are already installed\n");
75 return 1;
76 }
77 else
78 {
79 int status = system("/usr/libexec/darling/clt_install.py");
80 return WEXITSTATUS(status);
81 }
82 }
83 else if (strcmp(argv[1], "-r") == 0 || strcmp(argv[1], "--reset") == 0)
84 {
85 doReset();
86 }
87 else if (strcmp(argv[1], "-s") == 0 || strcmp(argv[1], "--switch") == 0 || strcmp(argv[1], "-switch") == 0)
88 {
89 if (argc != 3)
90 {
91 fprintf(stderr, "xcode-select: error: missing argument to '%s'\n", argv[1]);
92 return 1;
93 }
94
95 doSwitch(argv[2]);
96 }
97 else
98 {
99 fprintf(stderr, "xcode-select: error: unknown option: %s\n", argv[1]);
100 printUsage();
101 return 1;
102 }
103
104 return 0;
105 }
106 else
107 {
108 fprintf(stderr, "xcode-select: error: bad argument count\n");
109 printUsage();
110 }
111 return 1;
112}
113
114void printUsage(void)
115{
116 fprintf(stderr, "Usage: xcode-select [options]\n\n");
117 fprintf(stderr, "xcode-select is used to set up path to the active developer directory.\n"
118 "This affects both toolchain commands (such as clang or make) and Xcode-specific\n"
119 "tools (such as xcodebuild).\n\n");
120 fprintf(stderr, "Options:\n"
121 " -h, --help print this help message\n"
122 " -p, --print-path print the path of the active developer directory\n"
123 " -s <path>, --switch <path> change the path of the active developer directory\n"
124 " --install trigger the installation of command line developer tools\n"
125 " -v, --version print the version of this tool\n"
126 " -r, --reset reset to the default developer directory\n");
127}
128
129static void killLink(const char* path)
130{
131 if (unlink(path) != 0)
132 {
133 if (errno != ENOENT)
134 {
135 fprintf(stderr, "xcode-select: error: cannot remove existing link at '%s': %s\n",
136 path, strerror(errno));
137 exit(1);
138 }
139 }
140}
141
142void doReset(void)
143{
144 killLink("/var/db/xcode_select_link");
145 killLink("/usr/share/xcode-select/xcode_dir_link");
146 killLink("/usr/share/xcode-select/xcode_dir_path");
147}
148
149void doSwitch(const char* path)
150{
151 char buffer[1024];
152 bool unused;
153
154 if (!xcselect_find_developer_contents_from_path(path, buffer, &unused, sizeof(buffer)))
155 {
156 fprintf(stderr, "xcode-select: error: invalid developer directory '%s'\n", path);
157 exit(1);
158 }
159
160 doReset();
161
162 umask(022);
163 mkdir("/var/db", 0755);
164
165 if (symlink(buffer, "/var/db/xcode_select_link") != 0)
166 {
167 fprintf(stderr, "xcode-select: error: unable to create symlink: %s\n",
168 strerror(errno));
169 exit(1);
170 }
171}
172
173void doPrintManPaths(void)
174{
175 xcselect_manpaths *xcp;
176 const char *path;
177 unsigned i, count;
178
179 xcp = xcselect_get_manpaths(NULL);
180 if (xcp != NULL) {
181 count = xcselect_manpaths_get_num_paths(xcp);
182 for (i = 0; i < count; i++) {
183 path = xcselect_manpaths_get_path(xcp, i);
184 if (path != NULL) {
185 puts(path);
186 }
187 }
188 xcselect_manpaths_free(xcp);
189 }
190}
191