]>
Commit | Line | Data |
---|---|---|
28f540f4 | 1 | /* |
a7ab6ec8 | 2 | * From @(#)rpc_main.c 1.30 89/03/30 |
cb636bb2 | 3 | * |
a7ab6ec8 UD |
4 | * Copyright (c) 2010, Oracle America, Inc. |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions are | |
7 | * met: | |
cbd3dceb | 8 | * |
a7ab6ec8 UD |
9 | * * Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | |
11 | * * Redistributions in binary form must reproduce the above | |
12 | * copyright notice, this list of conditions and the following | |
13 | * disclaimer in the documentation and/or other materials | |
14 | * provided with the distribution. | |
15 | * * Neither the name of the "Oracle America, Inc." nor the names of its | |
16 | * contributors may be used to endorse or promote products derived | |
17 | * from this software without specific prior written permission. | |
cbd3dceb | 18 | * |
a7ab6ec8 UD |
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
22 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
23 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
24 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |
26 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
0d204b0a | 31 | */ |
28f540f4 RM |
32 | |
33 | /* | |
cbd3dceb | 34 | * rpc_main.c, Top level of the RPC protocol compiler. |
28f540f4 RM |
35 | */ |
36 | ||
9756dfe1 | 37 | #include <errno.h> |
28f540f4 | 38 | #include <stdio.h> |
0d204b0a UD |
39 | #include <string.h> |
40 | #include <unistd.h> | |
4360eafd | 41 | #include <libintl.h> |
0d204b0a UD |
42 | #include <ctype.h> |
43 | #include <sys/types.h> | |
44 | #include <sys/param.h> | |
28f540f4 | 45 | #include <sys/file.h> |
0d204b0a | 46 | #include <sys/stat.h> |
0dee6738 | 47 | #include <sys/wait.h> |
28f540f4 | 48 | #include "rpc_parse.h" |
0d204b0a | 49 | #include "rpc_util.h" |
28f540f4 | 50 | #include "rpc_scan.h" |
0d204b0a UD |
51 | #include "proto.h" |
52 | ||
cbbcaf23 UD |
53 | #include "../version.h" |
54 | #define PACKAGE _libc_intl_domainname | |
55 | ||
28f540f4 | 56 | #define EXTEND 1 /* alias for TRUE */ |
880f421f UD |
57 | #define DONT_EXTEND 0 /* alias for FALSE */ |
58 | ||
59 | struct commandline | |
60 | { | |
61 | int cflag; /* xdr C routines */ | |
62 | int hflag; /* header file */ | |
63 | int lflag; /* client side stubs */ | |
64 | int mflag; /* server side stubs */ | |
65 | int nflag; /* netid flag */ | |
66 | int sflag; /* server stubs for the given transport */ | |
67 | int tflag; /* dispatch Table file */ | |
68 | int Ssflag; /* produce server sample code */ | |
69 | int Scflag; /* produce client sample code */ | |
70 | int makefileflag; /* Generate a template Makefile */ | |
71 | const char *infile; /* input module name */ | |
72 | const char *outfile; /* output module name */ | |
73 | }; | |
28f540f4 | 74 | |
0d204b0a UD |
75 | |
76 | static const char *cmdname; | |
77 | ||
880f421f UD |
78 | #define SVR4_CPP "/usr/ccs/lib/cpp" |
79 | #define SUNOS_CPP "/lib/cpp" | |
80 | ||
0d204b0a | 81 | static const char *svcclosetime = "120"; |
5f73e771 | 82 | static int cppDefined; /* explicit path for C preprocessor */ |
880f421f | 83 | static const char *CPP = SUNOS_CPP; |
5f73e771 | 84 | static const char CPPFLAGS[] = "-C"; |
9756dfe1 | 85 | static char *pathbuf; |
0dee6738 | 86 | static int cpp_pid; |
880f421f UD |
87 | static const char *allv[] = |
88 | { | |
be18eced | 89 | "rpcgen", "-s", "udp", "-s", "tcp" |
28f540f4 | 90 | }; |
880f421f UD |
91 | static int allc = sizeof (allv) / sizeof (allv[0]); |
92 | static const char *allnv[] = | |
93 | { | |
94 | "rpcgen", "-s", "netpath", | |
0d204b0a | 95 | }; |
880f421f | 96 | static int allnc = sizeof (allnv) / sizeof (allnv[0]); |
0d204b0a UD |
97 | |
98 | /* | |
99 | * machinations for handling expanding argument list | |
100 | */ | |
880f421f UD |
101 | static void addarg (const char *); /* add another argument to the list */ |
102 | static void putarg (int, const char *); /* put argument at specified location */ | |
103 | static void clear_args (void); /* clear argument list */ | |
104 | static void checkfiles (const char *, const char *); | |
105 | /* check if out file already exists */ | |
106 | ||
107 | static void clear_args (void); | |
108 | static char *extendfile (const char *file, const char *ext); | |
109 | static void open_output (const char *infile, const char *outfile); | |
110 | static void add_warning (void); | |
111 | static void clear_args (void); | |
112 | static void find_cpp (void); | |
113 | static void open_input (const char *infile, const char *define); | |
114 | static int check_nettype (const char *name, const char *list_to_check[]); | |
115 | static void c_output (const char *infile, const char *define, | |
116 | int extend, const char *outfile); | |
117 | static void h_output (const char *infile, const char *define, | |
118 | int extend, const char *outfile); | |
119 | static void s_output (int argc, const char *argv[], const char *infile, | |
120 | const char *define, int extend, | |
121 | const char *outfile, int nomain, int netflag); | |
122 | static void l_output (const char *infile, const char *define, | |
123 | int extend, const char *outfile); | |
124 | static void t_output (const char *infile, const char *define, | |
125 | int extend, const char *outfile); | |
126 | static void svc_output (const char *infile, const char *define, | |
0d204b0a | 127 | int extend, const char *outfile); |
880f421f UD |
128 | static void clnt_output (const char *infile, const char *define, |
129 | int extend, const char *outfile); | |
130 | static void mkfile_output (struct commandline *cmd); | |
131 | static int do_registers (int argc, const char *argv[]); | |
132 | static void addarg (const char *cp); | |
133 | static void putarg (int whereto, const char *cp); | |
134 | static void checkfiles (const char *infile, const char *outfile); | |
135 | static int parseargs (int argc, const char *argv[], struct commandline *cmd); | |
cbbcaf23 UD |
136 | static void usage (FILE *stream, int status) __attribute__ ((noreturn)); |
137 | static void options_usage (FILE *stream, int status) __attribute__ ((noreturn)); | |
138 | static void print_version (void); | |
880f421f UD |
139 | static void c_initialize (void); |
140 | static char *generate_guard (const char *pathname); | |
0d204b0a UD |
141 | |
142 | ||
143 | #define ARGLISTLEN 20 | |
144 | #define FIXEDARGS 2 | |
145 | ||
146 | static const char *arglist[ARGLISTLEN]; | |
147 | static int argcount = FIXEDARGS; | |
148 | ||
149 | ||
880f421f UD |
150 | int nonfatalerrors; /* errors */ |
151 | int inetdflag /* = 1 */ ; /* Support for inetd *//* is now the default */ | |
152 | int pmflag; /* Support for port monitors */ | |
153 | int logflag; /* Use syslog instead of fprintf for errors */ | |
154 | int tblflag; /* Support for dispatch table file */ | |
155 | int mtflag; /* Support for MT */ | |
28f540f4 | 156 | |
0d204b0a UD |
157 | #define INLINE 3 |
158 | /*length at which to start doing an inline */ | |
28f540f4 | 159 | |
880f421f UD |
160 | int inlineflag = INLINE; /* length at which to start doing an inline. 3 = default |
161 | if 0, no xdr_inline code */ | |
0d204b0a | 162 | |
880f421f UD |
163 | int indefinitewait; /* If started by port monitors, hang till it wants */ |
164 | int exitnow; /* If started by port monitors, exit after the call */ | |
165 | int timerflag; /* TRUE if !indefinite && !exitnow */ | |
166 | int newstyle; /* newstyle of passing arguments (by value) */ | |
880f421f | 167 | int Cflag = 1; /* ANSI C syntax */ |
5f73e771 | 168 | int CCflag; /* C++ files */ |
880f421f | 169 | static int allfiles; /* generate all files */ |
5f73e771 | 170 | int tirpcflag; /* generating code for tirpc, by default */ |
5f73e771 UD |
171 | xdrfunc *xdrfunc_head; /* xdr function list */ |
172 | xdrfunc *xdrfunc_tail; /* xdr function list */ | |
9756dfe1 | 173 | |
0d204b0a | 174 | int |
880f421f | 175 | main (int argc, const char *argv[]) |
28f540f4 | 176 | { |
880f421f | 177 | struct commandline cmd; |
28f540f4 | 178 | |
880f421f UD |
179 | (void) memset ((char *) &cmd, 0, sizeof (struct commandline)); |
180 | clear_args (); | |
181 | if (!parseargs (argc, argv, &cmd)) | |
cbbcaf23 | 182 | usage (stderr, 1); |
c475b8f5 | 183 | |
880f421f UD |
184 | if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag || |
185 | cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) | |
186 | { | |
187 | checkfiles (cmd.infile, cmd.outfile); | |
188 | } | |
189 | else | |
190 | checkfiles (cmd.infile, NULL); | |
191 | ||
192 | if (cmd.cflag) | |
193 | c_output (cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); | |
194 | else if (cmd.hflag) | |
195 | h_output (cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); | |
196 | else if (cmd.lflag) | |
197 | l_output (cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile); | |
198 | else if (cmd.sflag || cmd.mflag || (cmd.nflag)) | |
199 | s_output (argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND, | |
200 | cmd.outfile, cmd.mflag, cmd.nflag); | |
201 | else if (cmd.tflag) | |
202 | t_output (cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile); | |
203 | else if (cmd.Ssflag) | |
204 | svc_output (cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile); | |
205 | else if (cmd.Scflag) | |
206 | clnt_output (cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile); | |
207 | else if (cmd.makefileflag) | |
208 | mkfile_output (&cmd); | |
209 | else | |
210 | { | |
211 | /* the rescans are required, since cpp may effect input */ | |
212 | c_output (cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c"); | |
213 | reinitialize (); | |
214 | h_output (cmd.infile, "-DRPC_HDR", EXTEND, ".h"); | |
215 | reinitialize (); | |
216 | l_output (cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c"); | |
217 | reinitialize (); | |
218 | if (inetdflag || !tirpcflag) | |
219 | s_output (allc, allv, cmd.infile, "-DRPC_SVC", EXTEND, | |
220 | "_svc.c", cmd.mflag, cmd.nflag); | |
221 | else | |
222 | s_output (allnc, allnv, cmd.infile, "-DRPC_SVC", | |
223 | EXTEND, "_svc.c", cmd.mflag, cmd.nflag); | |
224 | if (tblflag) | |
225 | { | |
226 | reinitialize (); | |
227 | t_output (cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i"); | |
28f540f4 | 228 | } |
880f421f UD |
229 | if (allfiles) |
230 | { | |
231 | reinitialize (); | |
232 | svc_output (cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c"); | |
233 | reinitialize (); | |
234 | clnt_output (cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c"); | |
28f540f4 | 235 | } |
880f421f UD |
236 | if (allfiles || (cmd.makefileflag == 1)) |
237 | { | |
238 | reinitialize (); | |
239 | mkfile_output (&cmd); | |
240 | } | |
241 | } | |
ce460d04 RM |
242 | |
243 | return nonfatalerrors; | |
28f540f4 RM |
244 | } |
245 | ||
246 | /* | |
cbd3dceb | 247 | * add extension to filename |
28f540f4 RM |
248 | */ |
249 | static char * | |
880f421f | 250 | extendfile (const char *file, const char *ext) |
28f540f4 | 251 | { |
880f421f UD |
252 | char *res; |
253 | const char *p; | |
254 | ||
255 | res = alloc (strlen (file) + strlen (ext) + 1); | |
256 | if (res == NULL) | |
257 | abort (); | |
258 | p = strrchr (file, '.'); | |
259 | if (p == NULL) | |
260 | p = file + strlen (file); | |
261 | strcpy (res, file); | |
262 | strcpy (res + (p - file), ext); | |
263 | return res; | |
28f540f4 RM |
264 | } |
265 | ||
266 | /* | |
cbd3dceb | 267 | * Open output file with given extension |
28f540f4 | 268 | */ |
0d204b0a | 269 | static void |
880f421f | 270 | open_output (const char *infile, const char *outfile) |
28f540f4 | 271 | { |
880f421f UD |
272 | if (outfile == NULL) |
273 | { | |
274 | fout = stdout; | |
275 | return; | |
276 | } | |
0d204b0a | 277 | |
880f421f UD |
278 | if (infile != NULL && streq (outfile, infile)) |
279 | { | |
280 | fprintf (stderr, _ ("%s: output would overwrite %s\n"), cmdname, | |
281 | infile); | |
282 | crash (); | |
283 | } | |
284 | fout = fopen (outfile, "w"); | |
285 | if (fout == NULL) | |
286 | { | |
d74e76f9 | 287 | fprintf (stderr, _ ("%s: unable to open %s: %m\n"), cmdname, outfile); |
880f421f UD |
288 | crash (); |
289 | } | |
290 | record_open (outfile); | |
0d204b0a UD |
291 | } |
292 | ||
0dee6738 UD |
293 | /* Close the output file and check for write errors. */ |
294 | static void | |
295 | close_output (const char *outfile) | |
296 | { | |
297 | if (fclose (fout) == EOF) | |
298 | { | |
d74e76f9 UD |
299 | fprintf (stderr, _("%s: while writing output %s: %m"), cmdname, |
300 | outfile ?: "<stdout>"); | |
0dee6738 UD |
301 | crash (); |
302 | } | |
303 | } | |
304 | ||
0d204b0a | 305 | static void |
880f421f | 306 | add_warning (void) |
0d204b0a | 307 | { |
880f421f UD |
308 | fprintf (fout, "/*\n"); |
309 | fprintf (fout, " * Please do not edit this file.\n"); | |
310 | fprintf (fout, " * It was generated using rpcgen.\n"); | |
311 | fprintf (fout, " */\n\n"); | |
0d204b0a UD |
312 | } |
313 | ||
314 | /* clear list of arguments */ | |
880f421f UD |
315 | static void |
316 | clear_args (void) | |
0d204b0a UD |
317 | { |
318 | int i; | |
880f421f | 319 | for (i = FIXEDARGS; i < ARGLISTLEN; ++i) |
0d204b0a UD |
320 | arglist[i] = NULL; |
321 | argcount = FIXEDARGS; | |
322 | } | |
323 | ||
324 | /* make sure that a CPP exists */ | |
880f421f UD |
325 | static void |
326 | find_cpp (void) | |
0d204b0a UD |
327 | { |
328 | struct stat buf; | |
329 | ||
880f421f UD |
330 | if (stat (CPP, &buf) < 0) |
331 | { /* /lib/cpp or explicit cpp does not exist */ | |
332 | if (cppDefined) | |
333 | { | |
334 | fprintf (stderr, _ ("cannot find C preprocessor: %s \n"), CPP); | |
335 | crash (); | |
336 | } | |
337 | else | |
338 | { /* try the other one */ | |
339 | CPP = SVR4_CPP; | |
340 | if (stat (CPP, &buf) < 0) | |
341 | { /* can't find any cpp */ | |
342 | fputs (_ ("cannot find any C preprocessor (cpp)\n"), stdout); | |
343 | crash (); | |
344 | } | |
345 | } | |
0d204b0a | 346 | } |
0d204b0a UD |
347 | } |
348 | ||
28f540f4 | 349 | /* |
cbd3dceb | 350 | * Open input file with given define for C-preprocessor |
28f540f4 | 351 | */ |
0d204b0a | 352 | static void |
880f421f | 353 | open_input (const char *infile, const char *define) |
28f540f4 | 354 | { |
880f421f UD |
355 | int pd[2]; |
356 | ||
357 | infilename = (infile == NULL) ? "<stdin>" : infile; | |
9eb2730e UD |
358 | if (pipe (pd) != 0) |
359 | { | |
360 | perror ("pipe"); | |
361 | exit (1); | |
362 | } | |
0dee6738 UD |
363 | cpp_pid = fork (); |
364 | switch (cpp_pid) | |
880f421f UD |
365 | { |
366 | case 0: | |
367 | find_cpp (); | |
368 | putarg (0, CPP); | |
369 | putarg (1, CPPFLAGS); | |
370 | addarg (define); | |
371 | if (infile) | |
372 | addarg (infile); | |
373 | addarg ((char *) NULL); | |
374 | close (1); | |
375 | dup2 (pd[1], 1); | |
376 | close (pd[0]); | |
377 | execv (arglist[0], (char **) arglist); | |
378 | perror ("execv"); | |
379 | exit (1); | |
380 | case -1: | |
381 | perror ("fork"); | |
382 | exit (1); | |
383 | } | |
384 | close (pd[1]); | |
385 | fin = fdopen (pd[0], "r"); | |
386 | if (fin == NULL) | |
387 | { | |
388 | fprintf (stderr, "%s: ", cmdname); | |
389 | perror (infilename); | |
390 | crash (); | |
391 | } | |
28f540f4 RM |
392 | } |
393 | ||
0dee6738 UD |
394 | /* Close the connection to the C-preprocessor and check for successfull |
395 | termination. */ | |
396 | static void | |
397 | close_input (void) | |
398 | { | |
399 | int status; | |
400 | ||
401 | fclose (fin); | |
402 | /* Check the termination status. */ | |
403 | if (waitpid (cpp_pid, &status, 0) < 0) | |
404 | { | |
405 | perror ("waitpid"); | |
406 | crash (); | |
407 | } | |
408 | if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0) | |
409 | { | |
410 | if (WIFSIGNALED (status)) | |
411 | fprintf (stderr, _("%s: C preprocessor failed with signal %d\n"), | |
412 | cmdname, WTERMSIG (status)); | |
413 | else | |
414 | fprintf (stderr, _("%s: C preprocessor failed with exit code %d\n"), | |
415 | cmdname, WEXITSTATUS (status)); | |
416 | crash (); | |
417 | } | |
418 | } | |
419 | ||
0d204b0a UD |
420 | /* valid tirpc nettypes */ |
421 | static const char *valid_ti_nettypes[] = | |
422 | { | |
423 | "netpath", | |
424 | "visible", | |
425 | "circuit_v", | |
426 | "datagram_v", | |
427 | "circuit_n", | |
428 | "datagram_n", | |
429 | "udp", | |
430 | "tcp", | |
431 | "raw", | |
432 | NULL | |
880f421f | 433 | }; |
0d204b0a UD |
434 | |
435 | /* valid inetd nettypes */ | |
436 | static const char *valid_i_nettypes[] = | |
437 | { | |
438 | "udp", | |
439 | "tcp", | |
440 | NULL | |
441 | }; | |
442 | ||
880f421f UD |
443 | static int |
444 | check_nettype (const char *name, const char *list_to_check[]) | |
445 | { | |
0d204b0a | 446 | int i; |
880f421f UD |
447 | for (i = 0; list_to_check[i] != NULL; i++) |
448 | { | |
449 | if (strcmp (name, list_to_check[i]) == 0) | |
450 | { | |
451 | return 1; | |
452 | } | |
453 | } | |
11bf311e | 454 | fprintf (stderr, _ ("illegal nettype: `%s'\n"), name); |
0d204b0a UD |
455 | return 0; |
456 | } | |
457 | ||
28f540f4 RM |
458 | /* |
459 | * Compile into an XDR routine output file | |
460 | */ | |
0d204b0a UD |
461 | |
462 | static void | |
880f421f UD |
463 | c_output (const char *infile, const char *define, int extend, |
464 | const char *outfile) | |
28f540f4 | 465 | { |
880f421f UD |
466 | definition *def; |
467 | char *include; | |
468 | const char *outfilename; | |
469 | long tell; | |
470 | ||
471 | c_initialize (); | |
472 | open_input (infile, define); | |
473 | outfilename = extend ? extendfile (infile, outfile) : outfile; | |
474 | open_output (infile, outfilename); | |
475 | add_warning (); | |
476 | if (infile && (include = extendfile (infile, ".h"))) | |
477 | { | |
478 | fprintf (fout, "#include \"%s\"\n", include); | |
479 | free (include); | |
480 | /* .h file already contains rpc/rpc.h */ | |
481 | } | |
482 | else | |
483 | fprintf (fout, "#include <rpc/rpc.h>\n"); | |
484 | tell = ftell (fout); | |
485 | while ((def = get_definition ()) != NULL) | |
486 | emit (def); | |
487 | ||
488 | if (extend && tell == ftell (fout)) | |
489 | unlink (outfilename); | |
0dee6738 UD |
490 | close_input (); |
491 | close_output (outfilename); | |
28f540f4 RM |
492 | } |
493 | ||
0d204b0a | 494 | void |
880f421f | 495 | c_initialize (void) |
0d204b0a UD |
496 | { |
497 | ||
498 | /* add all the starting basic types */ | |
499 | ||
880f421f UD |
500 | add_type (1, "int"); |
501 | add_type (1, "long"); | |
502 | add_type (1, "short"); | |
503 | add_type (1, "bool"); | |
0d204b0a | 504 | |
880f421f UD |
505 | add_type (1, "u_int"); |
506 | add_type (1, "u_long"); | |
507 | add_type (1, "u_short"); | |
0d204b0a UD |
508 | |
509 | } | |
510 | ||
511 | char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ | |
512 | char *(*proc)();\n\ | |
513 | xdrproc_t xdr_arg;\n\ | |
514 | unsigned len_arg;\n\ | |
515 | xdrproc_t xdr_res;\n\ | |
516 | unsigned len_res;\n\ | |
517 | };\n"; | |
518 | ||
519 | ||
880f421f UD |
520 | static char * |
521 | generate_guard (const char *pathname) | |
522 | { | |
523 | const char *filename; | |
524 | char *guard, *tmp; | |
525 | ||
526 | filename = strrchr (pathname, '/'); /* find last component */ | |
527 | filename = ((filename == NULL) ? pathname : filename + 1); | |
0292b0dd | 528 | guard = extendfile (filename, "_H_RPCGEN"); |
880f421f UD |
529 | /* convert to upper case */ |
530 | tmp = guard; | |
531 | while (*tmp) | |
532 | { | |
533 | if (islower (*tmp)) | |
534 | *tmp = toupper (*tmp); | |
535 | tmp++; | |
536 | } | |
0d204b0a | 537 | |
880f421f | 538 | return guard; |
0d204b0a UD |
539 | } |
540 | ||
28f540f4 RM |
541 | /* |
542 | * Compile into an XDR header file | |
543 | */ | |
0d204b0a UD |
544 | |
545 | ||
546 | static void | |
880f421f UD |
547 | h_output (const char *infile, const char *define, int extend, |
548 | const char *outfile) | |
28f540f4 | 549 | { |
880f421f UD |
550 | xdrfunc *xdrfuncp; |
551 | definition *def; | |
552 | const char *ifilename; | |
553 | const char *outfilename; | |
554 | long tell; | |
555 | char *guard; | |
556 | list *l; | |
0d204b0a | 557 | |
880f421f UD |
558 | open_input (infile, define); |
559 | outfilename = extend ? extendfile (infile, outfile) : outfile; | |
560 | open_output (infile, outfilename); | |
561 | add_warning (); | |
562 | ifilename = (infile == NULL) ? "STDIN" : infile; | |
563 | guard = generate_guard (outfilename ? outfilename : ifilename); | |
564 | ||
565 | fprintf (fout, "#ifndef _%s\n#define _%s\n\n", guard, | |
566 | guard); | |
567 | ||
568 | fprintf (fout, "#include <rpc/rpc.h>\n\n"); | |
569 | ||
570 | if (mtflag) | |
571 | { | |
572 | fprintf (fout, "#include <pthread.h>\n"); | |
573 | } | |
574 | ||
575 | /* put the C++ support */ | |
576 | if (Cflag && !CCflag) | |
577 | { | |
578 | fprintf (fout, "\n#ifdef __cplusplus\n"); | |
579 | fprintf (fout, "extern \"C\" {\n"); | |
580 | fprintf (fout, "#endif\n\n"); | |
581 | } | |
582 | ||
583 | tell = ftell (fout); | |
584 | /* print data definitions */ | |
585 | while ((def = get_definition ()) != NULL) | |
586 | { | |
587 | print_datadef (def); | |
588 | } | |
589 | ||
590 | /* print function declarations. | |
591 | Do this after data definitions because they might be used as | |
592 | arguments for functions */ | |
593 | for (l = defined; l != NULL; l = l->next) | |
594 | { | |
595 | print_funcdef (l->val); | |
596 | } | |
597 | /* Now print all xdr func declarations */ | |
598 | if (xdrfunc_head != NULL) | |
599 | { | |
600 | fprintf (fout, "\n/* the xdr functions */\n"); | |
601 | if (CCflag) | |
602 | { | |
603 | fprintf (fout, "\n#ifdef __cplusplus\n"); | |
604 | fprintf (fout, "extern \"C\" {\n"); | |
605 | fprintf (fout, "#endif\n"); | |
606 | } | |
607 | if (!Cflag) | |
608 | { | |
609 | xdrfuncp = xdrfunc_head; | |
610 | while (xdrfuncp != NULL) | |
611 | { | |
612 | print_xdr_func_def (xdrfuncp->name, | |
613 | xdrfuncp->pointerp, 2); | |
614 | xdrfuncp = xdrfuncp->next; | |
615 | } | |
0d204b0a | 616 | } |
880f421f UD |
617 | else |
618 | { | |
619 | int i; | |
620 | ||
621 | for (i = 1; i < 3; ++i) | |
622 | { | |
623 | if (i == 1) | |
624 | fprintf (fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); | |
625 | else | |
626 | fprintf (fout, "\n#else /* K&R C */\n"); | |
627 | ||
628 | xdrfuncp = xdrfunc_head; | |
629 | while (xdrfuncp != NULL) | |
630 | { | |
631 | print_xdr_func_def (xdrfuncp->name, | |
632 | xdrfuncp->pointerp, i); | |
633 | xdrfuncp = xdrfuncp->next; | |
634 | } | |
635 | } | |
636 | fprintf (fout, "\n#endif /* K&R C */\n"); | |
28f540f4 | 637 | } |
880f421f UD |
638 | } |
639 | ||
640 | if (extend && tell == ftell (fout)) | |
641 | { | |
642 | unlink (outfilename); | |
643 | } | |
644 | else if (tblflag) | |
645 | { | |
646 | fprintf (fout, rpcgen_table_dcl); | |
647 | } | |
648 | ||
649 | if (Cflag) | |
650 | { | |
651 | fprintf (fout, "\n#ifdef __cplusplus\n"); | |
652 | fprintf (fout, "}\n"); | |
653 | fprintf (fout, "#endif\n"); | |
654 | } | |
655 | ||
656 | fprintf (fout, "\n#endif /* !_%s */\n", guard); | |
0292b0dd | 657 | free (guard); |
0dee6738 UD |
658 | close_input (); |
659 | close_output (outfilename); | |
28f540f4 RM |
660 | } |
661 | ||
662 | /* | |
663 | * Compile into an RPC service | |
664 | */ | |
0d204b0a | 665 | static void |
880f421f UD |
666 | s_output (int argc, const char *argv[], const char *infile, const char *define, |
667 | int extend, const char *outfile, int nomain, int netflag) | |
28f540f4 | 668 | { |
880f421f UD |
669 | char *include; |
670 | definition *def; | |
671 | int foundprogram = 0; | |
672 | const char *outfilename; | |
673 | ||
674 | open_input (infile, define); | |
675 | outfilename = extend ? extendfile (infile, outfile) : outfile; | |
676 | open_output (infile, outfilename); | |
677 | add_warning (); | |
678 | if (infile && (include = extendfile (infile, ".h"))) | |
679 | { | |
680 | fprintf (fout, "#include \"%s\"\n", include); | |
681 | free (include); | |
682 | } | |
683 | else | |
684 | fprintf (fout, "#include <rpc/rpc.h>\n"); | |
685 | ||
686 | fprintf (fout, "#include <stdio.h>\n"); | |
687 | fprintf (fout, "#include <stdlib.h>\n"); | |
c7adcc24 | 688 | fprintf (fout, "#include <rpc/pmap_clnt.h>\n"); |
880f421f | 689 | if (Cflag) |
c7adcc24 | 690 | fprintf (fout, "#include <string.h>\n"); |
880f421f UD |
691 | if (strcmp (svcclosetime, "-1") == 0) |
692 | indefinitewait = 1; | |
693 | else if (strcmp (svcclosetime, "0") == 0) | |
694 | exitnow = 1; | |
695 | else if (inetdflag || pmflag) | |
696 | { | |
697 | fprintf (fout, "#include <signal.h>\n"); | |
698 | timerflag = 1; | |
699 | } | |
0d204b0a | 700 | |
880f421f | 701 | if (!tirpcflag && inetdflag) |
880f421f | 702 | fprintf (fout, "#include <sys/ioctl.h> /* ioctl, TIOCNOTTY */\n"); |
880f421f UD |
703 | if (Cflag && (inetdflag || pmflag)) |
704 | { | |
880f421f UD |
705 | fprintf (fout, "#include <sys/types.h> /* open */\n"); |
706 | fprintf (fout, "#include <sys/stat.h> /* open */\n"); | |
707 | fprintf (fout, "#include <fcntl.h> /* open */\n"); | |
708 | fprintf (fout, "#include <unistd.h> /* getdtablesize */\n"); | |
880f421f | 709 | } |
880f421f | 710 | if (tirpcflag && !(Cflag && (inetdflag || pmflag))) |
880f421f | 711 | fprintf (fout, "#include <sys/types.h>\n"); |
0d204b0a | 712 | |
880f421f | 713 | fprintf (fout, "#include <memory.h>\n"); |
880f421f UD |
714 | if (inetdflag || !tirpcflag) |
715 | { | |
716 | fprintf (fout, "#include <sys/socket.h>\n"); | |
717 | fprintf (fout, "#include <netinet/in.h>\n"); | |
718 | } | |
0d204b0a | 719 | |
880f421f UD |
720 | if ((netflag || pmflag) && tirpcflag && !nomain) |
721 | { | |
722 | fprintf (fout, "#include <netconfig.h>\n"); | |
723 | } | |
724 | if ( /*timerflag && */ tirpcflag) | |
725 | fprintf (fout, "#include <sys/resource.h> /* rlimit */\n"); | |
726 | if (logflag || inetdflag || pmflag) | |
727 | { | |
880f421f | 728 | fprintf (fout, "#include <syslog.h>\n"); |
880f421f | 729 | } |
0d204b0a | 730 | |
880f421f UD |
731 | /* for ANSI-C */ |
732 | if (Cflag) | |
733 | fprintf (fout, "\n#ifndef SIG_PF\n#define SIG_PF void(*)(int)\n#endif\n"); | |
0d204b0a | 734 | |
880f421f UD |
735 | if (timerflag) |
736 | fprintf (fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime); | |
737 | while ((def = get_definition ()) != NULL) | |
738 | { | |
739 | foundprogram |= (def->def_kind == DEF_PROGRAM); | |
740 | } | |
741 | if (extend && !foundprogram) | |
742 | { | |
743 | unlink (outfilename); | |
744 | return; | |
745 | } | |
746 | write_most (infile, netflag, nomain); | |
747 | if (!nomain) | |
748 | { | |
749 | if (!do_registers (argc, argv)) | |
750 | { | |
751 | if (outfilename) | |
752 | unlink (outfilename); | |
cbbcaf23 | 753 | usage (stderr, 1); |
28f540f4 | 754 | } |
880f421f UD |
755 | write_rest (); |
756 | } | |
0dee6738 UD |
757 | close_input (); |
758 | close_output (outfilename); | |
28f540f4 RM |
759 | } |
760 | ||
0d204b0a UD |
761 | /* |
762 | * generate client side stubs | |
763 | */ | |
764 | static void | |
880f421f UD |
765 | l_output (const char *infile, const char *define, int extend, |
766 | const char *outfile) | |
28f540f4 | 767 | { |
880f421f UD |
768 | char *include; |
769 | definition *def; | |
770 | int foundprogram = 0; | |
771 | const char *outfilename; | |
772 | ||
773 | open_input (infile, define); | |
774 | outfilename = extend ? extendfile (infile, outfile) : outfile; | |
775 | open_output (infile, outfilename); | |
776 | add_warning (); | |
777 | if (Cflag) | |
778 | fprintf (fout, "#include <memory.h> /* for memset */\n"); | |
779 | if (infile && (include = extendfile (infile, ".h"))) | |
780 | { | |
781 | fprintf (fout, "#include \"%s\"\n", include); | |
782 | free (include); | |
783 | } | |
784 | else | |
785 | fprintf (fout, "#include <rpc/rpc.h>\n"); | |
786 | while ((def = get_definition ()) != NULL) | |
787 | { | |
788 | foundprogram |= (def->def_kind == DEF_PROGRAM); | |
789 | } | |
790 | if (extend && !foundprogram) | |
791 | { | |
792 | unlink (outfilename); | |
793 | return; | |
794 | } | |
795 | write_stubs (); | |
0dee6738 UD |
796 | close_input (); |
797 | close_output (outfilename); | |
28f540f4 RM |
798 | } |
799 | ||
800 | /* | |
0d204b0a | 801 | * generate the dispatch table |
28f540f4 | 802 | */ |
0d204b0a | 803 | static void |
880f421f UD |
804 | t_output (const char *infile, const char *define, int extend, |
805 | const char *outfile) | |
0d204b0a | 806 | { |
880f421f UD |
807 | definition *def; |
808 | int foundprogram = 0; | |
809 | const char *outfilename; | |
810 | ||
811 | open_input (infile, define); | |
812 | outfilename = extend ? extendfile (infile, outfile) : outfile; | |
813 | open_output (infile, outfilename); | |
814 | add_warning (); | |
815 | while ((def = get_definition ()) != NULL) | |
816 | { | |
817 | foundprogram |= (def->def_kind == DEF_PROGRAM); | |
818 | } | |
819 | if (extend && !foundprogram) | |
820 | { | |
821 | unlink (outfilename); | |
822 | return; | |
823 | } | |
824 | write_tables (); | |
0dee6738 UD |
825 | close_input (); |
826 | close_output (outfilename); | |
0d204b0a UD |
827 | } |
828 | ||
829 | /* sample routine for the server template */ | |
830 | static void | |
880f421f UD |
831 | svc_output (const char *infile, const char *define, int extend, |
832 | const char *outfile) | |
0d204b0a UD |
833 | { |
834 | definition *def; | |
835 | char *include; | |
836 | const char *outfilename; | |
837 | long tell; | |
838 | ||
880f421f UD |
839 | open_input (infile, define); |
840 | outfilename = extend ? extendfile (infile, outfile) : outfile; | |
841 | checkfiles (infile, outfilename); | |
842 | /*check if outfile already exists. | |
843 | if so, print an error message and exit */ | |
844 | open_output (infile, outfilename); | |
845 | add_sample_msg (); | |
846 | ||
847 | if (infile && (include = extendfile (infile, ".h"))) | |
848 | { | |
849 | fprintf (fout, "#include \"%s\"\n", include); | |
850 | free (include); | |
851 | } | |
852 | else | |
853 | fprintf (fout, "#include <rpc/rpc.h>\n"); | |
854 | ||
855 | tell = ftell (fout); | |
856 | while ((def = get_definition ()) != NULL) | |
857 | { | |
858 | write_sample_svc (def); | |
859 | } | |
860 | if (extend && tell == ftell (fout)) | |
861 | { | |
862 | unlink (outfilename); | |
863 | } | |
0dee6738 UD |
864 | close_input (); |
865 | close_output (outfilename); | |
0d204b0a UD |
866 | } |
867 | ||
868 | ||
869 | /* sample main routine for client */ | |
870 | static void | |
880f421f UD |
871 | clnt_output (const char *infile, const char *define, int extend, |
872 | const char *outfile) | |
0d204b0a UD |
873 | { |
874 | definition *def; | |
875 | char *include; | |
876 | const char *outfilename; | |
877 | long tell; | |
878 | int has_program = 0; | |
28f540f4 | 879 | |
880f421f UD |
880 | open_input (infile, define); |
881 | outfilename = extend ? extendfile (infile, outfile) : outfile; | |
882 | checkfiles (infile, outfilename); | |
883 | /*check if outfile already exists. | |
884 | if so, print an error message and exit */ | |
885 | ||
886 | open_output (infile, outfilename); | |
887 | add_sample_msg (); | |
888 | if (infile && (include = extendfile (infile, ".h"))) | |
889 | { | |
890 | fprintf (fout, "#include \"%s\"\n", include); | |
891 | free (include); | |
892 | } | |
893 | else | |
894 | fprintf (fout, "#include <rpc/rpc.h>\n"); | |
895 | tell = ftell (fout); | |
896 | while ((def = get_definition ()) != NULL) | |
897 | { | |
898 | has_program += write_sample_clnt (def); | |
899 | } | |
900 | ||
901 | if (has_program) | |
902 | write_sample_clnt_main (); | |
903 | ||
904 | if (extend && tell == ftell (fout)) | |
905 | { | |
906 | unlink (outfilename); | |
907 | } | |
0dee6738 UD |
908 | close_input (); |
909 | close_output (outfilename); | |
880f421f UD |
910 | } |
911 | ||
0292b0dd UD |
912 | static const char space[] = " "; |
913 | ||
880f421f UD |
914 | static char * |
915 | file_name (const char *file, const char *ext) | |
916 | { | |
917 | char *temp; | |
918 | temp = extendfile (file, ext); | |
919 | ||
920 | if (access (temp, F_OK) != -1) | |
921 | return (temp); | |
0292b0dd UD |
922 | |
923 | free (temp); | |
924 | return (char *) space; | |
880f421f UD |
925 | } |
926 | ||
927 | static void | |
928 | mkfile_output (struct commandline *cmd) | |
929 | { | |
930 | char *mkfilename; | |
0292b0dd UD |
931 | char *clientname, *clntname, *xdrname, *hdrname; |
932 | char *servername, *svcname, *servprogname, *clntprogname; | |
880f421f UD |
933 | |
934 | svcname = file_name (cmd->infile, "_svc.c"); | |
935 | clntname = file_name (cmd->infile, "_clnt.c"); | |
936 | xdrname = file_name (cmd->infile, "_xdr.c"); | |
937 | hdrname = file_name (cmd->infile, ".h"); | |
938 | ||
939 | if (allfiles) | |
940 | { | |
941 | servername = extendfile (cmd->infile, "_server.c"); | |
942 | clientname = extendfile (cmd->infile, "_client.c"); | |
943 | } | |
944 | else | |
945 | { | |
0292b0dd UD |
946 | servername = (char *) space; |
947 | clientname = (char *) space; | |
880f421f UD |
948 | } |
949 | servprogname = extendfile (cmd->infile, "_server"); | |
950 | clntprogname = extendfile (cmd->infile, "_client"); | |
951 | ||
952 | if (allfiles) | |
953 | { | |
ee586e0e UD |
954 | char *cp, *temp; |
955 | ||
956 | mkfilename = alloc (strlen ("Makefile.") + strlen (cmd->infile) + 1); | |
0292b0dd UD |
957 | if (mkfilename == NULL) |
958 | abort (); | |
ee586e0e UD |
959 | temp = rindex (cmd->infile, '.'); |
960 | cp = stpcpy (mkfilename, "Makefile."); | |
486bdb88 UD |
961 | if (temp != NULL) |
962 | *((char *) stpncpy (cp, cmd->infile, temp - cmd->infile)) = '\0'; | |
963 | else | |
964 | stpcpy (cp, cmd->infile); | |
965 | ||
880f421f UD |
966 | } |
967 | else | |
968 | mkfilename = (char *) cmd->outfile; | |
969 | ||
970 | checkfiles (NULL, mkfilename); | |
971 | open_output (NULL, mkfilename); | |
972 | ||
973 | fprintf (fout, "\n# This is a template Makefile generated by rpcgen\n"); | |
974 | ||
975 | f_print (fout, "\n# Parameters\n\n"); | |
976 | ||
977 | f_print (fout, "CLIENT = %s\nSERVER = %s\n\n", clntprogname, servprogname); | |
978 | f_print (fout, "SOURCES_CLNT.c = \nSOURCES_CLNT.h = \n"); | |
979 | f_print (fout, "SOURCES_SVC.c = \nSOURCES_SVC.h = \n"); | |
980 | f_print (fout, "SOURCES.x = %s\n\n", cmd->infile); | |
981 | f_print (fout, "TARGETS_SVC.c = %s %s %s \n", | |
982 | svcname, servername, xdrname); | |
983 | f_print (fout, "TARGETS_CLNT.c = %s %s %s \n", | |
984 | clntname, clientname, xdrname); | |
985 | f_print (fout, "TARGETS = %s %s %s %s %s %s\n\n", | |
986 | hdrname, xdrname, clntname, | |
987 | svcname, clientname, servername); | |
988 | ||
989 | f_print (fout, "OBJECTS_CLNT = $(SOURCES_CLNT.c:%%.c=%%.o) \ | |
990 | $(TARGETS_CLNT.c:%%.c=%%.o)"); | |
991 | ||
992 | f_print (fout, "\nOBJECTS_SVC = $(SOURCES_SVC.c:%%.c=%%.o) \ | |
993 | $(TARGETS_SVC.c:%%.c=%%.o)"); | |
994 | ||
995 | f_print (fout, "\n# Compiler flags \n"); | |
996 | if (mtflag) | |
997 | fprintf (fout, "\nCPPFLAGS += -D_REENTRANT\nCFLAGS += -g \nLDLIBS \ | |
998 | += -lnsl -lpthread \n "); | |
999 | else | |
1000 | f_print (fout, "\nCFLAGS += -g \nLDLIBS += -lnsl\n"); | |
1001 | f_print (fout, "RPCGENFLAGS = \n"); | |
1002 | ||
1003 | f_print (fout, "\n# Targets \n\n"); | |
1004 | ||
1005 | f_print (fout, "all : $(CLIENT) $(SERVER)\n\n"); | |
1006 | f_print (fout, "$(TARGETS) : $(SOURCES.x) \n"); | |
1007 | f_print (fout, "\trpcgen $(RPCGENFLAGS) $(SOURCES.x)\n\n"); | |
1008 | f_print (fout, "$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) \ | |
1009 | $(TARGETS_CLNT.c) \n\n"); | |
1010 | ||
1011 | f_print (fout, "$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) \ | |
1012 | $(TARGETS_SVC.c) \n\n"); | |
1013 | f_print (fout, "$(CLIENT) : $(OBJECTS_CLNT) \n"); | |
1014 | f_print (fout, "\t$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) \ | |
1015 | $(LDLIBS) \n\n"); | |
1016 | f_print (fout, "$(SERVER) : $(OBJECTS_SVC) \n"); | |
1017 | f_print (fout, "\t$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n "); | |
1018 | f_print (fout, "clean:\n\t $(RM) core $(TARGETS) $(OBJECTS_CLNT) \ | |
1019 | $(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n"); | |
0dee6738 | 1020 | close_output (mkfilename); |
0292b0dd UD |
1021 | |
1022 | free (clntprogname); | |
1023 | free (servprogname); | |
1024 | if (servername != space) | |
1025 | free (servername); | |
1026 | if (clientname != space) | |
1027 | free (clientname); | |
1028 | if (mkfilename != (char *) cmd->outfile) | |
1029 | free (mkfilename); | |
1030 | if (svcname != space) | |
1031 | free (svcname); | |
1032 | if (clntname != space) | |
1033 | free (clntname); | |
1034 | if (xdrname != space) | |
1035 | free (xdrname); | |
1036 | if (hdrname != space) | |
1037 | free (hdrname); | |
0d204b0a UD |
1038 | } |
1039 | ||
1040 | /* | |
1041 | * Perform registrations for service output | |
1042 | * Return 0 if failed; 1 otherwise. | |
1043 | */ | |
880f421f UD |
1044 | static int |
1045 | do_registers (int argc, const char *argv[]) | |
28f540f4 | 1046 | { |
880f421f UD |
1047 | int i; |
1048 | ||
1049 | if (inetdflag || !tirpcflag) | |
1050 | { | |
1051 | for (i = 1; i < argc; i++) | |
1052 | { | |
1053 | if (streq (argv[i], "-s")) | |
1054 | { | |
1055 | if (!check_nettype (argv[i + 1], valid_i_nettypes)) | |
1056 | return 0; | |
1057 | write_inetd_register (argv[i + 1]); | |
1058 | i++; | |
1059 | } | |
28f540f4 | 1060 | } |
880f421f UD |
1061 | } |
1062 | else | |
1063 | { | |
1064 | for (i = 1; i < argc; i++) | |
1065 | if (streq (argv[i], "-s")) | |
1066 | { | |
1067 | if (!check_nettype (argv[i + 1], valid_ti_nettypes)) | |
1068 | return 0; | |
1069 | write_nettype_register (argv[i + 1]); | |
1070 | i++; | |
1071 | } | |
1072 | else if (streq (argv[i], "-n")) | |
1073 | { | |
1074 | write_netid_register (argv[i + 1]); | |
1075 | i++; | |
1076 | } | |
1077 | } | |
1078 | return 1; | |
28f540f4 RM |
1079 | } |
1080 | ||
1081 | /* | |
0d204b0a | 1082 | * Add another argument to the arg list |
28f540f4 | 1083 | */ |
0d204b0a | 1084 | static void |
880f421f | 1085 | addarg (const char *cp) |
0d204b0a | 1086 | { |
880f421f UD |
1087 | if (argcount >= ARGLISTLEN) |
1088 | { | |
1089 | fprintf (stderr, _("rpcgen: too many defines\n")); | |
1090 | crash (); | |
1091 | /*NOTREACHED */ | |
1092 | } | |
1093 | arglist[argcount++] = cp; | |
0d204b0a UD |
1094 | } |
1095 | ||
1096 | static void | |
880f421f | 1097 | putarg (int whereto, const char *cp) |
0d204b0a | 1098 | { |
880f421f UD |
1099 | if (whereto >= ARGLISTLEN) |
1100 | { | |
1101 | fprintf (stderr, _("rpcgen: arglist coding error\n")); | |
1102 | crash (); | |
1103 | /*NOTREACHED */ | |
1104 | } | |
1105 | arglist[whereto] = cp; | |
0d204b0a | 1106 | } |
28f540f4 | 1107 | |
0d204b0a UD |
1108 | /* |
1109 | * if input file is stdin and an output file is specified then complain | |
1110 | * if the file already exists. Otherwise the file may get overwritten | |
1111 | * If input file does not exist, exit with an error | |
1112 | */ | |
1113 | ||
1114 | static void | |
880f421f | 1115 | checkfiles (const char *infile, const char *outfile) |
0d204b0a | 1116 | { |
0d204b0a UD |
1117 | struct stat buf; |
1118 | ||
880f421f UD |
1119 | if (infile) /* infile ! = NULL */ |
1120 | if (stat (infile, &buf) < 0) | |
0d204b0a | 1121 | { |
880f421f UD |
1122 | perror (infile); |
1123 | crash (); | |
1124 | } | |
1125 | if (outfile) | |
1126 | { | |
1127 | if (stat (outfile, &buf) < 0) | |
1128 | return; /* file does not exist */ | |
1129 | else | |
1130 | { | |
1131 | fprintf (stderr, | |
ad8d58c1 UD |
1132 | /* TRANS: the file will not be removed; this is an |
1133 | TRANS: informative message. */ | |
db276fa1 | 1134 | _("file `%s' already exists and may be overwritten\n"), |
880f421f UD |
1135 | outfile); |
1136 | crash (); | |
1137 | } | |
0d204b0a | 1138 | } |
0d204b0a UD |
1139 | } |
1140 | ||
1141 | /* | |
1142 | * Parse command line arguments | |
1143 | */ | |
1144 | static int | |
880f421f | 1145 | parseargs (int argc, const char *argv[], struct commandline *cmd) |
28f540f4 | 1146 | { |
880f421f UD |
1147 | int i; |
1148 | int j; | |
1149 | int c; | |
1150 | char flag[(1 << 8 * sizeof (char))]; | |
1151 | int nflags; | |
1152 | ||
1153 | cmdname = argv[0]; | |
1154 | cmd->infile = cmd->outfile = NULL; | |
1155 | if (argc < 2) | |
1156 | { | |
1157 | return (0); | |
1158 | } | |
1159 | allfiles = 0; | |
1160 | flag['c'] = 0; | |
1161 | flag['h'] = 0; | |
1162 | flag['l'] = 0; | |
1163 | flag['m'] = 0; | |
1164 | flag['o'] = 0; | |
1165 | flag['s'] = 0; | |
1166 | flag['n'] = 0; | |
1167 | flag['t'] = 0; | |
1168 | flag['S'] = 0; | |
1169 | flag['C'] = 0; | |
1170 | flag['M'] = 0; | |
1171 | ||
1172 | for (i = 1; i < argc; i++) | |
1173 | { | |
1174 | if (argv[i][0] != '-') | |
1175 | { | |
1176 | if (cmd->infile) | |
1177 | { | |
1178 | fprintf (stderr, | |
1179 | _("Cannot specify more than one input file!\n")); | |
1180 | return 0; | |
1181 | } | |
1182 | cmd->infile = argv[i]; | |
28f540f4 | 1183 | } |
cbbcaf23 UD |
1184 | else if (strcmp (argv[i], "--help") == 0) |
1185 | usage (stdout, 0); | |
1186 | else if (strcmp (argv[i], "--version") == 0) | |
1187 | print_version (); | |
880f421f UD |
1188 | else |
1189 | { | |
1190 | for (j = 1; argv[i][j] != 0; j++) | |
1191 | { | |
1192 | c = argv[i][j]; | |
1193 | switch (c) | |
1194 | { | |
1195 | case 'a': | |
1196 | allfiles = 1; | |
1197 | break; | |
1198 | case 'c': | |
1199 | case 'h': | |
1200 | case 'l': | |
1201 | case 'm': | |
1202 | case 't': | |
1203 | if (flag[c]) | |
1204 | return 0; | |
1205 | flag[c] = 1; | |
1206 | break; | |
1207 | case 'S': | |
1208 | /* sample flag: Ss or Sc. | |
1209 | Ss means set flag['S']; | |
1210 | Sc means set flag['C']; | |
1211 | Sm means set flag['M']; */ | |
1212 | c = argv[i][++j]; /* get next char */ | |
1213 | if (c == 's') | |
1214 | c = 'S'; | |
1215 | else if (c == 'c') | |
1216 | c = 'C'; | |
1217 | else if (c == 'm') | |
1218 | c = 'M'; | |
1219 | else | |
1220 | return 0; | |
1221 | ||
1222 | if (flag[c]) | |
1223 | return 0; | |
1224 | flag[c] = 1; | |
1225 | break; | |
1226 | case 'C': /* ANSI C syntax */ | |
1227 | Cflag = 1; | |
1228 | break; | |
0d204b0a | 1229 | |
880f421f UD |
1230 | case 'k': /* K&R C syntax */ |
1231 | Cflag = 0; | |
1232 | break; | |
0d204b0a | 1233 | |
880f421f UD |
1234 | case 'b': /* turn TIRPC flag off for |
1235 | generating backward compatible | |
1236 | */ | |
1237 | tirpcflag = 0; | |
1238 | break; | |
0d204b0a | 1239 | |
880f421f UD |
1240 | case '5': /* turn TIRPC flag on for |
1241 | generating SysVr4 compatible | |
1242 | */ | |
1243 | tirpcflag = 1; | |
1244 | break; | |
880f421f UD |
1245 | case 'I': |
1246 | inetdflag = 1; | |
1247 | break; | |
1248 | case 'N': | |
1249 | newstyle = 1; | |
1250 | break; | |
1251 | case 'L': | |
1252 | logflag = 1; | |
1253 | break; | |
1254 | case 'K': | |
1255 | if (++i == argc) | |
1256 | { | |
1257 | return (0); | |
1258 | } | |
1259 | svcclosetime = argv[i]; | |
1260 | goto nextarg; | |
1261 | case 'T': | |
1262 | tblflag = 1; | |
1263 | break; | |
1264 | case 'M': | |
1265 | mtflag = 1; | |
1266 | break; | |
1267 | case 'i': | |
1268 | if (++i == argc) | |
1269 | { | |
1270 | return (0); | |
1271 | } | |
1272 | inlineflag = atoi (argv[i]); | |
1273 | goto nextarg; | |
1274 | case 'n': | |
1275 | case 'o': | |
1276 | case 's': | |
1277 | if (argv[i][j - 1] != '-' || | |
1278 | argv[i][j + 1] != 0) | |
1279 | { | |
1280 | return (0); | |
1281 | } | |
1282 | flag[c] = 1; | |
1283 | if (++i == argc) | |
1284 | { | |
1285 | return (0); | |
1286 | } | |
1287 | if (c == 's') | |
1288 | { | |
1289 | if (!streq (argv[i], "udp") && | |
be18eced | 1290 | !streq (argv[i], "tcp")) |
880f421f UD |
1291 | return 0; |
1292 | } | |
1293 | else if (c == 'o') | |
1294 | { | |
1295 | if (cmd->outfile) | |
1296 | return 0; | |
1297 | cmd->outfile = argv[i]; | |
1298 | } | |
1299 | goto nextarg; | |
1300 | case 'D': | |
1301 | if (argv[i][j - 1] != '-') | |
1302 | return 0; | |
1303 | addarg (argv[i]); | |
1304 | goto nextarg; | |
1305 | case 'Y': | |
1306 | if (++i == argc) | |
1307 | return 0; | |
1308 | { | |
1309 | size_t len = strlen (argv[i]); | |
1310 | pathbuf = malloc (len + 5); | |
1311 | if (pathbuf == NULL) | |
1312 | { | |
1313 | perror (cmdname); | |
1314 | crash (); | |
1315 | } | |
1316 | stpcpy (stpcpy (pathbuf, | |
1317 | argv[i]), | |
1318 | "/cpp"); | |
1319 | CPP = pathbuf; | |
1320 | cppDefined = 1; | |
1321 | goto nextarg; | |
1322 | } | |
1323 | ||
1324 | default: | |
1325 | return 0; | |
28f540f4 | 1326 | } |
880f421f UD |
1327 | } |
1328 | nextarg: | |
1329 | ; | |
28f540f4 | 1330 | } |
880f421f | 1331 | } |
0d204b0a | 1332 | |
880f421f UD |
1333 | cmd->cflag = flag['c']; |
1334 | cmd->hflag = flag['h']; | |
1335 | cmd->lflag = flag['l']; | |
1336 | cmd->mflag = flag['m']; | |
1337 | cmd->nflag = flag['n']; | |
1338 | cmd->sflag = flag['s']; | |
1339 | cmd->tflag = flag['t']; | |
1340 | cmd->Ssflag = flag['S']; | |
1341 | cmd->Scflag = flag['C']; | |
1342 | cmd->makefileflag = flag['M']; | |
1343 | ||
b982085b | 1344 | #ifndef _RPC_THREAD_SAFE_ |
e513a8fd AJ |
1345 | if (mtflag || newstyle) |
1346 | { | |
1347 | /* glibc doesn't support these flags. */ | |
1348 | f_print (stderr, | |
1349 | _("This implementation doesn't support newstyle or MT-safe code!\n")); | |
1350 | return (0); | |
1351 | } | |
b982085b | 1352 | #endif |
880f421f UD |
1353 | if (tirpcflag) |
1354 | { | |
1355 | pmflag = inetdflag ? 0 : 1; /* pmflag or inetdflag is always TRUE */ | |
1356 | if ((inetdflag && cmd->nflag)) | |
1357 | { /* netid not allowed with inetdflag */ | |
1358 | fprintf (stderr, _("Cannot use netid flag with inetd flag!\n")); | |
1359 | return 0; | |
1360 | } | |
1361 | } | |
1362 | else | |
1363 | { /* 4.1 mode */ | |
1364 | pmflag = 0; /* set pmflag only in tirpcmode */ | |
880f421f UD |
1365 | if (cmd->nflag) |
1366 | { /* netid needs TIRPC */ | |
1367 | f_print (stderr, _("Cannot use netid flag without TIRPC!\n")); | |
1368 | return (0); | |
0d204b0a | 1369 | } |
880f421f | 1370 | } |
0d204b0a | 1371 | |
880f421f UD |
1372 | if (newstyle && (tblflag || cmd->tflag)) |
1373 | { | |
1374 | f_print (stderr, _("Cannot use table flags with newstyle!\n")); | |
1375 | return (0); | |
1376 | } | |
0d204b0a | 1377 | |
880f421f UD |
1378 | /* check no conflicts with file generation flags */ |
1379 | nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag + | |
1380 | cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag; | |
0d204b0a | 1381 | |
880f421f UD |
1382 | if (nflags == 0) |
1383 | { | |
1384 | if (cmd->outfile != NULL || cmd->infile == NULL) | |
1385 | { | |
1386 | return (0); | |
28f540f4 | 1387 | } |
880f421f UD |
1388 | } |
1389 | else if (cmd->infile == NULL && | |
1390 | (cmd->Ssflag || cmd->Scflag || cmd->makefileflag)) | |
1391 | { | |
1392 | fprintf (stderr, | |
1393 | _("\"infile\" is required for template generation flags.\n")); | |
1394 | return 0; | |
1395 | } | |
1396 | if (nflags > 1) | |
1397 | { | |
1398 | fprintf (stderr, _("Cannot have more than one file generation flag!\n")); | |
1399 | return 0; | |
1400 | } | |
1401 | return 1; | |
28f540f4 | 1402 | } |
0d204b0a UD |
1403 | |
1404 | static void | |
cbbcaf23 | 1405 | usage (FILE *stream, int status) |
0d204b0a | 1406 | { |
cbbcaf23 UD |
1407 | fprintf (stream, _("usage: %s infile\n"), cmdname); |
1408 | fprintf (stream, _("\t%s [-abkCLNTM][-Dname[=value]] [-i size] \ | |
880f421f | 1409 | [-I [-K seconds]] [-Y path] infile\n"), cmdname); |
cbbcaf23 | 1410 | fprintf (stream, _("\t%s [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm] \ |
880f421f | 1411 | [-o outfile] [infile]\n"), cmdname); |
cbbcaf23 UD |
1412 | fprintf (stream, _("\t%s [-s nettype]* [-o outfile] [infile]\n"), cmdname); |
1413 | fprintf (stream, _("\t%s [-n netid]* [-o outfile] [infile]\n"), cmdname); | |
1414 | options_usage (stream, status); | |
1415 | exit (status); | |
1416 | } | |
1417 | ||
1418 | static void | |
1419 | options_usage (FILE *stream, int status) | |
1420 | { | |
1421 | f_print (stream, _("options:\n")); | |
1422 | f_print (stream, _("-a\t\tgenerate all files, including samples\n")); | |
1423 | f_print (stream, _("-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n")); | |
1424 | f_print (stream, _("-c\t\tgenerate XDR routines\n")); | |
1425 | f_print (stream, _("-C\t\tANSI C mode\n")); | |
1426 | f_print (stream, _("-Dname[=value]\tdefine a symbol (same as #define)\n")); | |
1427 | f_print (stream, _("-h\t\tgenerate header file\n")); | |
1428 | f_print (stream, _("-i size\t\tsize at which to start generating inline code\n")); | |
1429 | f_print (stream, _("-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n")); | |
1430 | f_print (stream, _("-K seconds\tserver exits after K seconds of inactivity\n")); | |
1431 | f_print (stream, _("-l\t\tgenerate client side stubs\n")); | |
1432 | f_print (stream, _("-L\t\tserver errors will be printed to syslog\n")); | |
1433 | f_print (stream, _("-m\t\tgenerate server side stubs\n")); | |
1434 | f_print (stream, _("-M\t\tgenerate MT-safe code\n")); | |
1435 | f_print (stream, _("-n netid\tgenerate server code that supports named netid\n")); | |
1436 | f_print (stream, _("-N\t\tsupports multiple arguments and call-by-value\n")); | |
1437 | f_print (stream, _("-o outfile\tname of the output file\n")); | |
1438 | f_print (stream, _("-s nettype\tgenerate server code that supports named nettype\n")); | |
1439 | f_print (stream, _("-Sc\t\tgenerate sample client code that uses remote procedures\n")); | |
1440 | f_print (stream, _("-Ss\t\tgenerate sample server code that defines remote procedures\n")); | |
1441 | f_print (stream, _("-Sm \t\tgenerate makefile template \n")); | |
1442 | f_print (stream, _("-t\t\tgenerate RPC dispatch table\n")); | |
1443 | f_print (stream, _("-T\t\tgenerate code to support RPC dispatch tables\n")); | |
1444 | f_print (stream, _("-Y path\t\tdirectory name to find C preprocessor (cpp)\n")); | |
1445 | ||
1446 | f_print (stream, "\n%s", _("\ | |
1447 | For bug reporting instructions, please see:\n\ | |
1448 | <http://www.gnu.org/software/libc/bugs.html>.\n")); | |
1449 | exit (status); | |
0d204b0a UD |
1450 | } |
1451 | ||
1452 | static void | |
cbbcaf23 | 1453 | print_version (void) |
0d204b0a | 1454 | { |
cbbcaf23 UD |
1455 | printf ("rpcgen (GNU %s) %s\n", PACKAGE, VERSION); |
1456 | exit (0); | |
0d204b0a | 1457 | } |