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