rpc_main.c revision 8874
1/* @(#)rpc_main.c	2.2 88/08/01 4.0 RPCSRC */
2/*
3 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
4 * unrestricted use provided that this legend is included on all tape
5 * media and as a part of the software program in whole or part.  Users
6 * may copy or modify Sun RPC without charge, but are not authorized
7 * to license or distribute it to anyone else except as part of a product or
8 * program developed by the user.
9 *
10 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13 *
14 * Sun RPC is provided with no support and without any obligation on the
15 * part of Sun Microsystems, Inc. to assist in its use, correction,
16 * modification or enhancement.
17 *
18 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20 * OR ANY PART THEREOF.
21 *
22 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23 * or profits or other special, indirect and consequential damages, even if
24 * Sun has been advised of the possibility of such damages.
25 *
26 * Sun Microsystems, Inc.
27 * 2550 Garcia Avenue
28 * Mountain View, California  94043
29 */
30#ifndef lint
31/*static char sccsid[] = "from: @(#)rpc_main.c 1.7 87/06/24 (C) 1987 SMI";*/
32static char rcsid[] = "$Id: rpc_main.c,v 1.2 1995/03/04 17:47:49 nate Exp $";
33#endif
34
35/*
36 * rpc_main.c, Top level of the RPC protocol compiler.
37 * Copyright (C) 1987, Sun Microsystems, Inc.
38 */
39
40#include <stdio.h>
41#include <strings.h>
42#include <sys/file.h>
43#include "rpc_util.h"
44#include "rpc_parse.h"
45#include "rpc_scan.h"
46
47#define EXTEND	1		/* alias for TRUE */
48
49struct commandline {
50	int cflag;
51	int hflag;
52	int lflag;
53	int sflag;
54	int mflag;
55	char *infile;
56	char *outfile;
57};
58
59static char *cmdname;
60static char CPP[] = "/usr/bin/cpp";
61static char CPPFLAGS[] = "-C";
62static char *allv[] = {
63	"rpcgen", "-s", "udp", "-s", "tcp",
64};
65static int allc = sizeof(allv)/sizeof(allv[0]);
66
67
68static int h_output(), c_output(), s_output(), l_output(), do_registers(),
69	   parseargs();
70
71main(argc, argv)
72	int argc;
73	char *argv[];
74
75{
76	struct commandline cmd;
77
78	if (!parseargs(argc, argv, &cmd)) {
79		f_print(stderr,
80			"usage: %s infile\n", cmdname);
81		f_print(stderr,
82			"       %s [-c | -h | -l | -m] [-o outfile] [infile]\n",
83			cmdname);
84		f_print(stderr,
85			"       %s [-s udp|tcp]* [-o outfile] [infile]\n",
86			cmdname);
87		exit(1);
88	}
89	if (cmd.cflag) {
90		c_output(cmd.infile, "-DRPC_XDR", !EXTEND, cmd.outfile);
91	} else if (cmd.hflag) {
92		h_output(cmd.infile, "-DRPC_HDR", !EXTEND, cmd.outfile);
93	} else if (cmd.lflag) {
94		l_output(cmd.infile, "-DRPC_CLNT", !EXTEND, cmd.outfile);
95	} else if (cmd.sflag || cmd.mflag) {
96		s_output(argc, argv, cmd.infile, "-DRPC_SVC", !EXTEND,
97			 cmd.outfile, cmd.mflag);
98	} else {
99		c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c");
100		reinitialize();
101		h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h");
102		reinitialize();
103		l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c");
104		reinitialize();
105		s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND,
106			 "_svc.c", cmd.mflag);
107	}
108	exit(0);
109}
110
111/*
112 * strip path and add extension to filename
113 */
114static char *
115extendfile(path, ext)
116	char *path;
117	char *ext;
118{
119	char *file;
120	char *res;
121	char *p;
122
123	if ((file = rindex(path, '/')) == NULL)
124		file = path;
125	else
126		file++;
127
128	res = alloc(strlen(file) + strlen(ext) + 1);
129	if (res == NULL) {
130		abort();
131	}
132	p = rindex(file, '.');
133	if (p == NULL) {
134		p = file + strlen(file);
135	}
136	(void) strcpy(res, file);
137	(void) strcpy(res + (p - file), ext);
138	return (res);
139}
140
141/*
142 * Open output file with given extension
143 */
144static
145open_output(infile, outfile)
146	char *infile;
147	char *outfile;
148{
149	if (outfile == NULL) {
150		fout = stdout;
151		return;
152	}
153	if (infile != NULL && streq(outfile, infile)) {
154		f_print(stderr, "%s: output would overwrite %s\n", cmdname,
155			infile);
156		crash();
157	}
158	fout = fopen(outfile, "w");
159	if (fout == NULL) {
160		f_print(stderr, "%s: unable to open ", cmdname);
161		perror(outfile);
162		crash();
163	}
164	record_open(outfile);
165}
166
167/*
168 * Open input file with given define for C-preprocessor
169 */
170static
171open_input(infile, define)
172	char *infile;
173	char *define;
174{
175	int pd[2];
176
177	infilename = (infile == NULL) ? "<stdin>" : infile;
178	(void) pipe(pd);
179	switch (fork()) {
180	case 0:
181		(void) close(1);
182		(void) dup2(pd[1], 1);
183		(void) close(pd[0]);
184		execl(CPP, CPP, CPPFLAGS, define, infile, NULL);
185		perror("execl");
186		exit(1);
187	case -1:
188		perror("fork");
189		exit(1);
190	}
191	(void) close(pd[1]);
192	fin = fdopen(pd[0], "r");
193	if (fin == NULL) {
194		f_print(stderr, "%s: ", cmdname);
195		perror(infilename);
196		crash();
197	}
198}
199
200/*
201 * Compile into an XDR routine output file
202 */
203static
204c_output(infile, define, extend, outfile)
205	char *infile;
206	char *define;
207	int extend;
208	char *outfile;
209{
210	definition *def;
211	char *include;
212	char *outfilename;
213	long tell;
214
215	open_input(infile, define);
216	outfilename = extend ? extendfile(infile, outfile) : outfile;
217	open_output(infile, outfilename);
218	f_print(fout, "#include <rpc/rpc.h>\n");
219	if (infile && (include = extendfile(infile, ".h"))) {
220		f_print(fout, "#include \"%s\"\n", include);
221		free(include);
222	}
223	tell = ftell(fout);
224	while (def = get_definition()) {
225		emit(def);
226	}
227	if (extend && tell == ftell(fout)) {
228		(void) unlink(outfilename);
229	}
230}
231
232/*
233 * Compile into an XDR header file
234 */
235static
236h_output(infile, define, extend, outfile)
237	char *infile;
238	char *define;
239	int extend;
240	char *outfile;
241{
242	definition *def;
243	char *outfilename;
244	long tell;
245
246	open_input(infile, define);
247	outfilename =  extend ? extendfile(infile, outfile) : outfile;
248	open_output(infile, outfilename);
249	tell = ftell(fout);
250	while (def = get_definition()) {
251		print_datadef(def);
252	}
253	if (extend && tell == ftell(fout)) {
254		(void) unlink(outfilename);
255	}
256}
257
258/*
259 * Compile into an RPC service
260 */
261static
262s_output(argc, argv, infile, define, extend, outfile, nomain)
263	int argc;
264	char *argv[];
265	char *infile;
266	char *define;
267	int extend;
268	char *outfile;
269	int nomain;
270{
271	char *include;
272	definition *def;
273	int foundprogram;
274	char *outfilename;
275
276	open_input(infile, define);
277	outfilename = extend ? extendfile(infile, outfile) : outfile;
278	open_output(infile, outfilename);
279	f_print(fout, "#include <stdio.h>\n");
280	f_print(fout, "#include <rpc/rpc.h>\n");
281	if (infile && (include = extendfile(infile, ".h"))) {
282		f_print(fout, "#include \"%s\"\n", include);
283		free(include);
284	}
285	foundprogram = 0;
286	while (def = get_definition()) {
287		foundprogram |= (def->def_kind == DEF_PROGRAM);
288	}
289	if (extend && !foundprogram) {
290		(void) unlink(outfilename);
291		return;
292	}
293	if (nomain) {
294		write_programs((char *)NULL);
295	} else {
296		write_most();
297		do_registers(argc, argv);
298		write_rest();
299		write_programs("static");
300	}
301}
302
303static
304l_output(infile, define, extend, outfile)
305	char *infile;
306	char *define;
307	int extend;
308	char *outfile;
309{
310	char *include;
311	definition *def;
312	int foundprogram;
313	char *outfilename;
314
315	open_input(infile, define);
316	outfilename = extend ? extendfile(infile, outfile) : outfile;
317	open_output(infile, outfilename);
318	f_print(fout, "#include <rpc/rpc.h>\n");
319	if (infile && (include = extendfile(infile, ".h"))) {
320		f_print(fout, "#include \"%s\"\n", include);
321		free(include);
322	}
323	foundprogram = 0;
324	while (def = get_definition()) {
325		foundprogram |= (def->def_kind == DEF_PROGRAM);
326	}
327	if (extend && !foundprogram) {
328		(void) unlink(outfilename);
329		return;
330	}
331	write_stubs();
332}
333
334/*
335 * Perform registrations for service output
336 */
337static
338do_registers(argc, argv)
339	int argc;
340	char *argv[];
341
342{
343	int i;
344
345	for (i = 1; i < argc; i++) {
346		if (streq(argv[i], "-s")) {
347			write_register(argv[i + 1]);
348			i++;
349		}
350	}
351}
352
353/*
354 * Parse command line arguments
355 */
356static
357parseargs(argc, argv, cmd)
358	int argc;
359	char *argv[];
360	struct commandline *cmd;
361
362{
363	int i;
364	int j;
365	char c;
366	char flag[(1 << 8 * sizeof(char))];
367	int nflags;
368
369	cmdname = argv[0];
370	cmd->infile = cmd->outfile = NULL;
371	if (argc < 2) {
372		return (0);
373	}
374	flag['c'] = 0;
375	flag['h'] = 0;
376	flag['s'] = 0;
377	flag['o'] = 0;
378	flag['l'] = 0;
379	flag['m'] = 0;
380	for (i = 1; i < argc; i++) {
381		if (argv[i][0] != '-') {
382			if (cmd->infile) {
383				return (0);
384			}
385			cmd->infile = argv[i];
386		} else {
387			for (j = 1; argv[i][j] != 0; j++) {
388				c = argv[i][j];
389				switch (c) {
390				case 'c':
391				case 'h':
392				case 'l':
393				case 'm':
394					if (flag[c]) {
395						return (0);
396					}
397					flag[c] = 1;
398					break;
399				case 'o':
400				case 's':
401					if (argv[i][j - 1] != '-' ||
402					    argv[i][j + 1] != 0) {
403						return (0);
404					}
405					flag[c] = 1;
406					if (++i == argc) {
407						return (0);
408					}
409					if (c == 's') {
410						if (!streq(argv[i], "udp") &&
411						    !streq(argv[i], "tcp")) {
412							return (0);
413						}
414					} else if (c == 'o') {
415						if (cmd->outfile) {
416							return (0);
417						}
418						cmd->outfile = argv[i];
419					}
420					goto nextarg;
421
422				default:
423					return (0);
424				}
425			}
426	nextarg:
427			;
428		}
429	}
430	cmd->cflag = flag['c'];
431	cmd->hflag = flag['h'];
432	cmd->sflag = flag['s'];
433	cmd->lflag = flag['l'];
434	cmd->mflag = flag['m'];
435	nflags = cmd->cflag + cmd->hflag + cmd->sflag + cmd->lflag + cmd->mflag;
436	if (nflags == 0) {
437		if (cmd->outfile != NULL || cmd->infile == NULL) {
438			return (0);
439		}
440	} else if (nflags > 1) {
441		return (0);
442	}
443	return (1);
444}
445