Initial revision
[sw-tools] / src / sw.c
1 /* -*-c-*-
2 *
3 * $Id: sw.c,v 1.1 1999/06/02 16:53:33 mdw Exp $
4 *
5 * Main driver code for sw-tools
6 *
7 * (c) 1999 EBI
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of sw-tools.
13 *
14 * sw-tools is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * sw-tools is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with sw-tools; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 /*----- Revision history --------------------------------------------------*
30 *
31 * $Log: sw.c,v $
32 * Revision 1.1 1999/06/02 16:53:33 mdw
33 * Initial revision
34 *
35 */
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #include "config.h"
40
41 #include <ctype.h>
42 #include <errno.h>
43 #include <signal.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include <unistd.h>
49
50 #include <mLib/alloc.h>
51 #include <mLib/dstr.h>
52 #include <mLib/exc.h>
53 #include <mLib/mdwopt.h>
54 #include <mLib/quis.h>
55 #include <mLib/report.h>
56 #include <mLib/sub.h>
57
58 #define CMD_LINK 0
59 #include "sw.h"
60 #include "sw_arch.h"
61 #include "sw_build.h"
62 #include "sw_info.h"
63 #include "sw_links.h"
64 #include "sw_rsh.h"
65
66 /*----- Static variables --------------------------------------------------*/
67
68 static cmd *cmds = CMD_LINK;
69
70 /*----- Global option variables -------------------------------------------*
71 *
72 * It'd be nicer if these could be parsed by the build commands, but alas
73 * this is not to be. Consider `sw configure --arch=i386-linux
74 * --with-diffutils': how is the program to know which options are for it and
75 * which are for the remote one? The `configure' command is important,
76 * because it does some hairy stuff under the covers (inserting magical
77 * options, and running `../configure'), so I can't just require `sw run
78 * configure'. Requiring the user to always put in a `--' to separate the
79 * two lots of options is horrific. So they get picked up at the main
80 * program and stuffed into global variables.
81 *
82 * On the other hand, there is the advantage that `--output' options can be
83 * put in an environment variable here.
84 */
85
86 const char *opt_output = 0;
87 const char *opt_arch = 0;
88 unsigned int opt_flags;
89
90 /*----- Helpful GNUy message routines -------------------------------------*/
91
92 /* --- @version@ --- */
93
94 static void version(FILE *fp)
95 {
96 fprintf(fp, "%s v. " VERSION "\n", QUIS);
97 }
98
99 /* --- @usage@ --- */
100
101 static void usage(FILE *fp)
102 {
103 fprintf(fp, "Usage: %s [-fbi] [-a arch,...] [-o style] command [args]\n",
104 QUIS);
105 }
106
107 /* --- @help@ --- */
108
109 static void help(FILE *fp, int full)
110 {
111 cmd *p;
112 version(fp);
113 fputc('\n', fp);
114 usage(fp);
115 fputs("\n\
116 Performs various handy jobs with multiple-architecture builds.\n\
117 \n\
118 There are some options which affect a few of the available commands:\n\
119 \n\
120 -a, --arch=ARCH,... Only build on the named architectures.\n\
121 -b, --beep Beep when the build is complete.\n\
122 -i, --install Mark architectures as done when build succeeds.\n\
123 -f, --force Run build commands on installed architectures.\n\
124 -o, --output=STYLE Display output in a particular style. Use style\n\
125 `help' for a list.\n\
126 \n", fp);
127
128 if (full) {
129 fputs("The various commands provided are:\n\n", fp);
130 for (p = cmds; p; p = p->next) {
131 fputs(p->help, fp);
132 fputc('\n', fp);
133 }
134 fprintf(fp,
135 "`%s' is an [mdw] production, brought to you in association with the\n\
136 European Bioinformatics Institute.\n", QUIS);
137 } else {
138 fputs("The various commands, in summary:\n\n", fp);
139 for (p = cmds; p; p = p->next) {
140 size_t sz = strcspn(p->help, "\n\t");
141 fwrite(p->help, 1, sz, fp);
142 fputc('\n', fp);
143 }
144 fprintf(fp,
145 "\nType `%s --help-full' for complete information. There's a lot of it!\n",
146 QUIS);
147 }
148 }
149
150 /*----- Main code ---------------------------------------------------------*/
151
152 /* --- @main@ --- *
153 *
154 * Arguments: @int argc@ = number of command line arguments
155 * @char *argv[]@ = array of command line strings
156 *
157 * Returns: Zero on success, nonzero on failure.
158 *
159 * Use: Main program. Parses some trivial arguments out, and
160 * dispatches control to one of the subprogram handlers.
161 */
162
163 int main(int argc, char *argv[])
164 {
165 unsigned f = 0;
166
167 enum {
168 f_bogus = 1
169 };
170
171 /* --- Initialize the support library --- */
172
173 ego(argv[0]);
174 sub_init();
175
176 /* --- Parse command line flags --- */
177
178 for (;;) {
179 static struct option opt[] = {
180
181 /* --- Standard GNUy help options --- */
182
183 { "help", 0, 0, 'h' },
184 { "help-full", 0, 0, 'H' },
185 { "version", 0, 0, 'v' },
186 { "usage", 0, 0, 'u' },
187
188 /* --- Build options --- *
189 *
190 */
191
192 { "arch", OPTF_ARGREQ, 0, 'a' },
193 { "force", 0, 0, 'f' },
194 { "install", 0, 0, 'i' },
195 { "output", OPTF_ARGREQ, 0, 'o' },
196 { "beep", 0, 0, 'b' },
197
198 /* --- Internal-use-only magical options --- *
199 *
200 * You get what you deserve if you use this.
201 */
202
203 { "me", OPTF_ARGREQ, 0, '=' },
204 { "remote", OPTF_ARGREQ, 0, '!' },
205
206 /* --- Termination marker --- */
207
208 { 0, 0, 0, 0 }
209 };
210 int i = mdwopt(argc, argv, "+hHvu a:bfio:", opt, 0, 0, gFlag_envVar);
211 if (i < 0)
212 break;
213
214 switch (i) {
215
216 /* --- GNUy help --- */
217
218 case 'h':
219 help(stdout, 0);
220 exit(0);
221 case 'H':
222 help(stdout, 1);
223 exit(0);
224 case 'v':
225 version(stdout);
226 exit(0);
227 case 'u':
228 usage(stdout);
229 exit(0);
230
231 /* --- Build options --- */
232
233 case 'a':
234 opt_arch = optarg;
235 break;
236 case 'f':
237 opt_flags |= optFlag_force;
238 break;
239 case 'b':
240 opt_flags |= optFlag_beep;
241 break;
242 case 'i':
243 opt_flags |= optFlag_install;
244 break;
245 case 'o':
246 opt_output = optarg;
247 break;
248
249 /* --- Magical options for internal use --- */
250
251 case '=':
252 ego(optarg);
253 break;
254 case '!':
255 swrsh_remote(optarg);
256 _exit(1);
257
258 /* --- The user screwed up --- */
259
260 default:
261 f |= f_bogus;
262 break;
263 }
264 }
265
266 if (f & f_bogus || argc == optind) {
267 usage(stderr);
268 exit(1);
269 }
270
271 /* --- Pick up the operation name --- */
272
273 argc -= optind;
274 argv += optind;
275 optind = 0;
276
277 {
278 cmd *p, *chosen = 0;
279 const char *which = argv[0];
280 size_t sz = strlen(which);
281
282 for (p = cmds; p; p = p->next) {
283 if (strncmp(which, p->name, sz) == 0) {
284 if (p->name[sz] == 0) {
285 chosen = p;
286 break;
287 } else if (chosen)
288 die(1, "ambiguous command name `%s'", which);
289 chosen = p;
290 }
291 }
292
293 if (!chosen)
294 die(1, "unknown command name `%s'", which);
295 signal(SIGPIPE, SIG_IGN);
296 TRY
297 return (chosen->cmd(argc, argv));
298 CATCH switch (exc_type) {
299 case EXC_NOMEM:
300 die(1, "not enough memory");
301 default:
302 RETHROW;
303 } END_TRY;
304 }
305 return (127);
306 }
307
308 /*----- That's all, folks -------------------------------------------------*/