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