Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

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