conf.c revision b03982bd7af59cf0a27cfd2374d7ac59d7f1149c
/*
* 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.
*/
/*
* "pmconfig" performs a mixture of Energy-Star configuration tasks
* for both CheckPoint-Resume and Power-Management services.
* Tasks include parsing a config file (usually "/etc/power.conf"),
* updating CPR and PM config files, and setting various PM options
* via ioctl requests. From the mix, pmconfig should have a more
* generalized name similar to "estarconfig".
*
* OPTIONS:
* "-r" reset CPR and PM options to default and exit.
* "-f file" specify an alternate config file; this is a
* private/non-advertised option used by "dtpower".
*/
#include "pmconfig.h"
#include <signal.h>
#include <stdarg.h>
#include <locale.h>
#include "powerd.h"
static char conf_header[] =
"#\n"
"# Copyright 1996-2002 Sun Microsystems, Inc. All rights reserved.\n"
"# Use is subject to license terms.\n"
"#\n"
"#pragma ident \"@(#)power.conf 2.1 02/03/04 SMI\"\n"
"#\n"
"# Power Management Configuration File\n"
"#\n\n";
static char *prog;
static char *cpr_conf = CPR_CONFIG;
static char orig_conf[] = "/etc/power.conf-Orig";
static char default_conf[] = "/etc/power.conf";
static char *power_conf = default_conf;
static pid_t powerd_pid;
static int tmp_fd;
char estar_vers = ESTAR_VNONE;
int ua_err = 0;
int debug = 0;
int pm_fd;
int def_src;
/*
* Until we get more graphics driver support, we only enable autopm,
* S3 support and autoS3 by default on X86 systems that are on our whitelist.
*/
int whitelist_only = 1;
int verify = 0;
static void
cleanup(void)
{
}
/*
* Multi-purpose message output routine; also exits when
* (status == MEXIT), other status is non-fatal.
* VARARGS2
*/
void
{
/*
* debug is checked once here, avoiding N duplicate checks
* before each MDEBUG caller and unnecessary text dupduplication.
*/
if (debug == 0) {
/*
* If debug is not enabled, skip a debug message;
* lead with the program name for an error message,
* and follow with a filename and line number if an
* error occurs while parsing a conf file.
*/
return;
if (lineno)
}
cleanup();
}
}
static void
usage(void)
{
exit(1);
}
/*
* Lookup estar version, check if uadmin() service is supported,
* and read cpr_config info from disk.
*/
static void
get_cpr_info(void)
{
char *err_fmt;
int fd;
#ifdef sparc
if (estar_vers == ESTAR_V2)
else if (estar_vers == ESTAR_V3)
else
}
#endif /* sparc */
/*
* Read in the cpr conf file. If any open or read error occurs,
* display an error message only for a non-root user. The file
* may not exist on a newly installed system.
*/
err_fmt = "%s %s; please rerun %s as root\n";
if (ruid)
} else {
if (ruid)
else {
}
}
}
}
/*
* Unconfigure and reset PM, device is left open for later use.
*/
static void
pm_rem_reset(void)
{
err_fmt = "cannot reset pm state: %s\n";
if (err_fmt)
}
static void
get_powerd_pid(void)
{
char pidstr[16];
int fd;
return;
}
}
/*
* Write revised cprconfig struct to disk based on perms;
* returns 1 if any error, otherwise 0.
*/
static int
update_cprconfig(void)
{
int fd;
if (rflag) {
/* For "pmconfig -r" case, copy select cpr-related fields. */
}
return (1);
/* save new struct data with old autopm setting */
} else if (!cpr_status.perm) {
return (1);
/* save original struct with new autopm setting */
return (1);
err_fmt = "error writing \"%s\", %s\n";
if (err_fmt)
if (fd != -1)
}
/*
* Signal old powerd when there's a valid pid, or start a new one;
* returns 1 if any error, otherwise 0.
*/
static int
restart_powerd(void)
{
int status = 0;
if (powerd_pid > 0) {
return (0);
return (1);
}
}
wp = -1;
(void) setreuid(0, 0);
(void) setregid(0, 0);
if (debug)
else
exit(1);
} else {
do {
}
if (wp == -1)
}
static void
save_orig(void)
{
int pid;
return;
return;
exit(1);
} else
}
static void
{
}
static void
{
}
/*
* Filter conf lines and write them to the tmp file.
*/
static void
{
int selected;
/*
* Lines from an alt conf file are selected when either:
* cip is NULL (keyword not matched, probably an old-style device),
* OR: it's both OK to accept the conf line (alt) AND either:
* (checkup) matches conftab status.
*/
if (selected)
}
/*
* Set checkup for conf line selection and parse a conf file with filtering.
* When pref is NULL, filter selects all conf lines from the new conf file;
* otherwise filter selects only cpr or pm related lines from the new or
* default conf file based on cpr or pm perm.
*/
static void
{
}
/*
* Search for any non-alt entries, call the handler routine,
* and write entries to the tmp file.
*/
static void
{
int skip;
if (skip)
return;
}
/*
* When perm and update status are OK, write a new conf file
* and rename to default_conf with the original attributes;
* returns 1 if any error, otherwise 0.
*/
static int
write_conf(void)
{
"(cpr perm %d update %d), (pm perm %d update %d)\n",
return (1);
}
save_orig();
return (1);
}
/*
* When both perms are set, save selected lines from the new file;
* otherwise save selected subsets from the new and default files.
*/
else {
}
/*
* "dtpower" will craft an alt conf file with modified content from
* /etc/power.conf, but any alt conf file is not a trusted source;
* since some alt conf lines may be skipped, the trusted source is
* searched for those lines to retain their functionality.
*/
err_str = "stat";
err_str = "chmod";
err_str = "chown";
err_str = "rename";
else
if (err_str)
}
/* ARGSUSED */
int
{
int rval = 0;
(void) textdomain(TEXT_DOMAIN);
usage();
switch (*(*vec + 1)) {
case 'd':
debug = 1;
break;
case 'f':
fflag = 1;
usage();
break;
case 'r':
rflag = 1;
break;
case 'W':
whitelist_only = 0;
break;
case 'v':
verify = 1;
break;
default:
usage();
break;
}
}
usage();
lookup_perms();
get_cpr_info();
pm_rem_reset();
(void) umask(022);
if (rflag)
return (update_cprconfig() || restart_powerd());
if (fflag)
rval = write_conf();
cleanup();
if (rval == 0)
return (rval);
}