/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* University Copyright- Copyright (c) 1982, 1986, 1988
* The Regents of the University of California
* All Rights Reserved
*
* University Acknowledgment- Portions of this document are derived from
* software developed by the University of California, Berkeley, and its
* contributors.
*/
/*
* rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
*/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "rpc_parse.h"
#include "rpc_util.h"
static void internal_proctype(proc_list *);
static void write_real_program(definition *);
static void write_programs(char *);
static void write_program(definition *, char *);
static void printerr(char *, char *);
static void write_svc_aux(int);
static void printif(char *, char *, char *, char *);
static void write_inetmost(char *);
static void print_return(char *);
static void print_pmapunset(char *);
static void print_err_message(const char *, const char *, ...);
static void write_msg_out(void);
static void write_timeout_func(void);
static void write_pm_most(char *, int);
static void write_rpc_svc_fg(char *, char *);
static void open_log_file(char *, char *);
static void
{
if (Cflag) {
} else {
}
}
static void
{
}
static void
write_mtauto(void)
{
}
/*
* write most of the service, that is, everything but the registrations.
*/
void
{
char *var_type;
if (!tirpcflag) {
"\t\t /* Whether Stream or Datagram ? */\n");
}
if (timerflag) {
"\n/* States a server can be in wrt request */\n\n");
if (nomain) {
"/* LINTED static unused if no main */\n");
}
"static int _rpcsvcstate = _IDLE;");
"\t/* Set when a request is serviced */\n");
"\t\t/* Number of requests being serviced */\n");
if (mtflag) {
"\t\t/* lock for _rpcsvcstate, _rpcsvccount */\n");
}
}
}
/* write out dispatcher and stubs */
if (nomain)
return;
if (inetdflag) {
/* Includes call to write_rpc_svc_fg() */
} else {
if (tirpcflag) {
if (netflag) {
"\tregister SVCXPRT *%s;\n", TRANSP);
"\tstruct netconfig *nconf = NULL;\n");
}
if (mtauto) {
"\tint mode = RPC_SVC_MT_AUTO;\n\n");
write_mtauto();
} else
"\tmutex_init(&_svcstate_lock, USYNC_THREAD, NULL);\n");
} else {
print_pmapunset("\t");
}
}
}
}
/*
* write a registration for the given transport
*/
void
{
list *l;
char *sp;
sp = "";
continue;
}
"%s\t(void) rpcb_unset(%s, %s, nconf);\n",
"%s\tif (!svc_reg(%s, %s, %s, ",
"unable to register (%s, %s, %s).",
}
}
}
/*
* write a registration for the given transport for TLI
*/
void
{
list *l;
continue;
}
print_err_message("\t\t",
"unable to create (%s, %s) for %s.",
}
}
}
/*
* write the rest of the service
*/
void
write_rest(void)
{
if (inetdflag) {
if (timerflag) {
if (mtflag) {
"\t\tif (thr_create(NULL, 0, closedown, NULL, 0, NULL) != 0) {\n");
print_err_message("\t\t\t",
"cannot create closedown thread");
} else {
"\t\t(void) signal(SIGALRM, %s closedown);\n",
"\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
}
}
}
}
static void
{
list *l;
/* write out stubs for procedure definitions */
}
/* write out dispatcher for each program */
}
}
/*
* write out definition of internal function (e.g. _printmsg_1(...))
* which calls server's defintion of actual function (e.g. printmsg_1(...)).
* Unpacks single user argument of printmsg_1 to call-by-value format
* expected by printmsg_1.
*/
static void
{
decl_list *l;
if (!newstyle)
return; /* not needed for old style */
}
if (!mtflag)
else
if (Cflag) {
/* arg name */
/* LINTED variable format */
else
if (mtflag) {
}
RQSTP);
} else {
if (mtflag)
else
/* arg name */
else {
}
if (mtflag)
}
/* for mtflag, arguments are different */
else
/* only print if non-void */
} else {
l = l->next)
}
}
}
}
static void
{
int filled;
}
if (Cflag) {
} else {
}
filled = 0;
"void")) {
continue;
}
filled = 1;
} else {
filled = 1;
}
}
if (!filled) {
}
if (mtflag) {
filled = 0;
continue;
filled = 1;
}
if (!filled)
} else
if (Cflag) {
if (mtflag)
"\tbool_t (*%s)(char *, void *, struct svc_req *);\n",
ROUTINE);
else
"\tchar *(*%s)(char *, struct svc_req *);\n",
ROUTINE);
} else {
"\tbool_t (*_xdr_%s)(), (*_xdr_%s)();\n",
if (mtflag)
else
}
if (timerflag) {
if (mtflag)
"\t(void) mutex_lock(&_svcstate_lock);\n");
if (mtflag)
"\t(void) mutex_unlock(&_svcstate_lock);\n");
}
Cflag ?
"\t\t(void) svc_sendreply(%s,\n\t\t (xdrproc_t)xdr_void, NULL);\n" :
"\t\t(void) svc_sendreply(%s, xdr_void,\n\t\t\tNULL);\n",
TRANSP);
print_return("\t\t");
}
} else {
}
/* One-way call */
} else {
}
if (Cflag) {
if (mtflag) {
"\t\t%s = (bool_t (*) (char *, "
"void *, struct svc_req *))",
ROUTINE);
} else {
"\t\t%s = (char *(*)(char *, "
"struct svc_req *))",
ROUTINE);
}
} else {
if (mtflag) {
"\t\t%s = (bool_t (*)())",
ROUTINE);
} else {
ROUTINE);
}
}
if (newstyle) { /* new style: calls internal routine */
}
else
}
print_return("\t\t");
"\t(void) memset((char *)&%s, 0, sizeof (%s));\n",
print_return("\t\t");
if (!mtflag)
if (Cflag)
"\t%s = (*%s)((char *)&%s, %s);\n",
else
else
if (Cflag)
"\t%s = (bool_t)(*%s)((char *)&%s, (void *)&%s, %s);\n",
else
"\t%s = (bool_t)(*%s)(&%s, &%s, %s);\n",
if (mtflag)
"\tif (_xdr_%s && %s > 0 &&\n"
"\t !svc_sendreply(%s, _xdr_%s, (char *)&%s)) {\n",
else
"\tif (_xdr_%s && %s != NULL &&\n"
"\t !svc_sendreply(%s, _xdr_%s, %s)) {\n",
/* print out free routine */
if (mtflag) {
RESULT);
};
print_return("\t");
}
}
static void
{
}
static void
{
}
int
{
return (1);
}
return (0);
}
static void
{
"\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
print_pmapunset("\t\t");
}
static void
{
if (exitnow) {
return;
}
if (timerflag) {
if (mtflag) {
"%s(void) mutex_lock(&_svcstate_lock);\n",
space);
}
if (mtflag) {
"%s(void) mutex_unlock(&_svcstate_lock);\n",
space);
}
}
}
static void
{
list *l;
}
}
}
}
static void
{
if (logflag)
else
}
/*
* Write the server auxiliary function (RPC_MSGOUT, timeout)
*/
static void
{
if (!logflag)
if (!nomain)
}
/*
* Write the RPC_MSGOUT function
*
* Note that while we define RPC_MSGOUT to be printf-like, all existing
* calls are of the form "%s","<msg>" and this implementation assumes that
* trivial case. If in the future it's desirable to generate richer calls
* this implementation can change to match. This way we don't (yet) have
* to introduce varargs into the generated code.
*/
static void
write_msg_out(void)
{
if (!Cflag) {
} else {
}
if (!Cflag) {
} else {
}
}
/*
* Write the timeout function
*/
static void
write_timeout_func(void)
{
if (!timerflag)
return;
if (mtflag) {
if (!Cflag) {
} else
"\t\tif (mutex_trylock(&_svcstate_lock) != 0)\n");
"\t\tif (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {\n");
if (tirpcflag) {
} else {
}
if (tirpcflag) {
} else {
}
"\t\t\tfor (i = 0; i < size && openfd < 2; i++)\n");
if (tirpcflag) {
} else {
}
return;
}
if (!Cflag) {
} else
if (tirpcflag) {
} else {
}
if (tirpcflag) {
} else {
}
"\t\tfor (i = 0; i < size && openfd < 2; i++)\n");
if (tirpcflag) {
} else {
}
}
/*
* Write the most of port monitor support
*/
static void
{
list *l;
if (!netflag) { /* Not included by -n option */
}
if (timerflag)
/*
* f_print(fout, "\t\textern char *getenv();\n");
*/
"\n\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n");
if (timerflag) {
}
if (timerflag)
"\n\t\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
"\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n",
TRANSP);
continue;
}
"\t\tif (!svc_reg(%s, %s, %s,\n",
print_err_message("\t\t\t",
"unable to register (%s, %s).",
}
}
if (timerflag) {
if (mtflag) {
"\t\t\tif (thr_create(NULL, 0, closedown, NULL,\n\t\t\t 0, NULL) != 0) {\n");
print_err_message("\t\t\t\t",
"cannot create closedown thread");
} else {
"\t\t\t(void) signal(SIGALRM, %s closedown);\n",
"\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
}
}
}
/*
* Support for backgrounding the server if self started.
*/
static void
{
if (tirpcflag)
if (inetdflag)
/* close all file descriptors */
if (tirpcflag) {
} else {
}
/* This removes control of the controlling terminal */
if (tirpcflag)
else {
"%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);
}
if (!logflag)
if (logflag)
}
static void
{
char *s;
if (s)
*s = '\0';
if (s)
*s = '.';
}
/*
* write a registration for the given transport for Inetd
*/
void
{
list *l;
char *sp;
int isudp;
if (inetdflag)
sp = "\t";
else
sp = "";
isudp = 1;
else
isudp = 0;
if (inetdflag) {
"\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n",
}
if (!isudp)
if (inetdflag) {
}
continue;
if (inetdflag)
else
"unable to register (%s, %s, %s).",
}
}
if (inetdflag)
}