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