#include <stdio.h>
#include <locale.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include "addrem.h"
#include "errmsg.h"
#include "plcysubr.h"
static void usage();
static int unload_drv(char *, int, int);
static int
unload_drv(char *driver_name, int force_flag, int verbose_flag)
{
int modid;
get_modid(driver_name, &modid);
if (modid != -1) {
if (modctl(MODUNLOAD, modid) < 0) {
(void) fprintf(stderr, gettext(ERR_MODUN), driver_name);
if (force_flag == 0) {
if (verbose_flag) {
(void) fprintf(stderr,
gettext(NOUPDATE), driver_name);
}
err_exit();
}
(void) fprintf(stderr, gettext(FORCE_UPDATE),
driver_name);
return (-1);
}
}
return (0);
}
static void
usage()
{
(void) fprintf(stderr, gettext(UPD_DRV_USAGE));
exit(1);
}
int
main(int argc, char *argv[])
{
int error, opt, major;
int cleanup_flag = 0;
int update_conf = 1;
int verbose_flag = 0;
int force_flag = 0;
int a_flag = 0;
int d_flag = 0;
int i_flag = 0;
int l_flag = 0;
int m_flag = 0;
int n_flag = 0;
char *perms = NULL;
char *aliases = NULL;
char *basedir = NULL;
char *policy = NULL;
char *aliases2 = NULL;
char *priv = NULL;
char *driver_name;
int found;
major_t major_num;
int rval;
int config_flags;
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
if (getuid() != 0) {
(void) fprintf(stderr, gettext(ERR_NOT_ROOT));
exit(1);
}
while ((opt = getopt(argc, argv, "m:ni:b:p:adlfuvP:")) != EOF) {
switch (opt) {
case 'a':
a_flag++;
break;
case 'b':
update_conf = 0;
basedir = optarg;
break;
case 'd':
d_flag++;
break;
case 'f':
force_flag++;
break;
case 'i':
i_flag++;
aliases = optarg;
if (check_space_within_quote(aliases) == ERROR) {
(void) fprintf(stderr, gettext(ERR_NO_SPACE),
aliases);
exit(1);
}
break;
case 'l':
l_flag++;
break;
case 'm':
m_flag++;
perms = optarg;
break;
case 'n':
n_flag++;
update_conf = 0;
break;
case 'p':
policy = optarg;
break;
case 'v':
verbose_flag++;
break;
case 'P':
priv = optarg;
break;
case '?' :
default:
usage();
}
}
if ((argv[optind] == NULL) || (optind + 1 != argc)) {
usage();
}
if ((a_flag && d_flag) ||
((a_flag || d_flag) &&
!m_flag && !i_flag && priv == NULL && policy == NULL)) {
usage();
}
if (m_flag || i_flag || policy != NULL || priv != NULL) {
if (!(a_flag || d_flag))
usage();
}
driver_name = argv[optind];
if ((build_filenames(basedir)) == ERROR) {
exit(1);
}
if (l_flag) {
list_entry(minor_perm, driver_name, ":");
return (NOERR);
}
enter_lock();
if ((check_perms_aliases(m_flag, i_flag)) == ERROR) {
err_exit();
}
if ((check_name_to_major(R_OK)) == ERROR)
err_exit();
if ((n_flag == 0) &&
(basedir == NULL || (strcmp(basedir, "/") == 0)) &&
(priv != NULL) && check_priv_entry(priv, a_flag) != 0)
err_exit();
if (policy != NULL && (policy = check_plcy_entry(policy, driver_name,
d_flag ? B_TRUE : B_FALSE)) == NULL)
err_exit();
if (a_flag) {
if (m_flag) {
if ((error = check_perm_opts(perms)) == ERROR) {
if (force_flag == 0) {
exit_unlock();
return (error);
}
}
if ((error != ERROR) &&
(error = update_minor_entry(driver_name, perms))) {
if (force_flag == 0) {
exit_unlock();
return (error);
}
}
cleanup_flag |= CLEAN_NAM_MAJ;
if ((n_flag == 0) &&
(basedir == NULL || (strcmp(basedir, "/") == 0))) {
rval = devfs_add_minor_perm(driver_name,
log_minorperm_error);
if (rval) {
(void) fprintf(stderr,
gettext(ERR_UPDATE_PERM),
driver_name);
}
}
}
if (priv != NULL) {
(void) append_to_file(driver_name, priv, extra_privs,
',', ":", 0);
cleanup_flag |= CLEAN_DRV_PRIV;
}
if (policy != NULL) {
if ((error = update_device_policy(device_policy,
policy, B_TRUE)) != 0) {
exit_unlock();
return (error);
}
cleanup_flag |= CLEAN_DEV_POLICY;
}
if (i_flag) {
found = get_major_no(driver_name, name_to_major);
if (found == ERROR) {
(void) fprintf(stderr, gettext(ERR_MAX_MAJOR),
name_to_major);
err_exit();
}
if (found == UNIQUE) {
(void) fprintf(stderr,
gettext(ERR_NOT_INSTALLED), driver_name);
err_exit();
}
major_num = (major_t)found;
error = trim_duplicate_aliases(driver_name,
aliases, &aliases2);
if (error == ERROR) {
exit_unlock();
return (error);
}
if (aliases2 == NULL)
goto done;
if ((force_flag == 0) && ((error =
aliases_paths_exist(aliases2)) == ERROR)) {
exit_unlock();
return (error);
}
if ((error = update_driver_aliases(driver_name,
aliases2)) == ERROR) {
exit_unlock();
return (error);
}
if (update_conf) {
sync();
config_flags = (verbose_flag) ?
CONFIG_DRV_VERBOSE : 0;
cleanup_flag |= CLEAN_DRV_ALIAS;
if (config_driver(driver_name, major_num,
aliases2, NULL, cleanup_flag,
config_flags) == ERROR) {
err_exit();
}
}
}
done:
if (update_conf && (i_flag || policy != NULL)) {
load_driver(driver_name, verbose_flag);
}
exit_unlock();
return (0);
}
if (d_flag) {
int err = NOERR;
if (m_flag) {
if ((n_flag == 0) &&
(basedir == NULL || (strcmp(basedir, "/") == 0))) {
rval = devfs_rm_minor_perm(driver_name,
log_minorperm_error);
if (rval) {
(void) fprintf(stderr,
gettext(ERR_UPDATE_PERM),
driver_name);
}
}
if ((error = delete_entry(minor_perm,
driver_name, ":", perms)) != NOERR) {
(void) fprintf(stderr, gettext(ERR_NO_ENTRY),
driver_name, minor_perm);
err = error;
}
if ((n_flag == 0) &&
(basedir == NULL || (strcmp(basedir, "/") == 0))) {
rval = devfs_add_minor_perm(driver_name,
log_minorperm_error);
if (rval) {
(void) fprintf(stderr,
gettext(ERR_UPDATE_PERM),
driver_name);
}
}
}
if (i_flag) {
found = get_major_no(driver_name, name_to_major);
if (found == ERROR) {
(void) fprintf(stderr, gettext(ERR_MAX_MAJOR),
name_to_major);
err_exit();
}
if (found == UNIQUE) {
(void) fprintf(stderr,
gettext(ERR_NOT_INSTALLED), driver_name);
err_exit();
}
major_num = (major_t)found;
error = NOERR;
rval = aliases_exist(aliases);
if (rval == ERROR && (force_flag == 0)) {
(void) fprintf(stderr,
gettext(ERR_ALIAS_NOT_BOUND),
driver_name);
if (err != NOERR)
err = rval;
}
if (rval == NOERR)
error = delete_entry(driver_aliases,
driver_name, ":", aliases);
if (error != NOERR && (force_flag == 0)) {
(void) fprintf(stderr, gettext(ERR_NO_ENTRY),
driver_name, driver_aliases);
if (err != NOERR)
err = error;
}
if (err == NOERR && update_conf) {
sync();
config_flags = 0;
if (verbose_flag)
config_flags |= CONFIG_DRV_VERBOSE;
if (force_flag)
config_flags |= CONFIG_DRV_FORCE;
error = unconfig_driver(driver_name, major_num,
aliases, config_flags);
if (error == ERROR && force_flag == 0) {
(void) fprintf(stderr,
gettext(ERR_DEV_IN_USE),
driver_name);
if (err != NOERR)
err = error;
}
}
}
if (priv != NULL) {
if ((error = delete_entry(extra_privs, driver_name, ":",
priv)) != NOERR) {
(void) fprintf(stderr, gettext(ERR_NO_ENTRY),
driver_name, extra_privs);
if (err != NOERR)
err = error;
}
}
if (policy != NULL) {
if ((error = delete_plcy_entry(device_policy,
policy)) != NOERR) {
(void) fprintf(stderr, gettext(ERR_NO_ENTRY),
driver_name, device_policy);
if (err != NOERR)
err = error;
}
}
if (err == NOERR && update_conf) {
if (i_flag || m_flag) {
(void) unload_drv(driver_name,
force_flag, verbose_flag);
}
if (policy != NULL)
load_driver(driver_name, verbose_flag);
}
exit_unlock();
return (err);
}
major = get_major_no(driver_name, name_to_major);
if (major == ERROR) {
err_exit();
}
if (update_conf) {
(void) unload_drv(driver_name, force_flag, verbose_flag);
if ((modctl(MODUNLOADDRVCONF, major) != 0) ||
(modctl(MODLOADDRVCONF, major, 0) != 0)) {
(void) fprintf(stderr, gettext(ERR_DRVCONF),
driver_name);
err_exit();
}
if (verbose_flag) {
(void) fprintf(stderr, gettext(DRVCONF_UPDATED),
driver_name);
}
load_driver(driver_name, verbose_flag);
}
exit_unlock();
return (NOERR);
}