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