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