/* vi: set sw=4 ts=4: */
/*
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
/*
The postal address is:
Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
*/
+
+//usage:#define devfsd_trivial_usage
+//usage: "mntpnt [-v]" IF_DEVFSD_FG_NP("[-fg][-np]")
+//usage:#define devfsd_full_usage "\n\n"
+//usage: "Manage devfs permissions and old device name symlinks\n"
+//usage: "\n mntpnt The mount point where devfs is mounted"
+//usage: "\n -v Print the protocol version numbers for devfsd"
+//usage: "\n and the kernel-side protocol version and exit"
+//usage: IF_DEVFSD_FG_NP(
+//usage: "\n -fg Run in foreground"
+//usage: "\n -np Exit after parsing the configuration file"
+//usage: "\n and processing synthetic REGISTER events,"
+//usage: "\n don't poll for events"
+//usage: )
+
#include "libbb.h"
#include "xregex.h"
#include <syslog.h>
/* Various defines taken from linux/devfs_fs.h */
#define DEVFSD_PROTOCOL_REVISION_KERNEL 5
-#define DEVFSD_IOCTL_BASE 'd'
+#define DEVFSD_IOCTL_BASE 'd'
/* These are the various ioctls */
#define DEVFSDIOC_GET_PROTO_REV _IOR(DEVFSD_IOCTL_BASE, 0, int)
#define DEVFSDIOC_SET_EVENT_MASK _IOW(DEVFSD_IOCTL_BASE, 2, int)
const regmatch_t *, unsigned);
static void action_modload(const struct devfsd_notify_struct *info, const struct config_entry_struct *entry);
static void action_copy(const struct devfsd_notify_struct *, const struct config_entry_struct *,
- const regmatch_t *, unsigned);
+ const regmatch_t *, unsigned);
static void action_compat(const struct devfsd_notify_struct *, unsigned);
static void free_config(void);
static void restore(char *spath, struct stat source_stat, int rootlen);
static const char *get_variable(const char *, void *);
static int make_dir_tree(const char *);
static int expand_expression(char *, unsigned, const char *, const char *(*)(const char *, void *), void *,
- const char *, const regmatch_t *, unsigned);
+ const char *, const regmatch_t *, unsigned);
static void expand_regexp(char *, size_t, const char *, const char *, const regmatch_t *, unsigned);
static const char *expand_variable( char *, unsigned, unsigned *, const char *,
const char *(*)(const char *, void *), void *);
static const char *get_variable_v2(const char *, const char *(*)(const char *, void *), void *);
-static char get_old_ide_name(unsigned , unsigned);
+static char get_old_ide_name(unsigned, unsigned);
static char *write_old_sd_name(char *, unsigned, unsigned, const char *);
/* busybox functions */
/*This action will pass "/dev/$devname"(i.e. "/dev/" prefixed to
the device name) to the module loading facility. In addition,
the /etc/modules.devfs configuration file is used.*/
- if (ENABLE_DEVFSD_MODLOAD)
+ if (ENABLE_DEVFSD_MODLOAD)
new->action.what = AC_MODLOAD;
- break;
+ break;
case 6: /* EXECUTE */
new->action.what = AC_EXECUTE;
num_args -= 3;
xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, (void*)event_mask);
while (!caught_signal) {
errno = 0;
- bytes = read(fd,(char *) &info, sizeof info);
+ bytes = read(fd, (char *) &info, sizeof info);
if (caught_signal)
break; /* Must test for this first */
if (errno == EINTR)
} /* End Function action_permissions */
static void action_modload(const struct devfsd_notify_struct *info,
- const struct config_entry_struct *entry UNUSED_PARAM)
+ const struct config_entry_struct *entry UNUSED_PARAM)
/* [SUMMARY] Load a module.
<info> The devfs change.
<entry> The config file entry.
argv[4] = concat_path_file("/dev", info->devname); /* device */
argv[5] = NULL;
- wait4pid(xspawn(argv));
+ spawn_and_wait(argv);
free(argv[4]);
} /* End Function action_modload */
static void action_execute(const struct devfsd_notify_struct *info,
- const struct config_entry_struct *entry,
- const regmatch_t *regexpr, unsigned int numexpr)
+ const struct config_entry_struct *entry,
+ const regmatch_t *regexpr, unsigned int numexpr)
/* [SUMMARY] Execute a programme.
<info> The devfs change.
<entry> The config file entry.
argv[count] = largv[count];
}
argv[count] = NULL;
- wait4pid(spawn(argv));
+ spawn_and_wait(argv);
} /* End Function action_execute */
static void action_copy(const struct devfsd_notify_struct *info,
- const struct config_entry_struct *entry,
- const regmatch_t *regexpr, unsigned int numexpr)
+ const struct config_entry_struct *entry,
+ const regmatch_t *regexpr, unsigned int numexpr)
/* [SUMMARY] Copy permissions.
<info> The devfs change.
<entry> The config file entry.
lstat(dpath, &dest_stat);
free(dpath);
if (S_ISLNK(source_stat.st_mode) || (source_stat.st_mode & S_ISVTX))
- copy_inode(dpath, &dest_stat,(source_stat.st_mode & ~S_ISVTX) , spath, &source_stat);
+ copy_inode(dpath, &dest_stat, (source_stat.st_mode & ~S_ISVTX), spath, &source_stat);
if (S_ISDIR(source_stat.st_mode))
- dir_operation(RESTORE, spath, rootlen,NULL);
+ dir_operation(RESTORE, spath, rootlen, NULL);
}
break;
un_addr.sun_family = AF_UNIX;
snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s", destpath);
- val = bind(fd,(struct sockaddr *) &un_addr,(int) sizeof un_addr);
+ val = bind(fd, (struct sockaddr *) &un_addr, (int) sizeof un_addr);
close(fd);
if (val != 0 || chmod(destpath, new_mode & ~S_IFMT) != 0)
break;
{
struct passwd *pw_ent;
struct group *grp_ent;
- static const char *msg;
-
- if (ENABLE_DEVFSD_VERBOSE)
- msg = "user";
+ const char *msg;
- if (isdigit(string[0]) ||((string[0] == '-') && isdigit(string[1])))
+ if (isdigit(string[0]) || ((string[0] == '-') && isdigit(string[1])))
return atoi(string);
if (flag == UID && (pw_ent = getpwnam(string)) != NULL)
return pw_ent->pw_uid;
- if (flag == GID && (grp_ent = getgrnam(string)) != NULL)
- return grp_ent->gr_gid;
- else if (ENABLE_DEVFSD_VERBOSE)
- msg = "group";
+ if (ENABLE_DEVFSD_VERBOSE)
+ msg = "user";
+
+ if (flag == GID) {
+ if ((grp_ent = getgrnam(string)) != NULL)
+ return grp_ent->gr_gid;
+ if (ENABLE_DEVFSD_VERBOSE)
+ msg = "group";
+ }
if (ENABLE_DEVFSD_VERBOSE)
msg_logger(LOG_ERR, "unknown %s: %s, defaulting to %cid=0", msg, string, msg[0]);
static const char *get_variable(const char *variable, void *info)
{
- static char sbuf[sizeof(int)*3 + 2]; /* sign and NUL */
static char *hostname;
struct get_variable_info *gv_info = info;
const char *field_names[] = {
- "hostname", "mntpt", "devpath", "devname",
- "uid", "gid", "mode", hostname, mount_point,
- gv_info->devpath, gv_info->devname, NULL
+ "hostname", "mntpt", "devpath", "devname", "uid", "gid", "mode",
+ NULL, mount_point, gv_info->devpath, gv_info->devname, NULL
};
int i;
if (!hostname)
hostname = safe_gethostname();
+ field_names[7] = hostname;
+
/* index_in_str_array returns i>=0 */
i = index_in_str_array(field_names, variable);
return field_names[i + 7];
if (i == 4)
- sprintf(sbuf, "%u", gv_info->info->uid);
- else if (i == 5)
- sprintf(sbuf, "%u", gv_info->info->gid);
- else if (i == 6)
- sprintf(sbuf, "%o", gv_info->info->mode);
- return sbuf;
+ return auto_string(xasprintf("%u", gv_info->info->uid));
+ if (i == 5)
+ return auto_string(xasprintf("%u", gv_info->info->gid));
+ /* i == 6 */
+ return auto_string(xasprintf("%o", gv_info->info->mode));
} /* End Function get_variable */
static void service(struct stat statbuf, char *path)
} /* End Function make_dir_tree */
static int expand_expression(char *output, unsigned int outsize,
- const char *input,
- const char *(*get_variable_func)(const char *variable, void *info),
- void *info,
- const char *devname,
- const regmatch_t *ex, unsigned int numexp)
+ const char *input,
+ const char *(*get_variable_func)(const char *variable, void *info),
+ void *info,
+ const char *devname,
+ const regmatch_t *ex, unsigned int numexp)
/* [SUMMARY] Expand environment variables and regular subexpressions in string.
<output> The output expanded expression is written here.
<length> The size of the output buffer.
} /* End Function expand_expression */
static void expand_regexp(char *output, size_t outsize, const char *input,
- const char *devname,
- const regmatch_t *ex, unsigned int numex)
+ const char *devname,
+ const regmatch_t *ex, unsigned int numex)
/* [SUMMARY] Expand all occurrences of the regular subexpressions \0 to \9.
<output> The output expanded expression is written here.
<outsize> The size of the output buffer.
};
const char *get_old_name(const char *devname, unsigned int namelen,
- char *buffer, unsigned int major, unsigned int minor)
+ char *buffer, unsigned int major, unsigned int minor)
/* [SUMMARY] Translate a kernel-supplied name into an old name.
<devname> The device name provided by the kernel.
<namelen> The length of the name.
int indexx;
const char *pty1;
const char *pty2;
- size_t len;
/* 1 to 5 "scsi/" , 6 to 9 "ide/host", 10 sbp/, 11 vcc/, 12 pty/ */
static const char *const fmt[] = {
NULL ,
};
for (trans = translate_table; trans->match != NULL; ++trans) {
- len = strlen(trans->match);
-
- if (strncmp(devname, trans->match, len) == 0) {
+ char *after_match = is_prefixed_with(devname, trans->match);
+ if (after_match) {
if (trans->format == NULL)
- return devname + len;
- sprintf(buffer, trans->format, devname + len);
+ return after_match;
+ sprintf(buffer, trans->format, after_match);
return buffer;
}
}
/* 2 ==scsi/disc, 4 == scsi/part */
if (i == 2 || i == 4)
- compat_name = write_old_sd_name(buffer, major, minor,((i == 2) ? "" : (ptr + 4)));
+ compat_name = write_old_sd_name(buffer, major, minor, ((i == 2) ? "" : (ptr + 4)));
/* 5 == scsi/mt */
if (i == 5) {
/*EXPERIMENTAL_FUNCTION*/
int st_expr_expand(char *output, unsigned int length, const char *input,
- const char *(*get_variable_func)(const char *variable,
- void *info),
- void *info)
+ const char *(*get_variable_func)(const char *variable,
+ void *info),
+ void *info)
/* [SUMMARY] Expand an expression using Borne Shell-like unquoted rules.
<output> The output expanded expression is written here.
<length> The size of the output buffer.
/* Private functions follow */
static const char *expand_variable(char *buffer, unsigned int length,
- unsigned int *out_pos, const char *input,
- const char *(*func)(const char *variable,
- void *info),
- void *info)
+ unsigned int *out_pos, const char *input,
+ const char *(*func)(const char *variable,
+ void *info),
+ void *info)
/* [SUMMARY] Expand a variable.
<buffer> The buffer to write to.
<length> The length of the output buffer.
ch = input[0];
if (ch == '$') {
/* Special case for "$$": PID */
- sprintf(tmp, "%d",(int) getpid());
+ sprintf(tmp, "%d", (int) getpid());
len = strlen(tmp);
if (len + *out_pos >= length)
goto expand_variable_out;
static const char *get_variable_v2(const char *variable,
- const char *(*func)(const char *variable, void *info),
- void *info)
+ const char *(*func)(const char *variable, void *info),
+ void *info)
/* [SUMMARY] Get a variable from the environment or .
<variable> The variable name.
<func> A function which will be used to get the variable. If this returns