1 /* 2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 3 * unrestricted use provided that this legend is included on all tape 4 * media and as a part of the software program in whole or part. Users 5 * may copy or modify Sun RPC without charge, but are not authorized 6 * to license or distribute it to anyone else except as part of a product or 7 * program developed by the user. 8 * 9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 12 * 13 * Sun RPC is provided with no support and without any obligation on the 14 * part of Sun Microsystems, Inc. to assist in its use, correction, 15 * modification or enhancement. 16 * 17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 19 * OR ANY PART THEREOF. 20 * 21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 22 * or profits or other special, indirect and consequential damages, even if 23 * Sun has been advised of the possibility of such damages. 24 * 25 * Sun Microsystems, Inc. 26 * 2550 Garcia Avenue 27 * Mountain View, California 94043 28 * 29 * @(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI 30 * $FreeBSD: src/usr.bin/rpcgen/rpc_main.c,v 1.11 1999/08/28 01:05:16 peter Exp $ 31 * $DragonFly: src/usr.bin/rpcgen/rpc_main.c,v 1.11 2007/08/25 08:55:26 corecode Exp $ 32 */ 33 34 35 #ident "@(#)rpc_main.c 1.21 94/04/25 SMI" 36 37 /* 38 * rpc_main.c, Top level of the RPC protocol compiler. 39 * Copyright (C) 1987, Sun Microsystems, Inc. 40 */ 41 42 #include <err.h> 43 #include <ctype.h> 44 #include <stdio.h> 45 #include <string.h> 46 #include <unistd.h> 47 #include <sys/types.h> 48 #include <sys/param.h> 49 #include <sys/file.h> 50 #include <sys/stat.h> 51 #include "rpc_parse.h" 52 #include "rpc_util.h" 53 #include "rpc_scan.h" 54 55 extern void write_sample_svc(definition *); 56 extern int write_sample_clnt(definition *); 57 extern void write_sample_clnt_main(void); 58 extern void add_sample_msg(void); 59 static void c_output(char *, char *, int, char *); 60 static void h_output(char *, char *, int, char *); 61 static void l_output(char *, char *, int, char *); 62 static void t_output(char *, char *, int, char *); 63 static void clnt_output(char *, char *, int, char *); 64 65 void c_initialize(void); 66 67 static void usage(void); 68 static void options_usage(void); 69 static int do_registers(int, char **); 70 static int parseargs(int, char **, struct commandline *); 71 static void svc_output(char *, char *, int, char *); 72 static void mkfile_output(struct commandline *); 73 static void s_output(int, char **, char *, char *, int, char *, int, int); 74 75 #define EXTEND 1 /* alias for TRUE */ 76 #define DONT_EXTEND 0 /* alias for FALSE */ 77 78 static int cppDefined = 0; /* explicit path for C preprocessor */ 79 80 static char *svcclosetime = "120"; 81 static char *CPP = NULL; 82 static char CPPFLAGS[] = "-C"; 83 static char pathbuf[MAXPATHLEN + 1]; 84 static char *allv[] = { 85 "rpcgen", "-s", "udp", "-s", "tcp", 86 }; 87 static int allc = sizeof (allv)/sizeof (allv[0]); 88 static char *allnv[] = { 89 "rpcgen", "-s", "netpath", 90 }; 91 static int allnc = sizeof (allnv)/sizeof (allnv[0]); 92 93 /* 94 * machinations for handling expanding argument list 95 */ 96 static void addarg(); /* add another argument to the list */ 97 static void putarg(); /* put argument at specified location */ 98 static void clear_args(); /* clear argument list */ 99 static void checkfiles(); /* check if out file already exists */ 100 101 102 103 #define ARGLISTLEN 20 104 #define FIXEDARGS 2 105 106 static char *arglist[ARGLISTLEN]; 107 static int argcount = FIXEDARGS; 108 109 110 int nonfatalerrors; /* errors */ 111 int inetdflag = 0; /* Support for inetd is now the default */ 112 int pmflag; /* Support for port monitors */ 113 int logflag; /* Use syslog instead of fprintf for errors */ 114 int tblflag; /* Support for dispatch table file */ 115 int mtflag = 0; /* Support for MT */ 116 #define INLINE 0 117 /* length at which to start doing an inline */ 118 119 int rpcgen_inline = INLINE; 120 /* 121 * Length at which to start doing an inline. INLINE = default 122 * if 0, no xdr_inline code 123 */ 124 125 int indefinitewait; /* If started by port monitors, hang till it wants */ 126 int exitnow; /* If started by port monitors, exit after the call */ 127 int timerflag; /* TRUE if !indefinite && !exitnow */ 128 int newstyle; /* newstyle of passing arguments (by value) */ 129 int Cflag = 0; /* ANSI C syntax */ 130 int CCflag = 0; /* C++ files */ 131 static int allfiles; /* generate all files */ 132 int tirpcflag = 0; /* generating code for tirpc, by default */ 133 xdrfunc *xdrfunc_head = NULL; /* xdr function list */ 134 xdrfunc *xdrfunc_tail = NULL; /* xdr function list */ 135 pid_t childpid; 136 137 138 int 139 main(int argc, char **argv) 140 { 141 struct commandline cmd; 142 143 memset(&cmd, 0, sizeof (struct commandline)); 144 clear_args(); 145 if (!parseargs(argc, argv, &cmd)) 146 usage(); 147 /* 148 * Only the client and server side stubs are likely to be customized, 149 * so in that case only, check if the outfile exists, and if so, 150 * print an error message and exit. 151 */ 152 if (cmd.Ssflag || cmd.Scflag || cmd.makefileflag) 153 checkfiles(cmd.infile, cmd.outfile); 154 else 155 checkfiles(cmd.infile, NULL); 156 157 if (cmd.cflag) { 158 c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); 159 } else if (cmd.hflag) { 160 h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); 161 } else if (cmd.lflag) { 162 l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile); 163 } else if (cmd.sflag || cmd.mflag || (cmd.nflag)) { 164 s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND, 165 cmd.outfile, cmd.mflag, cmd.nflag); 166 } else if (cmd.tflag) { 167 t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile); 168 } else if (cmd.Ssflag) { 169 svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND, 170 cmd.outfile); 171 } else if (cmd.Scflag) { 172 clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, 173 cmd.outfile); 174 } else if (cmd.makefileflag) { 175 mkfile_output(&cmd); 176 } else { 177 /* the rescans are required, since cpp may effect input */ 178 c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c"); 179 reinitialize(); 180 h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h"); 181 reinitialize(); 182 l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c"); 183 reinitialize(); 184 if (inetdflag || !tirpcflag) 185 s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND, 186 "_svc.c", cmd.mflag, cmd.nflag); 187 else 188 s_output(allnc, allnv, cmd.infile, "-DRPC_SVC", 189 EXTEND, "_svc.c", cmd.mflag, cmd.nflag); 190 if (tblflag) { 191 reinitialize(); 192 t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i"); 193 } 194 195 if (allfiles) { 196 reinitialize(); 197 svc_output(cmd.infile, "-DRPC_SERVER", EXTEND, 198 "_server.c"); 199 reinitialize(); 200 clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, 201 "_client.c"); 202 203 } 204 if (allfiles || (cmd.makefileflag == 1)){ 205 reinitialize(); 206 mkfile_output(&cmd); 207 } 208 } 209 210 exit(nonfatalerrors); 211 /* NOTREACHED */ 212 } 213 214 215 /* 216 * add extension to filename 217 */ 218 static char * 219 extendfile(char *path, char *ext) 220 { 221 char *res; 222 char *p; 223 char *file; 224 225 if ((file = strrchr(path, '/')) == NULL) 226 file = path; 227 else 228 file++; 229 res = alloc(strlen(file) + strlen(ext) + 1); 230 if (res == NULL) 231 abort(); 232 p = strrchr(file, '.'); 233 if (p == NULL) 234 p = file + strlen(file); 235 strcpy(res, file); 236 strcpy(res + (p - file), ext); 237 return(res); 238 } 239 240 /* 241 * Open output file with given extension 242 */ 243 static void 244 open_output(char *infile, char *outfile) 245 { 246 if (outfile == NULL) { 247 fout = stdout; 248 return; 249 } 250 251 if (infile != NULL && streq(outfile, infile)) { 252 warnx("%s already exists. No output generated", infile); 253 crash(); 254 } 255 fout = fopen(outfile, "w"); 256 if (fout == NULL) { 257 warn("unable to open %s", outfile); 258 crash(); 259 } 260 record_open(outfile); 261 } 262 263 static void 264 add_warning(void) 265 { 266 f_print(fout, "/*\n"); 267 f_print(fout, " * Please do not edit this file.\n"); 268 f_print(fout, " * It was generated using rpcgen.\n"); 269 f_print(fout, " */\n\n"); 270 } 271 272 /* clear list of arguments */ 273 static void 274 clear_args(void) 275 { 276 int i; 277 278 for (i = FIXEDARGS; i < ARGLISTLEN; i++) 279 arglist[i] = NULL; 280 argcount = FIXEDARGS; 281 } 282 283 /* make sure that a CPP exists */ 284 static int 285 find_cpp(void) 286 { 287 if (CPP) 288 return(0); 289 CPP = "cpp"; 290 return(1); 291 } 292 293 /* 294 * Open input file with given define for C-preprocessor 295 */ 296 static void 297 open_input(char *infile, char *define) 298 { 299 int pd[2]; 300 int usevp; 301 302 infilename = (infile == NULL) ? "<stdin>" : infile; 303 pipe(pd); 304 switch (childpid = fork()) { 305 case 0: 306 usevp = find_cpp(); 307 putarg(0, CPP); 308 putarg(1, CPPFLAGS); 309 addarg(define); 310 if (infile) 311 addarg(infile); 312 addarg((char *)NULL); 313 close(1); 314 dup2(pd[1], 1); 315 close(pd[0]); 316 if (usevp) 317 execvp(arglist[0], arglist); 318 else 319 execv(arglist[0], arglist); 320 err(1, "execv(%s)", arglist[0]); 321 case -1: 322 err(1, "fork"); 323 } 324 close(pd[1]); 325 fin = fdopen(pd[0], "r"); 326 if (fin == NULL) { 327 warn("%s", infilename); 328 crash(); 329 } 330 } 331 332 /* valid tirpc nettypes */ 333 static char* valid_ti_nettypes[] = 334 { 335 "netpath", 336 "visible", 337 "circuit_v", 338 "datagram_v", 339 "circuit_n", 340 "datagram_n", 341 "udp", 342 "tcp", 343 "raw", 344 NULL 345 }; 346 347 /* valid inetd nettypes */ 348 static char* valid_i_nettypes[] = 349 { 350 "udp", 351 "tcp", 352 NULL 353 }; 354 355 static int check_nettype(name, list_to_check) 356 char* name; 357 char* list_to_check[]; 358 { 359 int i; 360 for (i = 0; list_to_check[i] != NULL; i++) { 361 if (strcmp(name, list_to_check[i]) == 0) 362 return(1); 363 } 364 warnx("illegal nettype :\'%s\'", name); 365 return(0); 366 } 367 368 static char * 369 file_name(char *file, char *ext) 370 { 371 char *temp; 372 temp = extendfile(file, ext); 373 374 if (access(temp, F_OK) != -1) 375 return(temp); 376 else 377 return((char *)" "); 378 379 } 380 381 static void 382 c_output(char *infile, char *define, int extend, char *outfile) 383 { 384 definition *def; 385 char *include; 386 char *outfilename; 387 long tell; 388 389 c_initialize(); 390 open_input(infile, define); 391 outfilename = extend ? extendfile(infile, outfile) : outfile; 392 open_output(infile, outfilename); 393 add_warning(); 394 if (infile && (include = extendfile(infile, ".h"))) { 395 f_print(fout, "#include \"%s\"\n", include); 396 free(include); 397 /* .h file already contains rpc/rpc.h */ 398 } else 399 f_print(fout, "#include <rpc/rpc.h>\n"); 400 tell = ftell(fout); 401 while ( (def = get_definition()) ) 402 emit(def); 403 if (extend && tell == ftell(fout)) 404 unlink(outfilename); 405 } 406 407 void 408 c_initialize(void) 409 { 410 /* add all the starting basic types */ 411 add_type(1, "int"); 412 add_type(1, "long"); 413 add_type(1, "short"); 414 add_type(1, "bool"); 415 add_type(1, "u_int"); 416 add_type(1, "u_long"); 417 add_type(1, "u_short"); 418 } 419 420 char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ 421 char *(*proc)(); \n\ 422 xdrproc_t xdr_arg; \n\ 423 unsigned len_arg; \n\ 424 xdrproc_t xdr_res; \n\ 425 unsigned len_res; \n\ 426 }; \n"; 427 428 char *generate_guard(char *pathname) 429 { 430 char* filename, *guard, *tmp; 431 432 filename = strrchr(pathname, '/'); /* find last component */ 433 filename = ((filename == 0) ? pathname : filename+1); 434 guard = strdup(filename); 435 /* convert to upper case */ 436 tmp = guard; 437 while (*tmp) { 438 if (islower(*tmp)) 439 *tmp = toupper(*tmp); 440 tmp++; 441 } 442 guard = extendfile(guard, "_H_RPCGEN"); 443 return(guard); 444 } 445 446 /* 447 * Compile into an XDR header file 448 */ 449 450 static void 451 h_output(char *infile, char *define, int extend, char *outfile) 452 { 453 definition *def; 454 char *outfilename; 455 long tell; 456 char *guard; 457 list *l; 458 xdrfunc *xdrfuncp; 459 int i; 460 461 open_input(infile, define); 462 outfilename = extend ? extendfile(infile, outfile) : outfile; 463 open_output(infile, outfilename); 464 add_warning(); 465 if (outfilename || infile){ 466 guard = generate_guard(outfilename ? outfilename: infile); 467 } else 468 guard = "STDIN_"; 469 470 f_print(fout, "#ifndef _%s\n#define _%s\n\n", guard, 471 guard); 472 473 f_print(fout, "#include <rpc/rpc.h>\n"); 474 475 if (mtflag) 476 f_print(fout, "#include <pthread.h>\n"); 477 478 /* put the C++ support */ 479 if (Cflag && !CCflag){ 480 f_print(fout, "\n#ifdef __cplusplus\n"); 481 f_print(fout, "extern \"C\" {\n"); 482 f_print(fout, "#endif\n\n"); 483 } 484 485 /* put in a typedef for quadprecision. Only with Cflag */ 486 487 tell = ftell(fout); 488 489 /* print data definitions */ 490 while ((def = get_definition()) != 0) 491 print_datadef(def); 492 493 /* 494 * print function declarations. 495 * Do this after data definitions because they might be used as 496 * arguments for functions 497 */ 498 for (l = defined; l != NULL; l = l->next) 499 print_funcdef(l->val); 500 501 /* Now print all xdr func declarations */ 502 if (xdrfunc_head != NULL) { 503 f_print(fout, "\n/* the xdr functions */\n"); 504 505 if (CCflag) { 506 f_print(fout, "\n#ifdef __cplusplus\n"); 507 f_print(fout, "extern \"C\" {\n"); 508 f_print(fout, "#endif\n"); 509 } 510 511 if (!Cflag) { 512 xdrfuncp = xdrfunc_head; 513 while (xdrfuncp != NULL) { 514 print_xdr_func_def(xdrfuncp->name, 515 xdrfuncp->pointerp, 2); 516 xdrfuncp = xdrfuncp->next; 517 } 518 } else { 519 for (i = 1; i < 3; i++) { 520 if (i == 1) 521 f_print(fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); 522 else 523 f_print(fout, "\n#else /* K&R C */\n"); 524 525 xdrfuncp = xdrfunc_head; 526 while (xdrfuncp != NULL) { 527 print_xdr_func_def(xdrfuncp->name, 528 xdrfuncp->pointerp, i); 529 xdrfuncp = xdrfuncp->next; 530 } 531 } 532 f_print(fout, "\n#endif /* K&R C */\n"); 533 } 534 } 535 536 if (extend && tell == ftell(fout)) 537 unlink(outfilename); 538 else if (tblflag) 539 f_print(fout, rpcgen_table_dcl); 540 541 if (Cflag) { 542 f_print(fout, "\n#ifdef __cplusplus\n"); 543 f_print(fout, "}\n"); 544 f_print(fout, "#endif\n"); 545 } 546 547 f_print(fout, "\n#endif /* !_%s */\n", guard); 548 } 549 550 /* 551 * Compile into an RPC service 552 */ 553 static void 554 s_output(int argc, char **argv, char *infile, char *define, int extend, 555 char *outfile, int nomain, int netflag) 556 { 557 char *include; 558 definition *def; 559 int foundprogram = 0; 560 char *outfilename; 561 562 open_input(infile, define); 563 outfilename = extend ? extendfile(infile, outfile) : outfile; 564 open_output(infile, outfilename); 565 add_warning(); 566 if (infile && (include = extendfile(infile, ".h"))) { 567 f_print(fout, "#include \"%s\"\n", include); 568 free(include); 569 } else 570 f_print(fout, "#include <rpc/rpc.h>\n"); 571 572 f_print(fout, "#include <stdio.h>\n"); 573 f_print(fout, "#include <stdlib.h> /* getenv, exit */\n"); 574 if (Cflag) { 575 f_print(fout, 576 "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n"); 577 f_print(fout, "#include <string.h> /* strcmp */\n"); 578 } 579 if (strcmp(svcclosetime, "-1") == 0) 580 indefinitewait = 1; 581 else if (strcmp(svcclosetime, "0") == 0) 582 exitnow = 1; 583 else if (inetdflag || pmflag) { 584 f_print(fout, "#include <signal.h>\n"); 585 timerflag = 1; 586 } 587 588 if (!tirpcflag && inetdflag) 589 f_print(fout, "#include <sys/ttycom.h> /* TIOCNOTTY */\n"); 590 if (Cflag && (inetdflag || pmflag)) { 591 f_print(fout, "#ifdef __cplusplus\n"); 592 f_print(fout, 593 "#include <sysent.h> /* getdtablesize, open */\n"); 594 f_print(fout, "#endif /* __cplusplus */\n"); 595 if (tirpcflag) 596 f_print(fout, "#include <unistd.h> /* setsid */\n"); 597 } 598 if (tirpcflag) 599 f_print(fout, "#include <sys/types.h>\n"); 600 601 f_print(fout, "#include <memory.h>\n"); 602 if (tirpcflag) 603 f_print(fout, "#include <stropts.h>\n"); 604 if (inetdflag || !tirpcflag) { 605 f_print(fout, "#include <sys/socket.h>\n"); 606 f_print(fout, "#include <netinet/in.h>\n"); 607 } 608 609 if ((netflag || pmflag) && tirpcflag && !nomain) 610 f_print(fout, "#include <netconfig.h>\n"); 611 if (tirpcflag) 612 f_print(fout, "#include <sys/resource.h> /* rlimit */\n"); 613 if (logflag || inetdflag || pmflag) 614 f_print(fout, "#include <syslog.h>\n"); 615 616 /* for ANSI-C */ 617 if (Cflag) 618 f_print(fout, 619 "\n#ifndef SIG_PF\n#define SIG_PF void(*)\ 620 (int)\n#endif\n"); 621 622 f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n"); 623 if (timerflag) 624 f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", 625 svcclosetime); 626 while ((def = get_definition()) != 0) 627 foundprogram |= (def->def_kind == DEF_PROGRAM); 628 if (extend && !foundprogram) { 629 unlink(outfilename); 630 return; 631 } 632 write_most(infile, netflag, nomain); 633 if (!nomain) { 634 if (!do_registers(argc, argv)) { 635 if (outfilename) 636 unlink(outfilename); 637 usage(); 638 } 639 write_rest(); 640 } 641 } 642 643 /* 644 * generate client side stubs 645 */ 646 static void 647 l_output(char *infile, char *define, int extend, char *outfile) 648 { 649 char *include; 650 definition *def; 651 int foundprogram = 0; 652 char *outfilename; 653 654 open_input(infile, define); 655 outfilename = extend ? extendfile(infile, outfile) : outfile; 656 open_output(infile, outfilename); 657 add_warning(); 658 if (Cflag) 659 f_print (fout, "#include <memory.h> /* for memset */\n"); 660 if (infile && (include = extendfile(infile, ".h"))) { 661 f_print(fout, "#include \"%s\"\n", include); 662 free(include); 663 } else 664 f_print(fout, "#include <rpc/rpc.h>\n"); 665 while ((def = get_definition()) != 0) 666 foundprogram |= (def->def_kind == DEF_PROGRAM); 667 if (extend && !foundprogram) 668 unlink(outfilename); 669 else 670 write_stubs(); 671 } 672 673 /* 674 * generate the dispatch table 675 */ 676 static void 677 t_output(char *infile, char *define, int extend, char *outfile) 678 { 679 definition *def; 680 int foundprogram = 0; 681 char *outfilename; 682 683 open_input(infile, define); 684 outfilename = extend ? extendfile(infile, outfile) : outfile; 685 open_output(infile, outfilename); 686 add_warning(); 687 while ((def = get_definition()) != 0) 688 foundprogram |= (def->def_kind == DEF_PROGRAM); 689 if (extend && !foundprogram) 690 unlink(outfilename); 691 else 692 write_tables(); 693 } 694 695 /* sample routine for the server template */ 696 static void 697 svc_output(char *infile, char *define, int extend, char *outfile) 698 { 699 definition *def; 700 char *include; 701 char *outfilename; 702 long tell; 703 open_input(infile, define); 704 outfilename = extend ? extendfile(infile, outfile) : outfile; 705 checkfiles(infile, outfilename); 706 /* 707 * Check if outfile already exists. 708 * if so, print an error message and exit 709 */ 710 open_output(infile, outfilename); 711 add_sample_msg(); 712 713 if (infile && (include = extendfile(infile, ".h"))) { 714 f_print(fout, "#include \"%s\"\n", include); 715 free(include); 716 } else 717 f_print(fout, "#include <rpc/rpc.h>\n"); 718 719 tell = ftell(fout); 720 while ((def = get_definition()) != 0) 721 write_sample_svc(def); 722 if (extend && tell == ftell(fout)) 723 unlink(outfilename); 724 } 725 726 /* sample main routine for client */ 727 static void 728 clnt_output(char *infile, char *define, int extend, char *outfile) 729 { 730 definition *def; 731 char *include; 732 char *outfilename; 733 long tell; 734 int has_program = 0; 735 736 open_input(infile, define); 737 outfilename = extend ? extendfile(infile, outfile) : outfile; 738 checkfiles(infile, outfilename); 739 /* 740 * Check if outfile already exists. 741 * if so, print an error message and exit 742 */ 743 744 open_output(infile, outfilename); 745 add_sample_msg(); 746 if (infile && (include = extendfile(infile, ".h"))) { 747 f_print(fout, "#include \"%s\"\n", include); 748 free(include); 749 } else 750 f_print(fout, "#include <rpc/rpc.h>\n"); 751 tell = ftell(fout); 752 while ((def = get_definition()) != 0) 753 has_program += write_sample_clnt(def); 754 755 if (has_program) 756 write_sample_clnt_main(); 757 758 if (extend && tell == ftell(fout)) 759 unlink(outfilename); 760 } 761 762 763 static void mkfile_output(cmd) 764 struct commandline *cmd; 765 { 766 char *mkfilename, *clientname, *clntname, *xdrname, *hdrname; 767 char *servername, *svcname, *servprogname, *clntprogname; 768 char *temp; 769 770 svcname = file_name(cmd->infile, "_svc.c"); 771 clntname = file_name(cmd->infile, "_clnt.c"); 772 xdrname = file_name(cmd->infile, "_xdr.c"); 773 hdrname = file_name(cmd->infile, ".h"); 774 775 if (allfiles) { 776 servername = extendfile(cmd->infile, "_server.c"); 777 clientname = extendfile(cmd->infile, "_client.c"); 778 } else { 779 servername = " "; 780 clientname = " "; 781 } 782 servprogname = extendfile(cmd->infile, "_server"); 783 clntprogname = extendfile(cmd->infile, "_client"); 784 785 if (allfiles) { 786 mkfilename = alloc(strlen("makefile.") + 787 strlen(cmd->infile) + 1); 788 temp = strrchr(cmd->infile, '.'); 789 strcat(mkfilename, "makefile."); 790 strncat(mkfilename, cmd->infile, (temp - cmd->infile)); 791 } else 792 mkfilename = cmd->outfile; 793 794 checkfiles(NULL, mkfilename); 795 open_output(NULL, mkfilename); 796 797 f_print(fout, "\n# This is a template makefile generated " 798 "by rpcgen \n"); 799 800 f_print(fout, "\n# Parameters \n\n"); 801 802 f_print(fout, "CLIENT = %s\nSERVER = %s\n\n", 803 clntprogname, servprogname); 804 f_print(fout, "SOURCES_CLNT.c = \nSOURCES_CLNT.h = \n"); 805 f_print(fout, "SOURCES_SVC.c = \nSOURCES_SVC.h = \n"); 806 f_print(fout, "SOURCES.x = %s\n\n", cmd->infile); 807 f_print(fout, "TARGETS_SVC.c = %s %s %s \n", 808 svcname, servername, xdrname); 809 f_print(fout, "TARGETS_CLNT.c = %s %s %s \n", 810 clntname, clientname, xdrname); 811 f_print(fout, "TARGETS = %s %s %s %s %s %s\n\n", 812 hdrname, xdrname, clntname, 813 svcname, clientname, servername); 814 815 f_print(fout, "OBJECTS_CLNT = $(SOURCES_CLNT.c:%%.c=%%.o) " 816 "$(TARGETS_CLNT.c:%%.c=%%.o) "); 817 818 f_print(fout, "\nOBJECTS_SVC = $(SOURCES_SVC.c:%%.c=%%.o) " 819 "$(TARGETS_SVC.c:%%.c=%%.o) "); 820 821 822 f_print(fout, "\n# Compiler flags \n"); 823 if (mtflag) 824 f_print(fout, "\nCPPFLAGS += -D_REENTRANT\n" 825 "CFLAGS += -g \nLDLIBS += -lnsl -lthread\n"); 826 else 827 f_print(fout, "\nCFLAGS += -g \nLDLIBS +=\n"); 828 f_print(fout, "RPCGENFLAGS = \n"); 829 830 f_print(fout, "\n# Targets \n\n"); 831 832 f_print(fout, "all : $(CLIENT) $(SERVER)\n\n"); 833 f_print(fout, "$(TARGETS) : $(SOURCES.x) \n"); 834 f_print(fout, "\trpcgen $(RPCGENFLAGS) $(SOURCES.x)\n\n"); 835 f_print(fout, "$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) " 836 "$(TARGETS_CLNT.c) \n\n"); 837 838 f_print(fout, "$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) " 839 "$(TARGETS_SVC.c) \n\n"); 840 f_print(fout, "$(CLIENT) : $(OBJECTS_CLNT) \n"); 841 f_print(fout, "\t$(CC) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS) \n\n"); 842 f_print(fout, "$(SERVER) : $(OBJECTS_SVC) \n"); 843 f_print(fout, "\t$(CC) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n "); 844 f_print(fout, "clean:\n\t $(RM) -f core $(TARGETS) $(OBJECTS_CLNT) " 845 "$(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n"); 846 } 847 848 849 850 /* 851 * Perform registrations for service output 852 * Return 0 if failed; 1 otherwise. 853 */ 854 static int 855 do_registers(int argc, char **argv) 856 { 857 int i; 858 859 if (inetdflag || !tirpcflag) { 860 for (i = 1; i < argc; i++) { 861 if (streq(argv[i], "-s")) { 862 if (!check_nettype(argv[i + 1], 863 valid_i_nettypes)) 864 return(0); 865 write_inetd_register(argv[i + 1]); 866 i++; 867 } 868 } 869 } else { 870 for (i = 1; i < argc; i++) 871 if (streq(argv[i], "-s")) { 872 if (!check_nettype(argv[i + 1], 873 valid_ti_nettypes)) 874 return(0); 875 write_nettype_register(argv[i + 1]); 876 i++; 877 } else if (streq(argv[i], "-n")) { 878 write_netid_register(argv[i + 1]); 879 i++; 880 } 881 } 882 return(1); 883 } 884 885 /* 886 * Add another argument to the arg list 887 */ 888 static void 889 addarg(char *cp) 890 { 891 if (argcount >= ARGLISTLEN) { 892 warnx("too many defines"); 893 crash(); 894 /*NOTREACHED*/ 895 } 896 arglist[argcount++] = cp; 897 898 } 899 900 static void 901 putarg(where, cp) 902 char *cp; 903 int where; 904 { 905 if (where >= ARGLISTLEN) { 906 warnx("arglist coding error"); 907 crash(); 908 /*NOTREACHED*/ 909 } 910 arglist[where] = cp; 911 } 912 913 /* 914 * if input file is stdin and an output file is specified then complain 915 * if the file already exists. Otherwise the file may get overwritten 916 * If input file does not exist, exit with an error 917 */ 918 919 static void 920 checkfiles(char *infile, char *outfile) 921 { 922 struct stat buf; 923 924 if (infile != NULL && stat(infile, &buf) < 0) { 925 warn("%s", infile); 926 crash(); 927 } 928 if (outfile) { 929 if (stat(outfile, &buf) < 0) 930 return; /* file does not exist */ 931 else { 932 warnx("file '%s' already exists and may be overwritten", outfile); 933 crash(); 934 } 935 } 936 } 937 938 /* 939 * Parse command line arguments 940 */ 941 static int 942 parseargs(int argc, char **argv,struct commandline *cmd) 943 { 944 int i; 945 int j; 946 char c, ch; 947 char flag[(1 << 8 * sizeof (char))]; 948 int nflags; 949 950 cmd->infile = cmd->outfile = NULL; 951 if (argc < 2) 952 return(0); 953 954 allfiles = 0; 955 flag['c'] = 0; 956 flag['h'] = 0; 957 flag['l'] = 0; 958 flag['m'] = 0; 959 flag['o'] = 0; 960 flag['s'] = 0; 961 flag['n'] = 0; 962 flag['t'] = 0; 963 flag['S'] = 0; 964 flag['C'] = 0; 965 flag['M'] = 0; 966 967 for (i = 1; i < argc; i++) { 968 if (argv[i][0] != '-') { 969 if (cmd->infile) { 970 warnx("cannot specify more than one input file"); 971 return(0); 972 } 973 cmd->infile = argv[i]; 974 } else { 975 for (j = 1; argv[i][j] != 0; j++) { 976 c = argv[i][j]; 977 switch (c) { 978 case 'a': 979 allfiles = 1; 980 break; 981 case 'c': 982 case 'h': 983 case 'l': 984 case 'm': 985 case 't': 986 if (flag[(int)c]) 987 return(0); 988 flag[(int)c] = 1; 989 break; 990 case 'S': 991 /* 992 * sample flag: Ss or Sc. 993 * Ss means set flag['S']; 994 * Sc means set flag['C']; 995 * Sm means set flag['M']; 996 */ 997 ch = argv[i][++j]; /* get next char */ 998 if (ch == 's') 999 ch = 'S'; 1000 else if (ch == 'c') 1001 ch = 'C'; 1002 else if (ch == 'm') 1003 ch = 'M'; 1004 else 1005 return(0); 1006 1007 if (flag[(int)ch]) 1008 return(0); 1009 flag[(int)ch] = 1; 1010 break; 1011 case 'C': /* ANSI C syntax */ 1012 Cflag = 1; 1013 ch = argv[i][j+1]; /* get next char */ 1014 1015 if (ch != 'C') 1016 break; 1017 CCflag = 1; 1018 break; 1019 case 'b': 1020 tirpcflag = 1; 1021 break; 1022 1023 case 'I': 1024 inetdflag = 1; 1025 break; 1026 case 'N': 1027 newstyle = 1; 1028 break; 1029 case 'L': 1030 logflag = 1; 1031 break; 1032 case 'K': 1033 if (++i == argc) 1034 return(0); 1035 svcclosetime = argv[i]; 1036 goto nextarg; 1037 case 'T': 1038 tblflag = 1; 1039 break; 1040 case 'M': 1041 mtflag = 1; 1042 break; 1043 case 'i' : 1044 if (++i == argc) 1045 return(0); 1046 rpcgen_inline = atoi(argv[i]); 1047 goto nextarg; 1048 case 'n': 1049 case 'o': 1050 case 's': 1051 if (argv[i][j - 1] != '-' || 1052 argv[i][j + 1] != 0) 1053 return(0); 1054 flag[(int)c] = 1; 1055 if (++i == argc) 1056 return(0); 1057 if (c == 'o') { 1058 if (cmd->outfile) 1059 return(0); 1060 cmd->outfile = argv[i]; 1061 } 1062 goto nextarg; 1063 case 'D': 1064 if (argv[i][j - 1] != '-') 1065 return(0); 1066 addarg(argv[i]); 1067 goto nextarg; 1068 case 'Y': 1069 if (++i == argc) 1070 return(0); 1071 strcpy(pathbuf, argv[i]); 1072 strcat(pathbuf, "/cpp"); 1073 CPP = pathbuf; 1074 cppDefined = 1; 1075 goto nextarg; 1076 1077 default: 1078 return(0); 1079 } 1080 } 1081 nextarg: 1082 ; 1083 } 1084 } 1085 1086 cmd->cflag = flag['c']; 1087 cmd->hflag = flag['h']; 1088 cmd->lflag = flag['l']; 1089 cmd->mflag = flag['m']; 1090 cmd->nflag = flag['n']; 1091 cmd->sflag = flag['s']; 1092 cmd->tflag = flag['t']; 1093 cmd->Ssflag = flag['S']; 1094 cmd->Scflag = flag['C']; 1095 cmd->makefileflag = flag['M']; 1096 1097 if (tirpcflag) { 1098 pmflag = inetdflag ? 0 : 1; 1099 /* pmflag or inetdflag is always TRUE */ 1100 if ((inetdflag && cmd->nflag)) { 1101 /* netid not allowed with inetdflag */ 1102 warnx("cannot use netid flag with inetd flag"); 1103 return(0); 1104 } 1105 } else { /* 4.1 mode */ 1106 pmflag = 0; /* set pmflag only in tirpcmode */ 1107 if (cmd->nflag) { /* netid needs TIRPC */ 1108 warnx("cannot use netid flag without TIRPC"); 1109 return(0); 1110 } 1111 } 1112 1113 if (newstyle && (tblflag || cmd->tflag)) { 1114 warnx("cannot use table flags with newstyle"); 1115 return(0); 1116 } 1117 1118 /* check no conflicts with file generation flags */ 1119 nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag + 1120 cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + 1121 cmd->Scflag + cmd->makefileflag; 1122 1123 if (nflags == 0) { 1124 if (cmd->outfile != NULL || cmd->infile == NULL) 1125 return(0); 1126 } else if (cmd->infile == NULL && 1127 (cmd->Ssflag || cmd->Scflag || cmd->makefileflag)) { 1128 warnx("\"infile\" is required for template generation flags"); 1129 return(0); 1130 } if (nflags > 1) { 1131 warnx("cannot have more than one file generation flag"); 1132 return(0); 1133 } 1134 return(1); 1135 } 1136 1137 static void 1138 usage(void) 1139 { 1140 f_print(stderr, "%s\n%s\n%s\n%s\n%s\n", 1141 "usage: rpcgen infile", 1142 " rpcgen [-abCLNTM] [-Dname[=value]] [-i size]" 1143 "[-I [-K seconds]] [-Y path] infile", 1144 " rpcgen [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm]" 1145 "[-o outfile] [infile]", 1146 " rpcgen [-s nettype]* [-o outfile] [infile]", 1147 " rpcgen [-n netid]* [-o outfile] [infile]"); 1148 options_usage(); 1149 exit(1); 1150 } 1151 1152 static void 1153 options_usage(void) 1154 { 1155 f_print(stderr, "options:\n"); 1156 f_print(stderr, "-a\t\tgenerate all files, including samples\n"); 1157 f_print(stderr, "-b\t\tbackward compatibility mode (generates code" 1158 "for SunOS 4.X)\n"); 1159 f_print(stderr, "-c\t\tgenerate XDR routines\n"); 1160 f_print(stderr, "-C\t\tANSI C mode\n"); 1161 f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n"); 1162 f_print(stderr, "-h\t\tgenerate header file\n"); 1163 f_print(stderr, "-i size\t\tsize at which to start generating" 1164 "inline code\n"); 1165 f_print(stderr, "-I\t\tgenerate code for inetd support in server" 1166 "(for SunOS 4.X)\n"); 1167 f_print(stderr, "-K seconds\tserver exits after K seconds of" 1168 "inactivity\n"); 1169 f_print(stderr, "-l\t\tgenerate client side stubs\n"); 1170 f_print(stderr, "-L\t\tserver errors will be printed to syslog\n"); 1171 f_print(stderr, "-m\t\tgenerate server side stubs\n"); 1172 f_print(stderr, "-M\t\tgenerate MT-safe code\n"); 1173 f_print(stderr, "-n netid\tgenerate server code that supports" 1174 "named netid\n"); 1175 f_print(stderr, "-N\t\tsupports multiple arguments and" 1176 "call-by-value\n"); 1177 f_print(stderr, "-o outfile\tname of the output file\n"); 1178 f_print(stderr, "-s nettype\tgenerate server code that supports named" 1179 "nettype\n"); 1180 f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote" 1181 "procedures\n"); 1182 f_print(stderr, "-Ss\t\tgenerate sample server code that defines" 1183 "remote procedures\n"); 1184 f_print(stderr, "-Sm \t\tgenerate makefile template \n"); 1185 1186 f_print(stderr, "-t\t\tgenerate RPC dispatch table\n"); 1187 f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n"); 1188 f_print(stderr, "-Y path\t\tpath where cpp is found\n"); 1189 exit(1); 1190 } 1191