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