11897Swollman/*
21897Swollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
31897Swollman * unrestricted use provided that this legend is included on all tape
41897Swollman * media and as a part of the software program in whole or part.  Users
51897Swollman * may copy or modify Sun RPC without charge, but are not authorized
61897Swollman * to license or distribute it to anyone else except as part of a product or
71897Swollman * program developed by the user.
8100441Scharnier *
91897Swollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
101897Swollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
111897Swollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12100441Scharnier *
131897Swollman * Sun RPC is provided with no support and without any obligation on the
141897Swollman * part of Sun Microsystems, Inc. to assist in its use, correction,
151897Swollman * modification or enhancement.
16100441Scharnier *
171897Swollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
181897Swollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
191897Swollman * OR ANY PART THEREOF.
20100441Scharnier *
211897Swollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue
221897Swollman * or profits or other special, indirect and consequential damages, even if
231897Swollman * Sun has been advised of the possibility of such damages.
24100441Scharnier *
251897Swollman * Sun Microsystems, Inc.
261897Swollman * 2550 Garcia Avenue
271897Swollman * Mountain View, California  94043
281897Swollman */
2912798Swpaul
3012798Swpaul
31100441Scharnier#if 0
321897Swollman#ifndef lint
33146833Sstefanf#ident	"@(#)rpc_main.c	1.21	94/04/25 SMI"
3412798Swpaulstatic char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI";
351897Swollman#endif
3627935Scharnier#endif
371897Swollman
38100441Scharnier#include <sys/cdefs.h>
39100441Scharnier__FBSDID("$FreeBSD: releng/11.0/usr.bin/rpcgen/rpc_main.c 298183 2016-04-18 06:02:26Z araujo $");
40100441Scharnier
411897Swollman/*
428874Srgrimes * rpc_main.c, Top level of the RPC protocol compiler.
438874Srgrimes * Copyright (C) 1987, Sun Microsystems, Inc.
441897Swollman */
451897Swollman
4627935Scharnier#include <err.h>
4727935Scharnier#include <ctype.h>
481897Swollman#include <stdio.h>
4912798Swpaul#include <string.h>
5012798Swpaul#include <unistd.h>
5112798Swpaul#include <sys/types.h>
5212798Swpaul#include <sys/param.h>
531897Swollman#include <sys/file.h>
5412798Swpaul#include <sys/stat.h>
5512798Swpaul#include "rpc_parse.h"
56149682Sstefanf#include "rpc_scan.h"
571897Swollman#include "rpc_util.h"
581897Swollman
59152398Sdwmalonestatic void c_output(const char *, const char *, int, const char *);
60152398Sdwmalonestatic void h_output(const char *, const char *, int, const char *, int);
61152398Sdwmalonestatic void l_output(const char *, const char *, int, const char *);
62152398Sdwmalonestatic void t_output(const char *, const char *, int, const char *);
63152398Sdwmalonestatic void clnt_output(const char *, const char *, int, const char * );
64152398Sdwmalonestatic char *generate_guard(const char *);
65152398Sdwmalonestatic void c_initialize(void);
6617142Sjkh
6792921Simpstatic void usage(void);
6892921Simpstatic void options_usage(void);
69152398Sdwmalonestatic int do_registers(int, const char **);
70152398Sdwmalonestatic int parseargs(int, const char **, struct commandline *);
71152398Sdwmalonestatic void svc_output(const char *, const char *, int, const char *);
7292921Simpstatic void mkfile_output(struct commandline *);
73152398Sdwmalonestatic void s_output(int, const char **, const char *, const char *, int, const char *, int, int);
7412798Swpaul
7512798Swpaul#define	EXTEND	1		/* alias for TRUE */
7612798Swpaul#define	DONT_EXTEND	0		/* alias for FALSE */
7712798Swpaul
78152398Sdwmalonestatic const char *svcclosetime = "120";
79231079Sdimstatic const char *CPP = NULL;
80152398Sdwmalonestatic const char CPPFLAGS[] = "-C";
8112798Swpaulstatic char pathbuf[MAXPATHLEN + 1];
82152398Sdwmalonestatic const char *allv[] = {
831897Swollman	"rpcgen", "-s", "udp", "-s", "tcp",
841897Swollman};
8512798Swpaulstatic int allc = sizeof (allv)/sizeof (allv[0]);
86152398Sdwmalonestatic const char *allnv[] = {
8712798Swpaul	"rpcgen", "-s", "netpath",
8812798Swpaul};
8912798Swpaulstatic int allnc = sizeof (allnv)/sizeof (allnv[0]);
901897Swollman
9112798Swpaul/*
9212798Swpaul * machinations for handling expanding argument list
9312798Swpaul */
94152398Sdwmalonestatic void addarg(const char *);	/* add another argument to the list */
95231079Sdimstatic void insarg(int, const char *);	/* insert arg at specified location */
96152398Sdwmalonestatic void clear_args(void);		/* clear argument list */
97152398Sdwmalonestatic void checkfiles(const char *, const char *);
98152398Sdwmalone					/* check if out file already exists */
991897Swollman
1001897Swollman
10112798Swpaul
10212798Swpaul#define	ARGLISTLEN	20
103231079Sdim#define	FIXEDARGS	0
10412798Swpaul
105152407Srodrigcstatic char *arglist[ARGLISTLEN];
10612798Swpaulstatic int argcount = FIXEDARGS;
10712798Swpaul
10812798Swpaul
10912798Swpaulint nonfatalerrors;	/* errors */
11099979Salfredint inetdflag = 0;	/* Support for inetd is disabled by default, use -I */
11199979Salfredint pmflag = 0;		/* Support for port monitors is disabled by default */
11299979Salfredint tirpc_socket = 1;	/* TI-RPC on socket, no TLI library */
11312798Swpaulint logflag;		/* Use syslog instead of fprintf for errors */
11412798Swpaulint tblflag;		/* Support for dispatch table file */
11512798Swpaulint mtflag = 0;		/* Support for MT */
11699979Salfred
11712798Swpaul#define INLINE 0
11812798Swpaul/* length at which to start doing an inline */
11912798Swpaul
120149680Sstefanfint inline_size = INLINE;
12112798Swpaul/*
12212798Swpaul * Length at which to start doing an inline. INLINE = default
12312798Swpaul * if 0, no xdr_inline code
12412798Swpaul */
12512798Swpaul
12612798Swpaulint indefinitewait;	/* If started by port monitors, hang till it wants */
12712798Swpaulint exitnow;		/* If started by port monitors, exit after the call */
12812798Swpaulint timerflag;		/* TRUE if !indefinite && !exitnow */
12912798Swpaulint newstyle;		/* newstyle of passing arguments (by value) */
13012798Swpaulint CCflag = 0;		/* C++ files */
13112798Swpaulstatic int allfiles;   /* generate all files */
13212798Swpaulint tirpcflag = 1;    /* generating code for tirpc, by default */
13312798Swpaulxdrfunc *xdrfunc_head = NULL; /* xdr function list */
13412798Swpaulxdrfunc *xdrfunc_tail = NULL; /* xdr function list */
13512798Swpaulpid_t childpid;
13612798Swpaul
13712798Swpaul
13817142Sjkhint
139152398Sdwmalonemain(int argc, const char *argv[])
1401897Swollman{
1411897Swollman	struct commandline cmd;
1421897Swollman
14312798Swpaul	(void) memset((char *)&cmd, 0, sizeof (struct commandline));
14412798Swpaul	clear_args();
14512798Swpaul	if (!parseargs(argc, argv, &cmd))
14612798Swpaul		usage();
14712798Swpaul	/*
14812798Swpaul	 * Only the client and server side stubs are likely to be customized,
14912798Swpaul	 *  so in that case only, check if the outfile exists, and if so,
15012798Swpaul	 *  print an error message and exit.
15112798Swpaul	 */
15212798Swpaul	if (cmd.Ssflag || cmd.Scflag || cmd.makefileflag) {
15312798Swpaul		checkfiles(cmd.infile, cmd.outfile);
1541897Swollman	}
15512798Swpaul	else
15612798Swpaul		checkfiles(cmd.infile, NULL);
15712798Swpaul
1581897Swollman	if (cmd.cflag) {
15912798Swpaul		c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile);
1601897Swollman	} else if (cmd.hflag) {
161149695Sstefanf		h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile,
162149695Sstefanf		    cmd.hflag);
1631897Swollman	} else if (cmd.lflag) {
16412798Swpaul		l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile);
16512798Swpaul	} else if (cmd.sflag || cmd.mflag || (cmd.nflag)) {
16612798Swpaul		s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND,
16712798Swpaul			cmd.outfile, cmd.mflag, cmd.nflag);
16812798Swpaul	} else if (cmd.tflag) {
16912798Swpaul		t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile);
17012798Swpaul	} else if  (cmd.Ssflag) {
17112798Swpaul		svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND,
17212798Swpaul			cmd.outfile);
17312798Swpaul	} else if (cmd.Scflag) {
17412798Swpaul		clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND,
17512798Swpaul			    cmd.outfile);
17612798Swpaul	} else if (cmd.makefileflag) {
17712798Swpaul		mkfile_output(&cmd);
1781897Swollman	} else {
17912798Swpaul		/* the rescans are required, since cpp may effect input */
1801897Swollman		c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c");
1811897Swollman		reinitialize();
182149695Sstefanf		h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h", cmd.hflag);
1831897Swollman		reinitialize();
1841897Swollman		l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c");
1851897Swollman		reinitialize();
18612798Swpaul		if (inetdflag || !tirpcflag)
18712798Swpaul			s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND,
18812798Swpaul			"_svc.c", cmd.mflag, cmd.nflag);
18912798Swpaul		else
19012798Swpaul			s_output(allnc, allnv, cmd.infile, "-DRPC_SVC",
19112798Swpaul				EXTEND, "_svc.c", cmd.mflag, cmd.nflag);
19212798Swpaul		if (tblflag) {
19312798Swpaul			reinitialize();
194128810Ssmkelly			t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i");
19512798Swpaul		}
19612798Swpaul
19712798Swpaul		if (allfiles) {
19812798Swpaul			reinitialize();
19912798Swpaul			svc_output(cmd.infile, "-DRPC_SERVER", EXTEND,
20012798Swpaul				"_server.c");
20112798Swpaul			reinitialize();
20212798Swpaul			clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND,
20312798Swpaul				"_client.c");
20412798Swpaul
20512798Swpaul		}
20612798Swpaul		if (allfiles || (cmd.makefileflag == 1)){
20712798Swpaul			reinitialize();
20812798Swpaul			mkfile_output(&cmd);
20912798Swpaul		}
21012798Swpaul
2111897Swollman	}
21212798Swpaul	exit(nonfatalerrors);
21312798Swpaul	/* NOTREACHED */
2141897Swollman}
2151897Swollman
21612798Swpaul
2171897Swollman/*
21812798Swpaul * add extension to filename
2191897Swollman */
2201897Swollmanstatic char *
221152398Sdwmaloneextendfile(const char *path, const char *ext)
2221897Swollman{
2231897Swollman	char *res;
224152398Sdwmalone	const char *p;
225152398Sdwmalone	const char *file;
2261897Swollman
227229403Sed	if ((file = strrchr(path, '/')) == NULL)
2286886Snate		file = path;
2296886Snate	else
2306886Snate		file++;
231100441Scharnier	res = xmalloc(strlen(file) + strlen(ext) + 1);
23212798Swpaul	p = strrchr(file, '.');
2331897Swollman	if (p == NULL) {
2341897Swollman		p = file + strlen(file);
2351897Swollman	}
2361897Swollman	(void) strcpy(res, file);
2371897Swollman	(void) strcpy(res + (p - file), ext);
2381897Swollman	return (res);
2391897Swollman}
2401897Swollman
2411897Swollman/*
2428874Srgrimes * Open output file with given extension
2431897Swollman */
24417142Sjkhstatic void
245152398Sdwmaloneopen_output(const char *infile, const char *outfile)
2461897Swollman{
24712798Swpaul
2481897Swollman	if (outfile == NULL) {
2491897Swollman		fout = stdout;
2501897Swollman		return;
2511897Swollman	}
25212798Swpaul
2531897Swollman	if (infile != NULL && streq(outfile, infile)) {
25427935Scharnier		warnx("%s already exists. No output generated", infile);
2551897Swollman		crash();
2561897Swollman	}
2571897Swollman	fout = fopen(outfile, "w");
2581897Swollman	if (fout == NULL) {
25927935Scharnier		warn("unable to open %s", outfile);
2601897Swollman		crash();
2611897Swollman	}
2621897Swollman	record_open(outfile);
26312798Swpaul
26417142Sjkh	return;
2651897Swollman}
2661897Swollman
26717142Sjkhstatic void
268152398Sdwmaloneadd_warning(void)
26912798Swpaul{
27012798Swpaul	f_print(fout, "/*\n");
27112798Swpaul	f_print(fout, " * Please do not edit this file.\n");
27212798Swpaul	f_print(fout, " * It was generated using rpcgen.\n");
27312798Swpaul	f_print(fout, " */\n\n");
27412798Swpaul}
27512798Swpaul
27612798Swpaul/* clear list of arguments */
277152398Sdwmalonestatic void
278152398Sdwmaloneclear_args(void)
27912798Swpaul{
28012798Swpaul	int i;
28112798Swpaul	for (i = FIXEDARGS; i < ARGLISTLEN; i++)
28212798Swpaul		arglist[i] = NULL;
28312798Swpaul	argcount = FIXEDARGS;
28412798Swpaul}
28512798Swpaul
286231079Sdim/* prepend C-preprocessor and flags before arguments */
287152398Sdwmalonestatic void
288231079Sdimprepend_cpp(void)
28912798Swpaul{
290231079Sdim	int idx = 1;
291231079Sdim	const char *var;
292231079Sdim	char *dupvar, *s, *t;
29312798Swpaul
294231079Sdim	if (CPP != NULL)
295231079Sdim		insarg(0, CPP);
296231079Sdim	else if ((var = getenv("RPCGEN_CPP")) == NULL)
297231079Sdim		insarg(0, "/usr/bin/cpp");
298231079Sdim	else {
299231079Sdim		/* Parse command line in a rudimentary way */
300231079Sdim		dupvar = xstrdup(var);
301231079Sdim		for (s = dupvar, idx = 0; (t = strsep(&s, " \t")) != NULL; ) {
302231079Sdim			if (t[0])
303231079Sdim				insarg(idx++, t);
30412798Swpaul		}
305231079Sdim		free(dupvar);
30612798Swpaul	}
307231079Sdim
308231079Sdim	insarg(idx, CPPFLAGS);
30912798Swpaul}
31012798Swpaul
3111897Swollman/*
3128874Srgrimes * Open input file with given define for C-preprocessor
3131897Swollman */
31417142Sjkhstatic void
315152398Sdwmaloneopen_input(const char *infile, const char *define)
3161897Swollman{
3171897Swollman	int pd[2];
3181897Swollman
3191897Swollman	infilename = (infile == NULL) ? "<stdin>" : infile;
3201897Swollman	(void) pipe(pd);
32112798Swpaul	switch (childpid = fork()) {
3221897Swollman	case 0:
323231079Sdim		prepend_cpp();
32412798Swpaul		addarg(define);
32512798Swpaul		if (infile)
32612798Swpaul			addarg(infile);
32712798Swpaul		addarg((char *)NULL);
3281897Swollman		(void) close(1);
3291897Swollman		(void) dup2(pd[1], 1);
3301897Swollman		(void) close(pd[0]);
331231101Sdim		execvp(arglist[0], arglist);
332231101Sdim		err(1, "execvp %s", arglist[0]);
3331897Swollman	case -1:
334100441Scharnier		err(1, "fork");
3351897Swollman	}
3361897Swollman	(void) close(pd[1]);
3371897Swollman	fin = fdopen(pd[0], "r");
3381897Swollman	if (fin == NULL) {
33927935Scharnier		warn("%s", infilename);
3401897Swollman		crash();
3411897Swollman	}
3421897Swollman}
3431897Swollman
34412798Swpaul/* valid tirpc nettypes */
345152398Sdwmalonestatic const char *valid_ti_nettypes[] =
34612798Swpaul{
34712798Swpaul	"netpath",
34812798Swpaul	"visible",
34912798Swpaul	"circuit_v",
35012798Swpaul	"datagram_v",
35112798Swpaul	"circuit_n",
35212798Swpaul	"datagram_n",
35312798Swpaul	"udp",
35412798Swpaul	"tcp",
35512798Swpaul	"raw",
35612798Swpaul	NULL
35712798Swpaul	};
35812798Swpaul
35912798Swpaul/* valid inetd nettypes */
360152398Sdwmalonestatic const char *valid_i_nettypes[] =
36112798Swpaul{
36212798Swpaul	"udp",
36312798Swpaul	"tcp",
36412798Swpaul	NULL
36512798Swpaul	};
36612798Swpaul
367152398Sdwmalonestatic int
368152398Sdwmalonecheck_nettype(const char *name, const char *list_to_check[])
36912798Swpaul{
37012798Swpaul	int i;
37112798Swpaul	for (i = 0; list_to_check[i] != NULL; i++) {
37212798Swpaul		if (strcmp(name, list_to_check[i]) == 0) {
37312798Swpaul			return (1);
37412798Swpaul		}
37512798Swpaul	}
37627935Scharnier	warnx("illegal nettype :\'%s\'", name);
37712798Swpaul	return (0);
37812798Swpaul}
37912798Swpaul
380152398Sdwmalonestatic const char *
381152398Sdwmalonefile_name(const char *file, const char *ext)
38212798Swpaul{
38312798Swpaul	char *temp;
38412798Swpaul	temp = extendfile(file, ext);
38512798Swpaul
38612798Swpaul	if (access(temp, F_OK) != -1)
38712798Swpaul		return (temp);
38812798Swpaul	else
389152398Sdwmalone		return (" ");
39012798Swpaul
39112798Swpaul}
39212798Swpaul
39312798Swpaul
39417142Sjkhstatic void
395152398Sdwmalonec_output(const char *infile, const char *define, int extend, const char *outfile)
3961897Swollman{
3971897Swollman	definition *def;
3981897Swollman	char *include;
399152398Sdwmalone	const char *outfilename;
4001897Swollman	long tell;
4011897Swollman
40212798Swpaul	c_initialize();
4038874Srgrimes	open_input(infile, define);
4041897Swollman	outfilename = extend ? extendfile(infile, outfile) : outfile;
4051897Swollman	open_output(infile, outfilename);
40612798Swpaul	add_warning();
4071897Swollman	if (infile && (include = extendfile(infile, ".h"))) {
4081897Swollman		f_print(fout, "#include \"%s\"\n", include);
4091897Swollman		free(include);
41012798Swpaul		/* .h file already contains rpc/rpc.h */
41112798Swpaul	} else
41212798Swpaul		f_print(fout, "#include <rpc/rpc.h>\n");
4131897Swollman	tell = ftell(fout);
41417142Sjkh	while ( (def = get_definition()) ) {
4151897Swollman		emit(def);
4161897Swollman	}
4171897Swollman	if (extend && tell == ftell(fout)) {
4181897Swollman		(void) unlink(outfilename);
4191897Swollman	}
4201897Swollman}
4211897Swollman
42212798Swpaul
42317142Sjkhvoid
424152398Sdwmalonec_initialize(void)
42512798Swpaul{
42612798Swpaul
42712798Swpaul	/* add all the starting basic types */
42812798Swpaul	add_type(1, "int");
42912798Swpaul	add_type(1, "long");
43012798Swpaul	add_type(1, "short");
43112798Swpaul	add_type(1, "bool");
43212798Swpaul	add_type(1, "u_int");
43312798Swpaul	add_type(1, "u_long");
43412798Swpaul	add_type(1, "u_short");
43512798Swpaul
43612798Swpaul}
43712798Swpaul
438241737Sedstatic const char rpcgen_table_dcl[] = "struct rpcgen_table {\n\
43912798Swpaul	char	*(*proc)(); \n\
44012798Swpaul	xdrproc_t	xdr_arg; \n\
44112798Swpaul	unsigned	len_arg; \n\
44212798Swpaul	xdrproc_t	xdr_res; \n\
44312798Swpaul	unsigned	len_res; \n\
44412798Swpaul}; \n";
44512798Swpaul
44612798Swpaul
447152398Sdwmalonechar *
448152398Sdwmalonegenerate_guard(const char *pathname)
44912798Swpaul{
450152398Sdwmalone	const char *filename;
451152398Sdwmalone	char *guard, *tmp, *stopat;
45212798Swpaul
45312798Swpaul	filename = strrchr(pathname, '/');  /* find last component */
454298183Saraujo	filename = ((filename == NULL) ? pathname : filename+1);
455100441Scharnier	guard = xstrdup(filename);
456128817Ssmkelly	stopat = strrchr(guard, '.');
457128817Ssmkelly
458128817Ssmkelly	/*
459128817Ssmkelly	 * Convert to a valid C macro name and make it upper case.
460128817Ssmkelly	 * Map macro unfriendly characterss to '_'.
461128810Ssmkelly	 */
462128817Ssmkelly	for (tmp = guard; *tmp != '\000'; ++tmp) {
46312798Swpaul		if (islower(*tmp))
46412798Swpaul			*tmp = toupper(*tmp);
465128817Ssmkelly		else if (isupper(*tmp) || *tmp == '_')
466128810Ssmkelly			/* OK for C */;
467128810Ssmkelly		else if (tmp == guard)
468128810Ssmkelly			*tmp = '_';
469128810Ssmkelly		else if (isdigit(*tmp))
470128810Ssmkelly			/* OK for all but first character */;
471128817Ssmkelly		else if (tmp == stopat) {
472128817Ssmkelly			*tmp = '\0';
473128810Ssmkelly			break;
474128810Ssmkelly		} else
475128810Ssmkelly			*tmp = '_';
47612798Swpaul	}
477128817Ssmkelly	/*
478128817Ssmkelly	 * Can't have a '_' in front, because it'll end up being "__".
479128817Ssmkelly	 * "__" macros shoudln't be used. So, remove all of the
480128817Ssmkelly	 * '_' characters from the front.
481128810Ssmkelly	 */
482128817Ssmkelly	if (*guard == '_') {
483128817Ssmkelly		for (tmp = guard; *tmp == '_'; ++tmp)
484128817Ssmkelly			;
485128817Ssmkelly		strcpy(guard, tmp);
486128810Ssmkelly	}
48712798Swpaul	guard = extendfile(guard, "_H_RPCGEN");
48812798Swpaul	return (guard);
48912798Swpaul}
49012798Swpaul
4911897Swollman/*
4921897Swollman * Compile into an XDR header file
4931897Swollman */
49412798Swpaul
49512798Swpaul
49617142Sjkhstatic void
497152398Sdwmaloneh_output(const char *infile, const char *define, int extend, const char *outfile, int headeronly)
4981897Swollman{
4991897Swollman	definition *def;
500152398Sdwmalone	const char *outfilename;
5011897Swollman	long tell;
502152398Sdwmalone	const char *guard;
50312798Swpaul	list *l;
50412798Swpaul	xdrfunc *xdrfuncp;
5051897Swollman
5061897Swollman	open_input(infile, define);
5071897Swollman	outfilename =  extend ? extendfile(infile, outfile) : outfile;
5081897Swollman	open_output(infile, outfilename);
50912798Swpaul	add_warning();
51012798Swpaul	if (outfilename || infile){
51112798Swpaul		guard = generate_guard(outfilename ? outfilename: infile);
51212798Swpaul	} else
51312798Swpaul		guard = "STDIN_";
51412798Swpaul
51512798Swpaul	f_print(fout, "#ifndef _%s\n#define	_%s\n\n", guard,
51612798Swpaul		guard);
51712798Swpaul
51812798Swpaul	f_print(fout, "#include <rpc/rpc.h>\n");
51912798Swpaul
52099979Salfred	if (mtflag)
52139642Sobrien		f_print(fout, "#include <pthread.h>\n");
52212798Swpaul
52312798Swpaul	/* put the C++ support */
524149709Sstefanf	if (!CCflag) {
52512798Swpaul		f_print(fout, "\n#ifdef __cplusplus\n");
52612798Swpaul		f_print(fout, "extern \"C\" {\n");
52712798Swpaul		f_print(fout, "#endif\n\n");
52812798Swpaul	}
52912798Swpaul
53012798Swpaul	/* put in a typedef for quadprecision. Only with Cflag */
53112798Swpaul
5321897Swollman	tell = ftell(fout);
53312798Swpaul
53412798Swpaul	/* print data definitions */
53517142Sjkh	while ( (def = get_definition()) ) {
536149695Sstefanf		print_datadef(def, headeronly);
5371897Swollman	}
53812798Swpaul
53912798Swpaul	/*
54012798Swpaul	 * print function declarations.
54112798Swpaul	 *  Do this after data definitions because they might be used as
54212798Swpaul	 *  arguments for functions
54312798Swpaul	 */
54412798Swpaul	for (l = defined; l != NULL; l = l->next) {
545149695Sstefanf		print_funcdef(l->val, headeronly);
54612798Swpaul	}
54712798Swpaul	/* Now  print all xdr func declarations */
54812798Swpaul	if (xdrfunc_head != NULL){
54912798Swpaul
55012798Swpaul		f_print(fout,
55112798Swpaul			"\n/* the xdr functions */\n");
55212798Swpaul
55312798Swpaul		if (CCflag){
554149709Sstefanf			f_print(fout, "\n#ifdef __cplusplus\n");
555149709Sstefanf			f_print(fout, "extern \"C\" {\n");
556149709Sstefanf			f_print(fout, "#endif\n");
557149709Sstefanf		}
55812798Swpaul
559149709Sstefanf		xdrfuncp = xdrfunc_head;
560149709Sstefanf		while (xdrfuncp != NULL){
561149709Sstefanf			print_xdr_func_def(xdrfuncp->name, xdrfuncp->pointerp);
562149709Sstefanf			xdrfuncp = xdrfuncp->next;
56312798Swpaul		}
56412798Swpaul	}
56512798Swpaul
5661897Swollman	if (extend && tell == ftell(fout)) {
5671897Swollman		(void) unlink(outfilename);
56812798Swpaul	} else if (tblflag) {
56912798Swpaul		f_print(fout, rpcgen_table_dcl);
5701897Swollman	}
57112798Swpaul
572149709Sstefanf	f_print(fout, "\n#ifdef __cplusplus\n");
573149709Sstefanf	f_print(fout, "}\n");
574149709Sstefanf	f_print(fout, "#endif\n");
57512798Swpaul
57612798Swpaul	f_print(fout, "\n#endif /* !_%s */\n", guard);
5771897Swollman}
5781897Swollman
5791897Swollman/*
5801897Swollman * Compile into an RPC service
5811897Swollman */
58217142Sjkhstatic void
583152398Sdwmalones_output(int argc, const char *argv[], const char *infile, const char *define,
584152398Sdwmalone    int extend, const char *outfile, int nomain, int netflag)
5851897Swollman{
5861897Swollman	char *include;
5871897Swollman	definition *def;
58812798Swpaul	int foundprogram = 0;
589152398Sdwmalone	const char *outfilename;
5901897Swollman
5911897Swollman	open_input(infile, define);
5921897Swollman	outfilename = extend ? extendfile(infile, outfile) : outfile;
5931897Swollman	open_output(infile, outfilename);
59412798Swpaul	add_warning();
5951897Swollman	if (infile && (include = extendfile(infile, ".h"))) {
5961897Swollman		f_print(fout, "#include \"%s\"\n", include);
5971897Swollman		free(include);
59812798Swpaul	} else
59912798Swpaul		f_print(fout, "#include <rpc/rpc.h>\n");
60012798Swpaul
60112798Swpaul	f_print(fout, "#include <stdio.h>\n");
60212798Swpaul	f_print(fout, "#include <stdlib.h> /* getenv, exit */\n");
603149709Sstefanf	f_print (fout, "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n");
604149709Sstefanf	f_print (fout, "#include <string.h> /* strcmp */\n");
605109363Smbr	if (tirpcflag)
606109363Smbr		f_print(fout, "#include <rpc/rpc_com.h>\n");
60712798Swpaul	if (strcmp(svcclosetime, "-1") == 0)
60812798Swpaul		indefinitewait = 1;
60912798Swpaul	else if (strcmp(svcclosetime, "0") == 0)
61012798Swpaul		exitnow = 1;
61112798Swpaul	else if (inetdflag || pmflag) {
61212798Swpaul		f_print(fout, "#include <signal.h>\n");
61312798Swpaul		timerflag = 1;
61412798Swpaul	}
61512798Swpaul
61612798Swpaul	if (!tirpcflag && inetdflag)
61712798Swpaul		f_print(fout, "#include <sys/ttycom.h> /* TIOCNOTTY */\n");
618149709Sstefanf	if (inetdflag || pmflag) {
61912798Swpaul		f_print(fout, "#ifdef __cplusplus\n");
62012798Swpaul		f_print(fout,
621171931Sdelphij			"#include <sys/sysent.h> /* getdtablesize, open */\n");
62212798Swpaul		f_print(fout, "#endif /* __cplusplus */\n");
62312798Swpaul	}
62499979Salfred	if (tirpcflag) {
62599979Salfred		f_print(fout, "#include <fcntl.h> /* open */\n");
62699979Salfred		f_print(fout, "#include <unistd.h> /* fork / setsid */\n");
62712798Swpaul		f_print(fout, "#include <sys/types.h>\n");
62899979Salfred	}
62912798Swpaul
630141604Sstefanf	f_print(fout, "#include <string.h>\n");
63112798Swpaul	if (inetdflag || !tirpcflag) {
63212798Swpaul		f_print(fout, "#include <sys/socket.h>\n");
63312798Swpaul		f_print(fout, "#include <netinet/in.h>\n");
63412798Swpaul	}
63512798Swpaul
63612798Swpaul	if ((netflag || pmflag) && tirpcflag && !nomain) {
63712798Swpaul		f_print(fout, "#include <netconfig.h>\n");
63812798Swpaul	}
63912798Swpaul	if (tirpcflag)
64012798Swpaul		f_print(fout, "#include <sys/resource.h> /* rlimit */\n");
64199979Salfred	if (logflag || inetdflag || pmflag || tirpcflag)
64212798Swpaul		f_print(fout, "#include <syslog.h>\n");
64312798Swpaul
64412798Swpaul	f_print(fout, "\n#ifdef DEBUG\n#define	RPC_SVC_FG\n#endif\n");
64512798Swpaul	if (timerflag)
64612798Swpaul		f_print(fout, "\n#define	_RPCSVC_CLOSEDOWN %s\n",
64712798Swpaul			svcclosetime);
64817142Sjkh	while ( (def = get_definition()) ) {
6491897Swollman		foundprogram |= (def->def_kind == DEF_PROGRAM);
6501897Swollman	}
6511897Swollman	if (extend && !foundprogram) {
6521897Swollman		(void) unlink(outfilename);
6531897Swollman		return;
6541897Swollman	}
65512798Swpaul	write_most(infile, netflag, nomain);
65612798Swpaul	if (!nomain) {
65712798Swpaul		if (!do_registers(argc, argv)) {
65812798Swpaul			if (outfilename)
65912798Swpaul				(void) unlink(outfilename);
66012798Swpaul			usage();
66112798Swpaul		}
6621897Swollman		write_rest();
6631897Swollman	}
6641897Swollman}
6651897Swollman
66612798Swpaul/*
66712798Swpaul * generate client side stubs
66812798Swpaul */
66917142Sjkhstatic void
670152398Sdwmalonel_output(const char *infile, const char *define, int extend, const char *outfile)
6711897Swollman{
6721897Swollman	char *include;
6731897Swollman	definition *def;
67412798Swpaul	int foundprogram = 0;
675152398Sdwmalone	const char *outfilename;
6761897Swollman
6771897Swollman	open_input(infile, define);
6781897Swollman	outfilename = extend ? extendfile(infile, outfile) : outfile;
6791897Swollman	open_output(infile, outfilename);
68012798Swpaul	add_warning();
681149709Sstefanf	f_print (fout, "#include <string.h> /* for memset */\n");
6821897Swollman	if (infile && (include = extendfile(infile, ".h"))) {
6831897Swollman		f_print(fout, "#include \"%s\"\n", include);
6841897Swollman		free(include);
68512798Swpaul	} else
68612798Swpaul		f_print(fout, "#include <rpc/rpc.h>\n");
68717142Sjkh	while ( (def = get_definition()) ) {
6881897Swollman		foundprogram |= (def->def_kind == DEF_PROGRAM);
6891897Swollman	}
6901897Swollman	if (extend && !foundprogram) {
6911897Swollman		(void) unlink(outfilename);
6921897Swollman		return;
6931897Swollman	}
6941897Swollman	write_stubs();
6951897Swollman}
6961897Swollman
6971897Swollman/*
69812798Swpaul * generate the dispatch table
69912798Swpaul */
70017142Sjkhstatic void
701152398Sdwmalonet_output(const char *infile, const char *define, int extend, const char *outfile)
70212798Swpaul{
70312798Swpaul	definition *def;
70412798Swpaul	int foundprogram = 0;
705152398Sdwmalone	const char *outfilename;
70612798Swpaul
70712798Swpaul	open_input(infile, define);
70812798Swpaul	outfilename = extend ? extendfile(infile, outfile) : outfile;
70912798Swpaul	open_output(infile, outfilename);
71012798Swpaul	add_warning();
71117142Sjkh	while ( (def = get_definition()) ) {
71212798Swpaul		foundprogram |= (def->def_kind == DEF_PROGRAM);
71312798Swpaul	}
71412798Swpaul	if (extend && !foundprogram) {
71512798Swpaul		(void) unlink(outfilename);
71612798Swpaul		return;
71712798Swpaul	}
71812798Swpaul	write_tables();
71912798Swpaul}
72012798Swpaul
72112798Swpaul/* sample routine for the server template */
72217142Sjkhstatic void
723152398Sdwmalonesvc_output(const char *infile, const char *define, int extend, const char *outfile)
72412798Swpaul{
72512798Swpaul	definition *def;
72612798Swpaul	char *include;
727152398Sdwmalone	const char *outfilename;
72812798Swpaul	long tell;
72912798Swpaul	open_input(infile, define);
73012798Swpaul	outfilename = extend ? extendfile(infile, outfile) : outfile;
73112798Swpaul	checkfiles(infile, outfilename);
73212798Swpaul	/*
73312798Swpaul	 * Check if outfile already exists.
73412798Swpaul	 * if so, print an error message and exit
73512798Swpaul	 */
73612798Swpaul	open_output(infile, outfilename);
73712798Swpaul	add_sample_msg();
73812798Swpaul
73912798Swpaul	if (infile && (include = extendfile(infile, ".h"))) {
74012798Swpaul		f_print(fout, "#include \"%s\"\n", include);
74112798Swpaul		free(include);
74212798Swpaul	} else
74312798Swpaul		f_print(fout, "#include <rpc/rpc.h>\n");
74412798Swpaul
74512798Swpaul	tell = ftell(fout);
74617142Sjkh	while ( (def = get_definition()) ) {
74712798Swpaul		write_sample_svc(def);
74812798Swpaul	}
74912798Swpaul	if (extend && tell == ftell(fout)) {
75012798Swpaul		(void) unlink(outfilename);
75112798Swpaul	}
75212798Swpaul}
75312798Swpaul
75412798Swpaul/* sample main routine for client */
75517142Sjkhstatic void
756152398Sdwmaloneclnt_output(const char *infile, const char *define, int extend, const char *outfile)
75712798Swpaul{
75812798Swpaul	definition *def;
75912798Swpaul	char *include;
760152398Sdwmalone	const char *outfilename;
76112798Swpaul	long tell;
76212798Swpaul	int has_program = 0;
76312798Swpaul
76412798Swpaul	open_input(infile, define);
76512798Swpaul	outfilename = extend ? extendfile(infile, outfile) : outfile;
76612798Swpaul	checkfiles(infile, outfilename);
76712798Swpaul	/*
76812798Swpaul	 * Check if outfile already exists.
76912798Swpaul	 * if so, print an error message and exit
77012798Swpaul	 */
77112798Swpaul
77212798Swpaul	open_output(infile, outfilename);
77312798Swpaul	add_sample_msg();
77412798Swpaul	if (infile && (include = extendfile(infile, ".h"))) {
77512798Swpaul		f_print(fout, "#include \"%s\"\n", include);
77612798Swpaul		free(include);
77712798Swpaul	} else
77812798Swpaul		f_print(fout, "#include <rpc/rpc.h>\n");
779259914Sdfr	f_print(fout, "#include <stdio.h>\n");
780259914Sdfr	f_print(fout, "#include <stdlib.h>\n");
78112798Swpaul	tell = ftell(fout);
78217142Sjkh	while ( (def = get_definition()) ) {
78312798Swpaul		has_program += write_sample_clnt(def);
78412798Swpaul	}
78512798Swpaul
78612798Swpaul	if (has_program)
78712798Swpaul		write_sample_clnt_main();
78812798Swpaul
78912798Swpaul	if (extend && tell == ftell(fout)) {
79012798Swpaul		(void) unlink(outfilename);
79112798Swpaul	}
79212798Swpaul}
79312798Swpaul
79412798Swpaul
795152398Sdwmalonestatic void mkfile_output(struct commandline *cmd)
79612798Swpaul{
797152398Sdwmalone	const char *mkfilename, *clientname, *clntname, *xdrname, *hdrname;
798152398Sdwmalone	const char *servername, *svcname, *servprogname, *clntprogname;
799152398Sdwmalone	char *temp, *mkftemp;
80012798Swpaul
80112798Swpaul	svcname = file_name(cmd->infile, "_svc.c");
80212798Swpaul	clntname = file_name(cmd->infile, "_clnt.c");
80312798Swpaul	xdrname = file_name(cmd->infile, "_xdr.c");
80412798Swpaul	hdrname = file_name(cmd->infile, ".h");
80512798Swpaul
80612798Swpaul
80712798Swpaul	if (allfiles){
80812798Swpaul		servername = extendfile(cmd->infile, "_server.c");
80912798Swpaul		clientname = extendfile(cmd->infile, "_client.c");
81012798Swpaul	}else{
81112798Swpaul		servername = " ";
81212798Swpaul		clientname = " ";
81312798Swpaul	}
81412798Swpaul	servprogname = extendfile(cmd->infile, "_server");
81512798Swpaul	clntprogname = extendfile(cmd->infile, "_client");
81612798Swpaul
81712798Swpaul	if (allfiles){
818152398Sdwmalone		mkftemp = xmalloc(strlen("makefile.") +
819100441Scharnier		                     strlen(cmd->infile) + 1);
820229403Sed		temp = strrchr(cmd->infile, '.');
821152398Sdwmalone		strcpy(mkftemp, "makefile.");
822152398Sdwmalone		(void) strncat(mkftemp, cmd->infile,
82312798Swpaul			(temp - cmd->infile));
824152398Sdwmalone		mkfilename = mkftemp;
82512798Swpaul	} else
82612798Swpaul		mkfilename = cmd->outfile;
82712798Swpaul
82812798Swpaul
82912798Swpaul	checkfiles(NULL, mkfilename);
83012798Swpaul	open_output(NULL, mkfilename);
83112798Swpaul
83212798Swpaul	f_print(fout, "\n# This is a template makefile generated\
83312798Swpaul		by rpcgen \n");
83412798Swpaul
83512798Swpaul	f_print(fout, "\n# Parameters \n\n");
83612798Swpaul
83712798Swpaul	f_print(fout, "CLIENT = %s\nSERVER = %s\n\n",
83812798Swpaul		clntprogname, servprogname);
83912798Swpaul	f_print(fout, "SOURCES_CLNT.c = \nSOURCES_CLNT.h = \n");
84012798Swpaul	f_print(fout, "SOURCES_SVC.c = \nSOURCES_SVC.h = \n");
84112798Swpaul	f_print(fout, "SOURCES.x = %s\n\n", cmd->infile);
84212798Swpaul	f_print(fout, "TARGETS_SVC.c = %s %s %s \n",
84312798Swpaul		svcname, servername, xdrname);
84412798Swpaul	f_print(fout, "TARGETS_CLNT.c = %s %s %s \n",
84512798Swpaul		clntname, clientname, xdrname);
84612798Swpaul	f_print(fout, "TARGETS = %s %s %s %s %s %s\n\n",
84712798Swpaul		hdrname, xdrname, clntname,
84812798Swpaul		svcname, clientname, servername);
84912798Swpaul
85012798Swpaul	f_print(fout, "OBJECTS_CLNT = $(SOURCES_CLNT.c:%%.c=%%.o) \
85112798Swpaul$(TARGETS_CLNT.c:%%.c=%%.o) ");
85212798Swpaul
85312798Swpaul	f_print(fout, "\nOBJECTS_SVC = $(SOURCES_SVC.c:%%.c=%%.o) \
85412798Swpaul$(TARGETS_SVC.c:%%.c=%%.o) ");
85512798Swpaul
85612798Swpaul
85712798Swpaul	f_print(fout, "\n# Compiler flags \n");
85812798Swpaul	if (mtflag)
85999979Salfred		f_print(fout, "\nCFLAGS += -D_REENTRANT -D_THEAD_SAFE \nLDLIBS += -pthread\n");
86099979Salfred
86112798Swpaul	f_print(fout, "RPCGENFLAGS = \n");
86212798Swpaul
86312798Swpaul	f_print(fout, "\n# Targets \n\n");
86412798Swpaul
86512798Swpaul	f_print(fout, "all : $(CLIENT) $(SERVER)\n\n");
86612798Swpaul	f_print(fout, "$(TARGETS) : $(SOURCES.x) \n");
86712798Swpaul	f_print(fout, "\trpcgen $(RPCGENFLAGS) $(SOURCES.x)\n\n");
868259914Sdfr	if (allfiles) {
869259914Sdfr		f_print(fout, "\trpcgen -Sc $(RPCGENFLAGS) $(SOURCES.x) -o %s\n\n", clientname);
870259914Sdfr		f_print(fout, "\trpcgen -Ss $(RPCGENFLAGS) $(SOURCES.x) -o %s\n\n", servername);
871259914Sdfr	}
87212798Swpaul	f_print(fout, "$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) \
87312798Swpaul$(TARGETS_CLNT.c) \n\n");
87412798Swpaul
87512798Swpaul	f_print(fout, "$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) \
87612798Swpaul$(TARGETS_SVC.c) \n\n");
87712798Swpaul	f_print(fout, "$(CLIENT) : $(OBJECTS_CLNT) \n");
87812798Swpaul	f_print(fout, "\t$(CC) -o $(CLIENT) $(OBJECTS_CLNT) \
87912798Swpaul$(LDLIBS) \n\n");
88012798Swpaul	f_print(fout, "$(SERVER) : $(OBJECTS_SVC) \n");
881267174Sbdrewery	f_print(fout, "\t$(CC) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n");
882267174Sbdrewery	f_print(fout, "clean:\n\t rm -f core $(TARGETS) $(OBJECTS_CLNT) \
88312798Swpaul$(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n");
88412798Swpaul}
88512798Swpaul
88612798Swpaul
88712798Swpaul
88812798Swpaul/*
8898874Srgrimes * Perform registrations for service output
89012798Swpaul * Return 0 if failed; 1 otherwise.
8911897Swollman */
89217142Sjkhstatic int
893152398Sdwmalonedo_registers(int argc, const char *argv[])
8941897Swollman{
8951897Swollman	int i;
8961897Swollman
89712798Swpaul	if (inetdflag || !tirpcflag) {
89812798Swpaul		for (i = 1; i < argc; i++) {
89912798Swpaul			if (streq(argv[i], "-s")) {
90012798Swpaul				if (!check_nettype(argv[i + 1],
90112798Swpaul						    valid_i_nettypes))
90212798Swpaul					return (0);
90312798Swpaul				write_inetd_register(argv[i + 1]);
90412798Swpaul				i++;
90512798Swpaul			}
9061897Swollman		}
90712798Swpaul	} else {
90812798Swpaul		for (i = 1; i < argc; i++)
90912798Swpaul			if (streq(argv[i], "-s")) {
91012798Swpaul				if (!check_nettype(argv[i + 1],
91112798Swpaul						    valid_ti_nettypes))
91212798Swpaul					return (0);
91312798Swpaul				write_nettype_register(argv[i + 1]);
91412798Swpaul				i++;
91512798Swpaul			} else if (streq(argv[i], "-n")) {
91612798Swpaul				write_netid_register(argv[i + 1]);
91712798Swpaul				i++;
91812798Swpaul			}
9191897Swollman	}
92012798Swpaul	return (1);
9211897Swollman}
9221897Swollman
9231897Swollman/*
92412798Swpaul * Add another argument to the arg list
92512798Swpaul */
92612798Swpaulstatic void
927152398Sdwmaloneaddarg(const char *cp)
92812798Swpaul{
92912798Swpaul	if (argcount >= ARGLISTLEN) {
93027935Scharnier		warnx("too many defines");
93112798Swpaul		crash();
93212798Swpaul		/*NOTREACHED*/
93312798Swpaul	}
934152415Srodrigc	if (cp != NULL)
935152415Srodrigc		arglist[argcount++] = xstrdup(cp);
936152415Srodrigc	else
937152415Srodrigc		arglist[argcount++] = NULL;
93812798Swpaul
93912798Swpaul}
94012798Swpaul
941231079Sdim/*
942231079Sdim * Insert an argument at the specified location
943231079Sdim */
94412798Swpaulstatic void
945231079Sdiminsarg(int place, const char *cp)
94612798Swpaul{
947231079Sdim	int i;
948231079Sdim
949231079Sdim	if (argcount >= ARGLISTLEN) {
950231079Sdim		warnx("too many defines");
95112798Swpaul		crash();
95212798Swpaul		/*NOTREACHED*/
95312798Swpaul	}
954231079Sdim
955231079Sdim	/* Move up existing arguments */
956231080Sdim	for (i = argcount - 1; i >= place; i--)
957231079Sdim		arglist[i + 1] = arglist[i];
958231079Sdim
959231079Sdim	arglist[place] = xstrdup(cp);
960231079Sdim	argcount++;
96112798Swpaul}
96212798Swpaul
96312798Swpaul/*
96412798Swpaul * if input file is stdin and an output file is specified then complain
96512798Swpaul * if the file already exists. Otherwise the file may get overwritten
96612798Swpaul * If input file does not exist, exit with an error
96712798Swpaul */
96812798Swpaul
96912798Swpaulstatic void
970152398Sdwmalonecheckfiles(const char *infile, const char *outfile)
97112798Swpaul{
97212798Swpaul
97312798Swpaul	struct stat buf;
97412798Swpaul
97512798Swpaul	if (infile)		/* infile ! = NULL */
97612798Swpaul		if (stat(infile, &buf) < 0)
97712798Swpaul		{
97827935Scharnier			warn("%s", infile);
97912798Swpaul			crash();
980298089Spfg		}
98112798Swpaul	if (outfile) {
98212798Swpaul		if (stat(outfile, &buf) < 0)
98312798Swpaul			return;	/* file does not exist */
98412798Swpaul		else {
98527935Scharnier			warnx("file '%s' already exists and may be overwritten", outfile);
98612798Swpaul			crash();
98712798Swpaul		}
98812798Swpaul	}
98912798Swpaul}
99012798Swpaul
99112798Swpaul/*
9928874Srgrimes * Parse command line arguments
9931897Swollman */
99417142Sjkhstatic int
995152398Sdwmaloneparseargs(int argc, const char *argv[], struct commandline *cmd)
9961897Swollman{
9971897Swollman	int i;
9981897Swollman	int j;
99912798Swpaul	char c, ch;
100012798Swpaul	char flag[(1 << 8 * sizeof (char))];
10011897Swollman	int nflags;
10021897Swollman
10031897Swollman	cmd->infile = cmd->outfile = NULL;
10041897Swollman	if (argc < 2) {
10051897Swollman		return (0);
10061897Swollman	}
100712798Swpaul	allfiles = 0;
10081897Swollman	flag['c'] = 0;
10091897Swollman	flag['h'] = 0;
10101897Swollman	flag['l'] = 0;
10111897Swollman	flag['m'] = 0;
101212798Swpaul	flag['o'] = 0;
101312798Swpaul	flag['s'] = 0;
101412798Swpaul	flag['n'] = 0;
101512798Swpaul	flag['t'] = 0;
101612798Swpaul	flag['S'] = 0;
101712798Swpaul	flag['C'] = 0;
101812798Swpaul	flag['M'] = 0;
101912798Swpaul
10201897Swollman	for (i = 1; i < argc; i++) {
10211897Swollman		if (argv[i][0] != '-') {
10221897Swollman			if (cmd->infile) {
102327935Scharnier				warnx("cannot specify more than one input file");
10241897Swollman				return (0);
10251897Swollman			}
10261897Swollman			cmd->infile = argv[i];
10271897Swollman		} else {
10281897Swollman			for (j = 1; argv[i][j] != 0; j++) {
10291897Swollman				c = argv[i][j];
10301897Swollman				switch (c) {
103112798Swpaul				case 'a':
103212798Swpaul					allfiles = 1;
103312798Swpaul					break;
10341897Swollman				case 'c':
10351897Swollman				case 'h':
10361897Swollman				case 'l':
10371897Swollman				case 'm':
103812798Swpaul				case 't':
103917142Sjkh					if (flag[(int)c]) {
10401897Swollman						return (0);
10411897Swollman					}
104217142Sjkh					flag[(int)c] = 1;
10431897Swollman					break;
104412798Swpaul				case 'S':
104512798Swpaul					/*
104612798Swpaul					 * sample flag: Ss or Sc.
104712798Swpaul					 *  Ss means set flag['S'];
104812798Swpaul					 *  Sc means set flag['C'];
104912798Swpaul					 *  Sm means set flag['M'];
105012798Swpaul					 */
105112798Swpaul					ch = argv[i][++j]; /* get next char */
105212798Swpaul					if (ch == 's')
105312798Swpaul						ch = 'S';
105412798Swpaul					else if (ch == 'c')
105512798Swpaul						ch = 'C';
105612798Swpaul					else if (ch == 'm')
105712798Swpaul						ch = 'M';
105812798Swpaul					else
105912798Swpaul						return (0);
106012798Swpaul
106117142Sjkh					if (flag[(int)ch]) {
106212798Swpaul						return (0);
106312798Swpaul					}
106417142Sjkh					flag[(int)ch] = 1;
106512798Swpaul					break;
106612798Swpaul				case 'C': /* ANSI C syntax */
106712798Swpaul					ch = argv[i][j+1]; /* get next char */
106812798Swpaul
106912798Swpaul					if (ch != 'C')
107012798Swpaul						break;
107112798Swpaul					CCflag = 1;
107212798Swpaul					break;
107312798Swpaul				case 'b':
107412798Swpaul					/*
107512798Swpaul					 *  Turn TIRPC flag off for
107612798Swpaul					 *  generating backward compatible
107712798Swpaul					 *  code
107812798Swpaul					 */
107912798Swpaul					tirpcflag = 0;
108012798Swpaul					break;
108112798Swpaul
108212798Swpaul				case 'I':
108312798Swpaul					inetdflag = 1;
108412798Swpaul					break;
108512798Swpaul				case 'N':
108612798Swpaul					newstyle = 1;
108712798Swpaul					break;
108812798Swpaul				case 'L':
108912798Swpaul					logflag = 1;
109012798Swpaul					break;
109199979Salfred				case 'P':
109299979Salfred					pmflag = 1;
109399979Salfred					break;
109412798Swpaul				case 'K':
109512798Swpaul					if (++i == argc) {
109612798Swpaul						return (0);
109712798Swpaul					}
109812798Swpaul					svcclosetime = argv[i];
109912798Swpaul					goto nextarg;
110012798Swpaul				case 'T':
110112798Swpaul					tblflag = 1;
110212798Swpaul					break;
110312798Swpaul				case 'M':
110412798Swpaul					mtflag = 1;
110512798Swpaul					break;
110612798Swpaul				case 'i' :
110712798Swpaul					if (++i == argc) {
110812798Swpaul						return (0);
110912798Swpaul					}
1110149680Sstefanf					inline_size = atoi(argv[i]);
111112798Swpaul					goto nextarg;
111212798Swpaul				case 'n':
11131897Swollman				case 'o':
11141897Swollman				case 's':
11158874Srgrimes					if (argv[i][j - 1] != '-' ||
11161897Swollman					    argv[i][j + 1] != 0) {
11171897Swollman						return (0);
11181897Swollman					}
111917142Sjkh					flag[(int)c] = 1;
11201897Swollman					if (++i == argc) {
11211897Swollman						return (0);
11221897Swollman					}
112312798Swpaul					if (c == 'o') {
11241897Swollman						if (cmd->outfile) {
11251897Swollman							return (0);
11261897Swollman						}
11271897Swollman						cmd->outfile = argv[i];
11281897Swollman					}
11291897Swollman					goto nextarg;
113012798Swpaul				case 'D':
113112798Swpaul					if (argv[i][j - 1] != '-') {
113212798Swpaul						return (0);
113312798Swpaul					}
113412798Swpaul					(void) addarg(argv[i]);
113512798Swpaul					goto nextarg;
113612798Swpaul				case 'Y':
113712798Swpaul					if (++i == argc) {
113812798Swpaul						return (0);
113912798Swpaul					}
1140231054Sdim					if (strlcpy(pathbuf, argv[i],
1141231054Sdim					    sizeof(pathbuf)) >= sizeof(pathbuf)
1142231054Sdim					    || strlcat(pathbuf, "/cpp",
1143231054Sdim					    sizeof(pathbuf)) >=
1144231054Sdim					    sizeof(pathbuf)) {
114581956Skris						warnx("argument too long");
114681956Skris						return (0);
114781956Skris					}
114812798Swpaul					CPP = pathbuf;
114912798Swpaul					goto nextarg;
11501897Swollman
115112798Swpaul
115212798Swpaul
11531897Swollman				default:
11541897Swollman					return (0);
11551897Swollman				}
11561897Swollman			}
115712798Swpaul		nextarg:
11581897Swollman			;
11591897Swollman		}
11601897Swollman	}
116112798Swpaul
11621897Swollman	cmd->cflag = flag['c'];
11631897Swollman	cmd->hflag = flag['h'];
11641897Swollman	cmd->lflag = flag['l'];
11651897Swollman	cmd->mflag = flag['m'];
116612798Swpaul	cmd->nflag = flag['n'];
116712798Swpaul	cmd->sflag = flag['s'];
116812798Swpaul	cmd->tflag = flag['t'];
116912798Swpaul	cmd->Ssflag = flag['S'];
117012798Swpaul	cmd->Scflag = flag['C'];
117112798Swpaul	cmd->makefileflag = flag['M'];
117212798Swpaul
117312798Swpaul	if (tirpcflag) {
117499979Salfred		if (inetdflag)
117599979Salfred			pmflag = 0;
117612798Swpaul		if ((inetdflag && cmd->nflag)) {
117712798Swpaul			/* netid not allowed with inetdflag */
117827935Scharnier			warnx("cannot use netid flag with inetd flag");
117912798Swpaul			return (0);
118012798Swpaul		}
118112798Swpaul	} else {		/* 4.1 mode */
118212798Swpaul		pmflag = 0;	/* set pmflag only in tirpcmode */
118312798Swpaul		if (cmd->nflag) { /* netid needs TIRPC */
118427935Scharnier			warnx("cannot use netid flag without TIRPC");
118512798Swpaul			return (0);
118612798Swpaul		}
118712798Swpaul	}
118812798Swpaul
118912798Swpaul	if (newstyle && (tblflag || cmd->tflag)) {
119027935Scharnier		warnx("cannot use table flags with newstyle");
119112798Swpaul		return (0);
119212798Swpaul	}
119312798Swpaul
119412798Swpaul	/* check no conflicts with file generation flags */
119512798Swpaul	nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag +
119612798Swpaul		cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag +
119712798Swpaul			cmd->Scflag + cmd->makefileflag;
119812798Swpaul
11991897Swollman	if (nflags == 0) {
12001897Swollman		if (cmd->outfile != NULL || cmd->infile == NULL) {
12011897Swollman			return (0);
12021897Swollman		}
120312798Swpaul	} else if (cmd->infile == NULL &&
120412798Swpaul	    (cmd->Ssflag || cmd->Scflag || cmd->makefileflag)) {
120527935Scharnier		warnx("\"infile\" is required for template generation flags");
12061897Swollman		return (0);
120712798Swpaul	} if (nflags > 1) {
120827935Scharnier		warnx("cannot have more than one file generation flag");
120912798Swpaul		return (0);
12101897Swollman	}
12111897Swollman	return (1);
12121897Swollman}
121312798Swpaul
121417142Sjkhstatic void
1215201382Sedusage(void)
121612798Swpaul{
1217100441Scharnier	f_print(stderr, "%s\n%s\n%s\n%s\n%s\n",
121827935Scharnier		"usage: rpcgen infile",
121927935Scharnier		"       rpcgen [-abCLNTM] [-Dname[=value]] [-i size]\
122099979Salfred[-I -P [-K seconds]] [-Y path] infile",
122127935Scharnier		"       rpcgen [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm]\
122227935Scharnier[-o outfile] [infile]",
122327935Scharnier		"       rpcgen [-s nettype]* [-o outfile] [infile]",
122427935Scharnier		"       rpcgen [-n netid]* [-o outfile] [infile]");
122512798Swpaul	options_usage();
122612798Swpaul	exit(1);
122712798Swpaul}
122812798Swpaul
122917142Sjkhstatic void
1230201382Sedoptions_usage(void)
123112798Swpaul{
123212798Swpaul	f_print(stderr, "options:\n");
123312798Swpaul	f_print(stderr, "-a\t\tgenerate all files, including samples\n");
123499979Salfred	f_print(stderr, "-b\t\tbackward compatibility mode (generates code \
123599979Salfredfor FreeBSD 4.X)\n");
123612798Swpaul	f_print(stderr, "-c\t\tgenerate XDR routines\n");
123712798Swpaul	f_print(stderr, "-C\t\tANSI C mode\n");
123812798Swpaul	f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n");
123912798Swpaul	f_print(stderr, "-h\t\tgenerate header file\n");
124012798Swpaul	f_print(stderr, "-i size\t\tsize at which to start generating\
124112798Swpaulinline code\n");
124299979Salfred	f_print(stderr, "-I\t\tgenerate code for inetd support in server\n");
124312798Swpaul	f_print(stderr, "-K seconds\tserver exits after K seconds of\
124412798Swpaulinactivity\n");
124512798Swpaul	f_print(stderr, "-l\t\tgenerate client side stubs\n");
124612798Swpaul	f_print(stderr, "-L\t\tserver errors will be printed to syslog\n");
124712798Swpaul	f_print(stderr, "-m\t\tgenerate server side stubs\n");
124812798Swpaul	f_print(stderr, "-M\t\tgenerate MT-safe code\n");
124912798Swpaul	f_print(stderr, "-n netid\tgenerate server code that supports\
125012798Swpaulnamed netid\n");
125112798Swpaul	f_print(stderr, "-N\t\tsupports multiple arguments and\
125212798Swpaulcall-by-value\n");
125312798Swpaul	f_print(stderr, "-o outfile\tname of the output file\n");
125499979Salfred	f_print(stderr, "-P\t\tgenerate code for port monitoring support in server\n");
125512798Swpaul	f_print(stderr, "-s nettype\tgenerate server code that supports named\
125612798Swpaulnettype\n");
125712798Swpaul	f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote\
125812798Swpaulprocedures\n");
125912798Swpaul	f_print(stderr, "-Ss\t\tgenerate sample server code that defines\
126012798Swpaulremote procedures\n");
126112798Swpaul	f_print(stderr, "-Sm \t\tgenerate makefile template \n");
126212798Swpaul
126312798Swpaul	f_print(stderr, "-t\t\tgenerate RPC dispatch table\n");
126412798Swpaul	f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n");
126512798Swpaul	f_print(stderr, "-Y path\t\tpath where cpp is found\n");
126612798Swpaul	exit(1);
126712798Swpaul}
1268