/*
* 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.
*/
/*
* PICL daemon
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <libintl.h>
#include <locale.h>
#include <alloca.h>
#include <errno.h>
#include <assert.h>
#include <stropts.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <synch.h>
#include <door.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <time.h>
#include <sys/systeminfo.h>
#include <dirent.h>
#include <syslog.h>
#include <poll.h>
#include <limits.h>
#include <picl.h>
#include "picl2door.h"
#include <picltree.h>
#include "ptree_impl.h"
/*
* Log text messages
*/
#define SIGACT_FAILED \
gettext("Failed to install signal handler for %s: %s\n")
/*
* Constants
*/
/*
* Macros
*/
extern char **environ;
/*
* Module Variables
*/
static int doreinit = 0;
static int service_requests = 0;
static int pool_count = 0;
static int wait_count = 0;
static struct {
int count;
/*
* This returns an error message to libpicl
*/
static void
{
0);
}
/*
* picld_init is called when a picl_initialize request is received
*/
static void
{
int clmajrev;
if (clmajrev < PICL_VERSION_1)
}
/*
* picld_fini is called when a picl_shutdown request is received
*/
static void
{
}
static void
{
}
static int
{
int i;
if (uid == 0)
return (PICL_SUCCESS);
for (i = 0; i < MAX_CONCURRENT_WAITS; i++) {
return (PICL_FAILURE);
user_count[i].count++;
return (PICL_SUCCESS);
}
free_idx = i;
}
if (free_idx != -1) {
return (PICL_SUCCESS);
}
return (PICL_FAILURE);
}
static void
{
int i;
if (uid == 0)
return;
for (i = 0; i < MAX_CONCURRENT_WAITS; i++) {
if (--user_count[i].count == 0)
user_count[i].uid = 0;
return;
}
}
}
static int
{
int rv;
if (pthread_mutex_lock(&wait_req_mutex) != 0)
return (PICL_FAILURE);
if ((wait_count < MAX_CONCURRENT_WAITS) &&
rv = PICL_SUCCESS;
wait_count++;
} else {
rv = PICL_FAILURE;
}
(void) pthread_mutex_unlock(&wait_req_mutex);
return (rv);
}
static void
{
(void) pthread_mutex_lock(&wait_req_mutex);
wait_count--;
(void) pthread_mutex_unlock(&wait_req_mutex);
}
/*
* picld_wait is called when a picl_wait request is received
*/
static void
{
int err;
if (door_ucred(&puc) != 0)
else {
else {
}
}
}
/*
* This function returns the handle of the root node of the PICL tree
*/
static void
{
int err;
if (err != PICL_SUCCESS)
}
/*
* This function returns the value of the PICL property
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
cred);
if (err != PICL_SUCCESS)
/*
* adjust returned bytes for charstrings
*/
/*
* convert handle values to picl handles
*/
}
/*
* This function returns the value of the PICL property specified by
* its name.
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
/*
* allocate the minimum of piclinfo.size and input bufsize
*/
cred);
if (err != PICL_SUCCESS)
/*
* adjust returned value size for charstrings
*/
}
/*
* This function sets a property value
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
/*
* For non-volatile prop, only super user can set its value.
*/
if (err != PICL_SUCCESS)
0);
}
/*
* This function sets the value of a property specified by its name.
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
/*
* For non-volatile prop, only super user can set its value.
*/
cred);
if (err != PICL_SUCCESS)
NULL, 0);
}
/*
* This function returns the property information
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
}
/*
* This function returns the node's first property handle
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
}
/*
* This function returns the next property handle in list
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
}
/*
* This function returns the handle of a property specified by its name
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
0);
}
/*
* This function gets the next property on the same row in the table
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
}
/*
* This function returns the handle of the next property in the same column
* of the table.
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
}
/*
* This function finds the node in the PICLTREE that matches the given
* criteria and returns its handle.
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
}
/*
* and returns its handle
*/
static void
{
int err;
if (err != PICL_SUCCESS)
}
/*
* This function returns finds the frutree parent node for a given node
* and returns its handle
*/
static void
{
int err;
if (err != PICL_SUCCESS)
if (err != PICL_SUCCESS)
}
/*
* This function is called when an unknown client request is received.
*/
static void
{
}
static void
{
int dos_flag;
dos_flag = 0;
if (pthread_mutex_lock(&dos_mutex) != 0)
service_requests = 1;
}
if (service_requests > dos_req_limit)
dos_flag = 1;
if (pthread_mutex_unlock(&dos_mutex) != 0)
if (dos_flag)
}
/* ARGSUSED */
static void
{
/*LINTED*/
case PICL_CNUM_INIT:
/*LINTED*/
break;
case PICL_CNUM_FINI:
/*LINTED*/
break;
case PICL_CNUM_GETROOT:
/*LINTED*/
break;
case PICL_CNUM_GETATTRVAL:
/*LINTED*/
break;
/*LINTED*/
break;
case PICL_CNUM_GETATTRINFO:
/*LINTED*/
break;
case PICL_CNUM_GETFIRSTATTR:
/*LINTED*/
break;
case PICL_CNUM_GETNEXTATTR:
/*LINTED*/
break;
case PICL_CNUM_GETATTRBYNAME:
/*LINTED*/
break;
case PICL_CNUM_GETATTRBYROW:
/*LINTED*/
break;
case PICL_CNUM_GETATTRBYCOL:
/*LINTED*/
break;
case PICL_CNUM_SETATTRVAL:
/*LINTED*/
break;
/*LINTED*/
break;
case PICL_CNUM_PING:
/*LINTED*/
break;
case PICL_CNUM_WAIT:
/*LINTED*/
break;
case PICL_CNUM_FINDNODE:
/*LINTED*/
break;
case PICL_CNUM_NODEBYPATH:
/*LINTED*/
break;
case PICL_CNUM_FRUTREEPARENT:
/*LINTED*/
break;
default:
/*LINTED*/
break;
};
/*NOTREACHED*/
}
/* ARGSUSED */
static void
{
doreinit = 1;
}
/*
* "ping" to see if a daemon is already running
*/
static int
daemon_exists(void)
{
int doorh;
if (doorh < 0)
return (0);
return (0);
}
return (0);
}
return (1);
}
return (0);
}
return (1);
}
/*
* picld_create_server_thread - binds the running thread to the private
* door pool, and sets the required cancellation state.
*/
/* ARGSUSED */
static void *
{
/*
* wait for door descriptor to be initialized
*/
(void) pthread_mutex_lock(&door_mutex);
while (door_id == -1) {
}
(void) pthread_mutex_unlock(&door_mutex);
/*
* Bind this thread to the door's private thread pool
*/
perror("door_bind");
}
/*
* Disable thread cancellation mechanism
*/
return (NULL);
}
/*
* picld_server_create_fn - creates threads for the private door pool
*
*/
/* ARGSUSED */
static void
{
/*
* For the non-private pool do nothing. It's used for events which are
* single threaded anyway. The single thread servicing that pool is
* created when the event plugin creates its door. Note that the event
* plugin runs before setup_door instantiates picld_server_create_fn as
* the new create_proc so the door library default create_proc is used.
*/
return;
(void) pthread_mutex_lock(&pool_mutex);
if (pool_count < MAX_POOL_SIZE) {
(void) pthread_attr_init(&attr);
(void) pthread_attr_setdetachstate(&attr,
NULL)) {
perror("pthread_create");
} else {
pool_count++;
}
}
(void) pthread_mutex_unlock(&pool_mutex);
}
/*
* Create the picld door
*/
static int
setup_door(void)
{
(void) door_server_create(picld_server_create_fn);
(void) pthread_mutex_lock(&door_mutex);
/*
* Create the door
*/
if (door_id < 0) {
(void) pthread_mutex_unlock(&door_mutex);
return (-1);
} else {
(void) pthread_cond_signal(&door_cv);
(void) pthread_mutex_unlock(&door_mutex);
}
int newfd;
/* ensure that the door file is world-readable */
/* restore the file mode creation mask */
if (newfd < 0)
return (-1);
}
(fdetach(PICLD_DOOR) < 0) ||
return (-1);
}
return (0);
}
/*
* Main function of picl daemon
*/
int
{
int c;
(void) textdomain(TEXT_DOMAIN);
if (getuid() != 0) {
return (0);
}
doreinit = 0;
logflag = 1;
verbose_level = 0;
/*
* parse arguments
*/
switch (c) {
case 'd':
break;
case 'i':
logflag = 0;
break;
case 's':
break;
case 't':
break;
case 'v':
logflag = 0;
break;
default:
break;
}
}
/*
* is there a daemon already running?
*/
if (daemon_exists()) {
exit(1);
}
/*
* (piclenvd) can use it to simulate sleep() without being affected
* by time being set back. No other PICL plug-in should use SIGALRM
* or alarm() for now.
*/
(void) sigemptyset(&ublk);
/*
* Ignore SIGHUP until all the initialization is done.
*/
if (logflag != 0) { /* daemonize */
if (pid < 0)
exit(1);
if (pid > 0)
/* parent */
exit(0);
/* child */
exit(1);
}
(void) setsid();
closefrom(0);
}
/*
* Initialize the PICL Tree
*/
exit(1);
}
if (setup_door()) {
exit(1);
}
/*
* setup signal handlers for post-init
*/
/*
* wait for requests
*/
for (;;) {
(void) pause();
if (doreinit) {
/*
* Block SIGHUP during reinitialization.
* environmental plug-in (piclenvd) can use it to
* simulate sleep() without being affected by time
* being set back. No ohter PICL plug-in should use
* SIGALRM or alarm() for now.
*/
(void) sigemptyset(&ublk);
doreinit = 0;
(void) xptree_reinitialize();
}
}
}