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