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