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