1 /* $OpenBSD: rpc_main.c,v 1.20 2004/05/09 22:22:45 deraadt Exp $ */
2 /* $NetBSD: rpc_main.c,v 1.9 1996/02/19 11:12:43 pk Exp $ */
3 /*
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or
9 * program developed by the user or with the express written consent of
10 * Sun Microsystems, Inc.
11 *
12 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
13 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
14 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
15 *
16 * Sun RPC is provided with no support and without any obligation on the
17 * part of Sun Microsystems, Inc. to assist in its use, correction,
18 * modification or enhancement.
19 *
20 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
21 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
22 * OR ANY PART THEREOF.
23 *
24 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
25 * or profits or other special, indirect and consequential damages, even if
26 * Sun has been advised of the possibility of such damages.
27 *
28 * Sun Microsystems, Inc.
29 * 2550 Garcia Avenue
30 * Mountain View, California 94043
31 */
32
33 #ifndef lint
34 static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI";
35 static char cvsid[] = "$OpenBSD: rpc_main.c,v 1.20 2004/05/09 22:22:45 deraadt Exp $";
36 #endif
37
38 /*
39 * rpc_main.c, Top level of the RPC protocol compiler.
40 */
41
42 #define RPCGEN_VERSION "199506"/* This program's version (year & month) */
43
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/file.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <stdlib.h>
52 #include <ctype.h>
53 #include <sys/stat.h>
54 #include "rpc_parse.h"
55 #include "rpc_util.h"
56 #include "rpc_scan.h"
57
58 #define EXTEND 1 /* alias for TRUE */
59 #define DONT_EXTEND 0 /* alias for FALSE */
60
61 #define SVR4_CPP "/usr/ccs/lib/cpp"
62 #define SUNOS_CPP "/lib/cpp"
63 static int cppDefined = 0; /* explicit path for C preprocessor */
64
65 struct commandline {
66 int cflag; /* xdr C routines */
67 int hflag; /* header file */
68 int lflag; /* client side stubs */
69 int mflag; /* server side stubs */
70 int nflag; /* netid flag */
71 int sflag; /* server stubs for the given transport */
72 int tflag; /* dispatch Table file */
73 int Ssflag; /* produce server sample code */
74 int Scflag; /* produce client sample code */
75 char *infile; /* input module name */
76 char *outfile;/* output module name */
77 };
78
79 static char *cmdname;
80
81 static char *svcclosetime = "120";
82 static char *CPP = "/usr/libexec/cpp";
83 static char CPPFLAGS[] = "-C";
84 static char pathbuf[MAXPATHLEN];
85 static char *allv[] = {
86 "rpcgen", "-s", "udp", "-s", "tcp",
87 };
88 static int allc = sizeof(allv) / sizeof(allv[0]);
89 static char *allnv[] = {
90 "rpcgen", "-s", "netpath",
91 };
92 static int allnc = sizeof(allnv) / sizeof(allnv[0]);
93
94 #define ARGLISTLEN 20
95 #define FIXEDARGS 2
96
97 static char *arglist[ARGLISTLEN];
98 static int argcount = FIXEDARGS;
99
100
101 int nonfatalerrors; /* errors */
102 int inetdflag /* = 1 */ ; /* Support for inetd *//* is now the
103 * default */
104 int pmflag; /* Support for port monitors */
105 int logflag; /* Use syslog instead of fprintf for errors */
106 int tblflag; /* Support for dispatch table file */
107 int callerflag; /* Generate svc_caller() function */
108
109 #define INLINE 3
110 /* length at which to start doing an inline */
111
112 int doinline = INLINE; /* length at which to start doing an
113 * inline. 3 = default if 0, no
114 * xdr_inline code */
115
116 int indefinitewait; /* If started by port monitors, hang till it
117 * wants */
118 int exitnow; /* If started by port monitors, exit after
119 * the call */
120 int timerflag; /* TRUE if !indefinite && !exitnow */
121 int newstyle; /* newstyle of passing arguments (by value) */
122 int Cflag = 0; /* ANSI C syntax */
123 static int allfiles; /* generate all files */
124 int tirpcflag = 0; /* generating code for tirpc, by default */
125
126 #ifdef __MSDOS__
127 static char *dos_cppfile = NULL;
128 #endif
129
130 static void c_output(char *, char *, int, char *);
131 static void h_output(char *, char *, int, char *);
132 static void s_output(int, char **, char *, char *, int, char *, int, int);
133 static void l_output(char *, char *, int, char *);
134 static void t_output(char *, char *, int, char *);
135 static void svc_output(char *, char *, int, char *);
136 static void clnt_output(char *, char *, int, char *);
137 static int do_registers(int, char **);
138 static void addarg(char *);
139 static void putarg(int, char *);
140 static void clear_args(void);
141 static void checkfiles(char *, char *);
142 static int parseargs(int, char **, struct commandline *);
143 static void usage(void);
144 void c_initialize(void);
145
146 int
main(int argc,char * argv[])147 main(int argc, char *argv[])
148 {
149 struct commandline cmd;
150
151 (void) memset((char *) &cmd, 0, sizeof(struct commandline));
152 clear_args();
153 if (!parseargs(argc, argv, &cmd))
154 usage();
155
156 if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag ||
157 cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) {
158 checkfiles(cmd.infile, cmd.outfile);
159 } else
160 checkfiles(cmd.infile, NULL);
161
162 if (cmd.cflag) {
163 c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile);
164 } else if (cmd.hflag) {
165 h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile);
166 } else if (cmd.lflag) {
167 l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile);
168 } else if (cmd.sflag || cmd.mflag || (cmd.nflag)) {
169 s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND,
170 cmd.outfile, cmd.mflag, cmd.nflag);
171 } else if (cmd.tflag) {
172 t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile);
173 } else if (cmd.Ssflag) {
174 svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile);
175 } else if (cmd.Scflag) {
176 clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile);
177 } else {
178 /* the rescans are required, since cpp may effect input */
179 c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c");
180 reinitialize();
181 h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h");
182 reinitialize();
183 l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c");
184 reinitialize();
185 if (inetdflag || !tirpcflag)
186 s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND,
187 "_svc.c", cmd.mflag, cmd.nflag);
188 else
189 s_output(allnc, allnv, cmd.infile, "-DRPC_SVC",
190 EXTEND, "_svc.c", cmd.mflag, cmd.nflag);
191 if (tblflag) {
192 reinitialize();
193 t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i");
194 }
195 if (allfiles) {
196 reinitialize();
197 svc_output(cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c");
198 }
199 if (allfiles) {
200 reinitialize();
201 clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c");
202 }
203 }
204 #ifdef __MSDOS__
205 if (dos_cppfile != NULL) {
206 (void) fclose(fin);
207 (void) unlink(dos_cppfile);
208 }
209 #endif
210 exit(nonfatalerrors);
211 /* NOTREACHED */
212 }
213
214 /*
215 * add extension to filename
216 */
217 static char *
extendfile(char * path,char * ext)218 extendfile(char *path, char *ext)
219 {
220 char *file;
221 char *res;
222 char *p;
223 size_t len;
224
225 if ((file = strrchr(path, '/')) == NULL)
226 file = path;
227 else
228 file++;
229
230 len = strlen(file) + strlen(ext) + 1;
231 res = alloc(len);
232 if (res == NULL) {
233 fprintf(stderr, "could not allocate memory\n");
234 exit(1);
235 }
236 p = strrchr(file, '.');
237 if (p == NULL)
238 p = file + strlen(file);
239 (void) strlcpy(res, file, len);
240 (void) strlcpy(res + (p - file), ext, len - (p - file));
241 return (res);
242 }
243
244 /*
245 * Open output file with given extension
246 */
247 static void
open_output(char * infile,char * outfile)248 open_output(char *infile, char *outfile)
249 {
250
251 if (outfile == NULL) {
252 fout = stdout;
253 return;
254 }
255 if (infile != NULL && streq(outfile, infile)) {
256 fprintf(stderr, "%s: output would overwrite %s\n", cmdname,
257 infile);
258 crash();
259 }
260 fout = fopen(outfile, "w");
261 if (fout == NULL) {
262 fprintf(stderr, "%s: unable to open ", cmdname);
263 perror(outfile);
264 crash();
265 }
266 record_open(outfile);
267
268 }
269
270 static void
add_warning(void)271 add_warning(void)
272 {
273 fprintf(fout, "/*\n");
274 fprintf(fout, " * Please do not edit this file.\n");
275 fprintf(fout, " * It was generated using rpcgen.\n");
276 fprintf(fout, " */\n\n");
277 }
278
279 /* clear list of arguments */
280 static void
clear_args(void)281 clear_args(void)
282 {
283 int i;
284 for (i = FIXEDARGS; i < ARGLISTLEN; i++)
285 arglist[i] = NULL;
286 argcount = FIXEDARGS;
287 }
288
289 /* make sure that a CPP exists */
290 static void
find_cpp(void)291 find_cpp(void)
292 {
293 struct stat buf;
294
295 /* SVR4 or explicit cpp does not exist */
296 if (stat(CPP, &buf) < 0) {
297 if (cppDefined) {
298 fprintf(stderr, "cannot find C preprocessor: %s \n", CPP);
299 crash();
300 } else {
301 /* try the other one */
302 CPP = SUNOS_CPP;
303 if (stat(CPP, &buf) < 0) { /* can't find any cpp */
304 fprintf(stderr,
305 "cannot find any C preprocessor: %s\n", CPP);
306 crash();
307 }
308 }
309 }
310 }
311
312 /*
313 * Open input file with given define for C-preprocessor
314 */
315 static void
open_input(char * infile,char * define)316 open_input(char *infile, char *define)
317 {
318 int pd[2];
319
320 infilename = (infile == NULL) ? "<stdin>" : infile;
321 #ifdef __MSDOS__
322 #define DOSCPP "\\prog\\bc31\\bin\\cpp.exe"
323 {
324 int retval;
325 char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE],
326 ext[MAXEXT];
327 char cppfile[MAXPATH];
328 char *cpp;
329
330 if ((cpp = searchpath("cpp.exe")) == NULL &&
331 (cpp = getenv("RPCGENCPP")) == NULL)
332 cpp = DOSCPP;
333
334 putarg(0, cpp);
335 putarg(1, "-P-");
336 putarg(2, CPPFLAGS);
337 addarg(define);
338 addarg(infile);
339 addarg(NULL);
340
341 retval = spawnvp(P_WAIT, arglist[0], arglist);
342 if (retval != 0) {
343 fprintf(stderr, "%s: C PreProcessor failed\n", cmdname);
344 crash();
345 }
346 fnsplit(infile, drive, dir, name, ext);
347 fnmerge(cppfile, drive, dir, name, ".i");
348
349 fin = fopen(cppfile, "r");
350 if (fin == NULL) {
351 fprintf(stderr, "%s: ", cmdname);
352 perror(cppfile);
353 crash();
354 }
355 dos_cppfile = strdup(cppfile);
356 if (dos_cppfile == NULL) {
357 fprintf(stderr, "%s: out of memory\n", cmdname);
358 crash();
359 }
360 }
361 #else
362 (void) pipe(pd);
363 switch (fork()) {
364 case 0:
365 find_cpp();
366 putarg(0, CPP);
367 putarg(1, CPPFLAGS);
368 addarg(define);
369 addarg(infile);
370 addarg((char *) NULL);
371 (void) close(1);
372 (void) dup2(pd[1], 1);
373 (void) close(pd[0]);
374 execv(arglist[0], arglist);
375 perror("execv");
376 exit(1);
377 case -1:
378 perror("fork");
379 exit(1);
380 }
381 (void) close(pd[1]);
382 fin = fdopen(pd[0], "r");
383 #endif
384 if (fin == NULL) {
385 fprintf(stderr, "%s: ", cmdname);
386 perror(infilename);
387 crash();
388 }
389 }
390
391 /* valid tirpc nettypes */
392 static char *valid_ti_nettypes[] = {
393 "netpath",
394 "visible",
395 "circuit_v",
396 "datagram_v",
397 "circuit_n",
398 "datagram_n",
399 "udp",
400 "tcp",
401 "raw",
402 NULL
403 };
404
405 /* valid inetd nettypes */
406 static char *valid_i_nettypes[] = {
407 "udp",
408 "tcp",
409 NULL
410 };
411
412 static int
check_nettype(char * name,char * list_to_check[])413 check_nettype(char *name, char *list_to_check[])
414 {
415 int i;
416 for (i = 0; list_to_check[i] != NULL; i++) {
417 if (strcmp(name, list_to_check[i]) == 0)
418 return 1;
419 }
420 fprintf(stderr, "illegal nettype :\'%s\'\n", name);
421 return 0;
422 }
423
424 /*
425 * Compile into an XDR routine output file
426 */
427
428 static void
c_output(infile,define,extend,outfile)429 c_output(infile, define, extend, outfile)
430 char *infile;
431 char *define;
432 int extend;
433 char *outfile;
434 {
435 definition *def;
436 char *include;
437 char *outfilename;
438 long tell;
439
440 c_initialize();
441 open_input(infile, define);
442 outfilename = extend ? extendfile(infile, outfile) : outfile;
443 open_output(infile, outfilename);
444 add_warning();
445 if (infile && (include = extendfile(infile, ".h"))) {
446 fprintf(fout, "#include \"%s\"\n", include);
447 free(include);
448 /* .h file already contains rpc/rpc.h */
449 } else
450 fprintf(fout, "#include <rpc/rpc.h>\n");
451 tell = ftell(fout);
452 while ((def = get_definition())) {
453 emit(def);
454 }
455 if (extend && tell == ftell(fout)) {
456 (void) unlink(outfilename);
457 }
458 }
459
460
461 void
c_initialize(void)462 c_initialize(void)
463 {
464
465 /* add all the starting basic types */
466
467 add_type(1, "int");
468 add_type(1, "long");
469 add_type(1, "short");
470 add_type(1, "bool");
471
472 add_type(1, "u_int");
473 add_type(1, "u_long");
474 add_type(1, "u_short");
475
476 }
477
478 char rpcgen_table_dcl[] = "struct rpcgen_table {\n\
479 char *(*proc)();\n\
480 xdrproc_t xdr_arg;\n\
481 unsigned int len_arg;\n\
482 xdrproc_t xdr_res;\n\
483 unsigned int len_res;\n\
484 };\n";
485
486
487 static char *
generate_guard(char * pathname)488 generate_guard(char *pathname)
489 {
490 char *filename, *guard, *tmp;
491
492 filename = strrchr(pathname, '/'); /* find last component */
493 filename = ((filename == 0) ? pathname : filename + 1);
494 guard = strdup(filename);
495 if (guard == NULL) {
496 fprintf(stderr, "out of memory while processing %s\n", filename);
497 crash();
498 }
499
500 /* convert to upper case */
501 tmp = guard;
502 while (*tmp) {
503 if (islower(*tmp))
504 *tmp = toupper(*tmp);
505 tmp++;
506 }
507
508 guard = extendfile(guard, "_H_RPCGEN");
509 return (guard);
510 }
511
512 /*
513 * Compile into an XDR header file
514 */
515
516 static void
h_output(infile,define,extend,outfile)517 h_output(infile, define, extend, outfile)
518 char *infile;
519 char *define;
520 int extend;
521 char *outfile;
522 {
523 definition *def;
524 char *outfilename;
525 long tell;
526 char *guard;
527 list *l;
528
529 open_input(infile, define);
530 outfilename = extend ? extendfile(infile, outfile) : outfile;
531 open_output(infile, outfilename);
532 add_warning();
533 guard = generate_guard(outfilename ? outfilename : infile);
534
535 fprintf(fout, "#ifndef _%s\n#define _%s\n\n", guard,
536 guard);
537
538 fprintf(fout, "#define RPCGEN_VERSION\t%s\n\n", RPCGEN_VERSION);
539 fprintf(fout, "#include <rpc/rpc.h>\n\n");
540
541 tell = ftell(fout);
542 /* print data definitions */
543 while ((def = get_definition())) {
544 print_datadef(def);
545 }
546
547 /*
548 * print function declarations. Do this after data definitions
549 * because they might be used as arguments for functions
550 */
551 for (l = defined; l != NULL; l = l->next) {
552 print_funcdef(l->val);
553 }
554 if (extend && tell == ftell(fout)) {
555 (void) unlink(outfilename);
556 } else if (tblflag) {
557 fprintf(fout, rpcgen_table_dcl);
558 }
559 fprintf(fout, "\n#endif /* !_%s */\n", guard);
560 }
561
562 /*
563 * Compile into an RPC service
564 */
565 static void
s_output(argc,argv,infile,define,extend,outfile,nomain,netflag)566 s_output(argc, argv, infile, define, extend, outfile, nomain, netflag)
567 int argc;
568 char *argv[];
569 char *infile;
570 char *define;
571 int extend;
572 char *outfile;
573 int nomain;
574 int netflag;
575 {
576 char *include;
577 definition *def;
578 int foundprogram = 0;
579 char *outfilename;
580
581 open_input(infile, define);
582 outfilename = extend ? extendfile(infile, outfile) : outfile;
583 open_output(infile, outfilename);
584 add_warning();
585 if (infile && (include = extendfile(infile, ".h"))) {
586 fprintf(fout, "#include \"%s\"\n", include);
587 free(include);
588 } else
589 fprintf(fout, "#include <rpc/rpc.h>\n");
590
591 fprintf(fout, "#include <stdio.h>\n");
592 fprintf(fout, "#include <stdlib.h>/* getenv, exit */\n");
593 if (Cflag) {
594 fprintf(fout,
595 "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n");
596 fprintf(fout, "#include <string.h> /* strcmp */ \n");
597 }
598 fprintf(fout, "#include <netdb.h>\n"); /* evas */
599 if (strcmp(svcclosetime, "-1") == 0)
600 indefinitewait = 1;
601 else if (strcmp(svcclosetime, "0") == 0)
602 exitnow = 1;
603 else if (inetdflag || pmflag) {
604 fprintf(fout, "#include <signal.h>\n");
605 timerflag = 1;
606 }
607 if (!tirpcflag && inetdflag)
608 fprintf(fout, "#include <sys/ttycom.h>/* TIOCNOTTY */\n");
609 if (Cflag && (inetdflag || pmflag)) {
610 fprintf(fout, "#ifdef __cplusplus\n");
611 fprintf(fout, "#include <sysent.h> /* getdtablesize, open */\n");
612 fprintf(fout, "#endif /* __cplusplus */\n");
613
614 if (tirpcflag)
615 fprintf(fout, "#include <unistd.h> /* setsid */\n");
616 }
617 if (tirpcflag)
618 fprintf(fout, "#include <sys/types.h>\n");
619
620 fprintf(fout, "#include <memory.h>\n");
621 if (tirpcflag)
622 fprintf(fout, "#include <stropts.h>\n");
623
624 if (inetdflag || !tirpcflag) {
625 fprintf(fout, "#include <sys/socket.h>\n");
626 fprintf(fout, "#include <netinet/in.h>\n");
627 }
628 if ((netflag || pmflag) && tirpcflag) {
629 fprintf(fout, "#include <netconfig.h>\n");
630 }
631 if (/* timerflag && */ tirpcflag)
632 fprintf(fout, "#include <sys/resource.h> /* rlimit */\n");
633 if (logflag || inetdflag || pmflag) {
634 fprintf(fout, "#include <syslog.h>\n");
635 fprintf(fout, "#include <errno.h>\n");
636 }
637 /* for ANSI-C */
638 fprintf(fout, "\n#ifdef __STDC__\n#define SIG_PF void(*)(int)\n#endif\n");
639
640 fprintf(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n");
641 if (timerflag)
642 fprintf(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime);
643 while ((def = get_definition())) {
644 foundprogram |= (def->def_kind == DEF_PROGRAM);
645 }
646 if (extend && !foundprogram) {
647 (void) unlink(outfilename);
648 return;
649 }
650 if (callerflag) /* EVAS */
651 fprintf(fout, "\nstatic SVCXPRT *caller;\n"); /* EVAS */
652 write_most(infile, netflag, nomain);
653 if (!nomain) {
654 if (!do_registers(argc, argv)) {
655 if (outfilename)
656 (void) unlink(outfilename);
657 usage();
658 }
659 write_rest();
660 }
661 }
662
663 /*
664 * generate client side stubs
665 */
666 static void
l_output(infile,define,extend,outfile)667 l_output(infile, define, extend, outfile)
668 char *infile;
669 char *define;
670 int extend;
671 char *outfile;
672 {
673 char *include;
674 definition *def;
675 int foundprogram = 0;
676 char *outfilename;
677
678 open_input(infile, define);
679 outfilename = extend ? extendfile(infile, outfile) : outfile;
680 open_output(infile, outfilename);
681 add_warning();
682 if (Cflag)
683 fprintf(fout, "#include <memory.h> /* for memset */\n");
684 if (infile && (include = extendfile(infile, ".h"))) {
685 fprintf(fout, "#include \"%s\"\n", include);
686 free(include);
687 } else
688 fprintf(fout, "#include <rpc/rpc.h>\n");
689 while ((def = get_definition()))
690 foundprogram |= (def->def_kind == DEF_PROGRAM);
691
692 if (extend && !foundprogram) {
693 (void) unlink(outfilename);
694 return;
695 }
696 write_stubs();
697 }
698
699 /*
700 * generate the dispatch table
701 */
702 static void
t_output(infile,define,extend,outfile)703 t_output(infile, define, extend, outfile)
704 char *infile;
705 char *define;
706 int extend;
707 char *outfile;
708 {
709 definition *def;
710 int foundprogram = 0;
711 char *outfilename;
712
713 open_input(infile, define);
714 outfilename = extend ? extendfile(infile, outfile) : outfile;
715 open_output(infile, outfilename);
716 add_warning();
717 while ((def = get_definition()))
718 foundprogram |= (def->def_kind == DEF_PROGRAM);
719
720 if (extend && !foundprogram) {
721 (void) unlink(outfilename);
722 return;
723 }
724 write_tables();
725 }
726
727 /* sample routine for the server template */
728 static void
svc_output(infile,define,extend,outfile)729 svc_output(infile, define, extend, outfile)
730 char *infile;
731 char *define;
732 int extend;
733 char *outfile;
734 {
735 definition *def;
736 char *include;
737 char *outfilename;
738 long tell;
739
740 open_input(infile, define);
741 outfilename = extend ? extendfile(infile, outfile) : outfile;
742 checkfiles(infile, outfilename); /* check if outfile already
743 * exists. if so, print an
744 * error message and exit */
745 open_output(infile, outfilename);
746 add_sample_msg();
747
748 if (infile && (include = extendfile(infile, ".h"))) {
749 fprintf(fout, "#include \"%s\"\n", include);
750 free(include);
751 } else
752 fprintf(fout, "#include <rpc/rpc.h>\n");
753
754 tell = ftell(fout);
755 while ((def = get_definition()))
756 write_sample_svc(def);
757
758 if (extend && tell == ftell(fout))
759 (void) unlink(outfilename);
760 }
761
762
763 /* sample main routine for client */
764 static void
clnt_output(infile,define,extend,outfile)765 clnt_output(infile, define, extend, outfile)
766 char *infile;
767 char *define;
768 int extend;
769 char *outfile;
770 {
771 definition *def;
772 char *include, *outfilename;
773 long tell;
774 int has_program = 0;
775
776 open_input(infile, define);
777 outfilename = extend ? extendfile(infile, outfile) : outfile;
778
779 /*
780 * check if outfile already exists. if so,
781 * print an error message and exit
782 */
783 checkfiles(infile, outfilename);
784
785 open_output(infile, outfilename);
786 add_sample_msg();
787 if (infile && (include = extendfile(infile, ".h"))) {
788 fprintf(fout, "#include \"%s\"\n", include);
789 free(include);
790 } else
791 fprintf(fout, "#include <rpc/rpc.h>\n");
792 tell = ftell(fout);
793 while ((def = get_definition()))
794 has_program += write_sample_clnt(def);
795
796 if (has_program)
797 write_sample_clnt_main();
798
799 if (extend && tell == ftell(fout))
800 (void) unlink(outfilename);
801 }
802
803 /*
804 * Perform registrations for service output
805 * Return 0 if failed; 1 otherwise.
806 */
807 static int
do_registers(argc,argv)808 do_registers(argc, argv)
809 int argc;
810 char *argv[];
811 {
812 int i;
813
814 if (inetdflag || !tirpcflag) {
815 for (i = 1; i < argc; i++) {
816 if (streq(argv[i], "-s")) {
817 if (!check_nettype(argv[i + 1], valid_i_nettypes))
818 return 0;
819 write_inetd_register(argv[i + 1]);
820 i++;
821 }
822 }
823 } else {
824 for (i = 1; i < argc; i++)
825 if (streq(argv[i], "-s")) {
826 if (!check_nettype(argv[i + 1], valid_ti_nettypes))
827 return 0;
828 write_nettype_register(argv[i + 1]);
829 i++;
830 } else if (streq(argv[i], "-n")) {
831 write_netid_register(argv[i + 1]);
832 i++;
833 }
834 }
835 return 1;
836 }
837
838 /*
839 * Add another argument to the arg list
840 */
841 static void
addarg(cp)842 addarg(cp)
843 char *cp;
844 {
845 if (argcount >= ARGLISTLEN) {
846 fprintf(stderr, "rpcgen: too many defines\n");
847 crash();
848 /* NOTREACHED */
849 }
850 arglist[argcount++] = cp;
851
852 }
853
854 static void
putarg(where,cp)855 putarg(where, cp)
856 char *cp;
857 int where;
858 {
859 if (where >= ARGLISTLEN) {
860 fprintf(stderr, "rpcgen: arglist coding error\n");
861 crash();
862 /* NOTREACHED */
863 }
864 arglist[where] = cp;
865 }
866
867 /*
868 * if input file is stdin and an output file is specified then complain
869 * if the file already exists. Otherwise the file may get overwritten
870 * If input file does not exist, exit with an error
871 */
872 static void
checkfiles(infile,outfile)873 checkfiles(infile, outfile)
874 char *infile;
875 char *outfile;
876 {
877 struct stat buf;
878
879 if (infile) /* infile ! = NULL */
880 if (stat(infile, &buf) < 0) {
881 perror(infile);
882 crash();
883 }
884 #if 0
885 if (outfile) {
886 if (stat(outfile, &buf) < 0)
887 return; /* file does not exist */
888 else {
889 fprintf(stderr,
890 "file '%s' already exists and may be overwritten\n",
891 outfile);
892 crash();
893 }
894 }
895 #endif
896 }
897
898 /*
899 * Parse command line arguments
900 */
901 static int
parseargs(argc,argv,cmd)902 parseargs(argc, argv, cmd)
903 int argc;
904 char *argv[];
905 struct commandline *cmd;
906 {
907 int i, j, nflags;
908 char c, flag[(1 << 8 * sizeof(char))];
909
910 cmdname = argv[0];
911 cmd->infile = cmd->outfile = NULL;
912 if (argc < 2)
913 return (0);
914
915 allfiles = 0;
916 flag['c'] = 0;
917 flag['h'] = 0;
918 flag['l'] = 0;
919 flag['m'] = 0;
920 flag['o'] = 0;
921 flag['s'] = 0;
922 flag['n'] = 0;
923 flag['t'] = 0;
924 flag['S'] = 0;
925 flag['C'] = 0;
926 for (i = 1; i < argc; i++) {
927 if (argv[i][0] != '-') {
928 if (cmd->infile) {
929 fprintf(stderr,
930 "Cannot specify more than one input file!\n");
931 return (0);
932 }
933 cmd->infile = argv[i];
934 } else {
935 for (j = 1; argv[i][j] != 0; j++) {
936 c = argv[i][j];
937 switch (c) {
938 case 'A':
939 callerflag = 1;
940 break;
941 case 'a':
942 allfiles = 1;
943 break;
944 case 'c':
945 case 'h':
946 case 'l':
947 case 'm':
948 case 't':
949 if (flag[(unsigned char)c])
950 return (0);
951 flag[(unsigned char)c] = 1;
952 break;
953 case 'S':
954 /*
955 * sample flag: Ss or Sc. Ss means
956 * set flag['S']; Sc means set
957 * flag['C'];
958 */
959 c = argv[i][++j]; /* get next char */
960 if (c == 's')
961 c = 'S';
962 else if (c == 'c')
963 c = 'C';
964 else
965 return (0);
966
967 if (flag[(unsigned char)c])
968 return (0);
969 flag[(unsigned char)c] = 1;
970 break;
971 case 'C': /* ANSI C syntax */
972 Cflag = 1;
973 break;
974
975 case 'b':
976 /*
977 * turn TIRPC flag off for
978 * generating backward compatible
979 */
980 tirpcflag = 0;
981 break;
982
983 case 'I':
984 inetdflag = 1;
985 break;
986 case 'N':
987 newstyle = 1;
988 break;
989 case 'L':
990 logflag = 1;
991 break;
992 case 'K':
993 if (++i == argc)
994 return (0);
995 svcclosetime = argv[i];
996 goto nextarg;
997 case 'T':
998 tblflag = 1;
999 break;
1000 case 'i':
1001 if (++i == argc)
1002 return (0);
1003 doinline = atoi(argv[i]);
1004 goto nextarg;
1005 case 'n':
1006 case 'o':
1007 case 's':
1008 if (argv[i][j - 1] != '-' ||
1009 argv[i][j + 1] != 0)
1010 return (0);
1011 flag[(unsigned char)c] = 1;
1012 if (++i == argc)
1013 return (0);
1014 if (c == 's') {
1015 if (!streq(argv[i], "udp") &&
1016 !streq(argv[i], "tcp"))
1017 return (0);
1018 } else if (c == 'o') {
1019 if (cmd->outfile)
1020 return (0);
1021 cmd->outfile = argv[i];
1022 }
1023 goto nextarg;
1024 case 'D':
1025 if (argv[i][j - 1] != '-')
1026 return (0);
1027 (void) addarg(argv[i]);
1028 goto nextarg;
1029 case 'Y':
1030 if (++i == argc)
1031 return (0);
1032 if (snprintf(pathbuf, sizeof pathbuf,
1033 "%s/cpp", argv[i]) >= sizeof pathbuf)
1034 usage();
1035 CPP = pathbuf;
1036 cppDefined = 1;
1037 goto nextarg;
1038 default:
1039 return (0);
1040 }
1041 }
1042 nextarg:
1043 ;
1044 }
1045 }
1046
1047 cmd->cflag = flag['c'];
1048 cmd->hflag = flag['h'];
1049 cmd->lflag = flag['l'];
1050 cmd->mflag = flag['m'];
1051 cmd->nflag = flag['n'];
1052 cmd->sflag = flag['s'];
1053 cmd->tflag = flag['t'];
1054 cmd->Ssflag = flag['S'];
1055 cmd->Scflag = flag['C'];
1056
1057 if (tirpcflag) {
1058 pmflag = inetdflag ? 0 : 1; /* pmflag or inetdflag is
1059 * always TRUE */
1060 if (inetdflag && cmd->nflag) {
1061 /* netid not allowed with inetdflag */
1062 fprintf(stderr, "Cannot use netid flag with inetd flag!\n");
1063 return (0);
1064 }
1065 } else {
1066 /* 4.1 mode */
1067 pmflag = 0; /* set pmflag only in tirpcmode */
1068 inetdflag = 1; /* inetdflag is TRUE by default */
1069 if (cmd->nflag) {
1070 /* netid needs TIRPC */
1071 fprintf(stderr, "Cannot use netid flag without TIRPC!\n");
1072 return (0);
1073 }
1074 }
1075
1076 if (newstyle && (tblflag || cmd->tflag)) {
1077 fprintf(stderr, "Cannot use table flags with newstyle!\n");
1078 return (0);
1079 }
1080 /* check no conflicts with file generation flags */
1081 nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag +
1082 cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag;
1083
1084 if (nflags == 0) {
1085 if (cmd->outfile != NULL || cmd->infile == NULL)
1086 return (0);
1087 } else if (nflags > 1) {
1088 fprintf(stderr, "Cannot have more than one file generation flag!\n");
1089 return (0);
1090 }
1091 return (1);
1092 }
1093
1094 static void
usage(void)1095 usage(void)
1096 {
1097 fprintf(stderr, "usage: %s [-abACILNT] [-Dname[=value]] [-i lines] "
1098 "[-K seconds] infile\n", cmdname);
1099 fprintf(stderr, " %s [-c | -h | -l | -m | -t | -Sc | -Ss] "
1100 "[-o outfile] [infile]\n", cmdname);
1101 fprintf(stderr, " %s [-s nettype]* [-o outfile] [infile]\n", cmdname);
1102 exit(1);
1103 }
1104