1 /* $OpenBSD: rpc_main.c,v 1.3 1997/10/11 21:10:41 deraadt Exp $ */ 2 /* $NetBSD: rpc_main.c,v 1.9 1996/02/19 11:12:43 pk Exp $ */ 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"; 35 static char cvsid[] = "$OpenBSD: rpc_main.c,v 1.3 1997/10/11 21:10:41 deraadt Exp $"; 36 #endif 37 38 /* 39 * rpc_main.c, Top level of the RPC protocol compiler. 40 */ 41 42 #define RPCGEN_VERSION "199506" /* This program's version (year & month) */ 43 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 115 int doinline=INLINE; /* length at which to start doing an inline. 3 = default 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 539 f_print(fout, "#define RPCGEN_VERSION\t%s\n\n", RPCGEN_VERSION); 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 } 1015 doinline = atoi(argv[i]); 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 } 1155