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