udev-event.c revision 07630cea1f3a845c09309f197ac7c4f11edd3b62
/*
* Copyright (C) 2003-2013 Kay Sievers <kay@vrfy.org>
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/signalfd.h>
#include <unistd.h>
#include "event-util.h"
#include "formats-util.h"
#include "netlink-util.h"
#include "process-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "udev.h"
typedef struct Spawn {
const char *cmd;
bool accept_failure;
} Spawn;
struct udev_event *event;
return NULL;
return event;
}
return;
}
size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size) {
enum subst_type {
};
static const struct subst_map {
const char *name;
const char fmt;
enum subst_type type;
} map[] = {
};
const char *from;
char *s;
size_t l;
s = dest;
l = size;
for (;;) {
char attrbuf[UTIL_PATH_SIZE];
while (from[0] != '\0') {
if (from[0] == '$') {
/* substitute named variable */
unsigned int i;
from++;
goto copy;
}
for (i = 0; i < ELEMENTSOF(map); i++) {
goto subst;
}
}
} else if (from[0] == '%') {
/* substitute format char */
unsigned int i;
from++;
goto copy;
}
for (i = 0; i < ELEMENTSOF(map); i++) {
from += 2;
goto subst;
}
}
}
copy:
/* copy char */
if (l == 0)
goto out;
s[0] = from[0];
from++;
s++;
l--;
}
goto out;
/* extract possible $format{attr} */
if (from[0] == '{') {
unsigned int i;
from++;
for (i = 0; from[i] != '}'; i++) {
if (from[i] == '\0') {
goto out;
}
}
if (i >= sizeof(attrbuf))
goto out;
attrbuf[i] = '\0';
from += i+1;
} else {
}
switch (type) {
case SUBST_DEVPATH:
break;
case SUBST_KERNEL:
break;
case SUBST_KERNEL_NUMBER:
break;
break;
case SUBST_ID:
break;
break;
case SUBST_DRIVER: {
const char *driver;
break;
break;
break;
}
case SUBST_MAJOR: {
char num[UTIL_PATH_SIZE];
break;
}
case SUBST_MINOR: {
char num[UTIL_PATH_SIZE];
break;
}
case SUBST_RESULT: {
char *rest;
int i;
break;
/* get part part of the result string */
i = 0;
if (i > 0) {
char result[UTIL_PATH_SIZE];
char tmp[UTIL_PATH_SIZE];
char *cpos;
while (--i) {
cpos++;
cpos++;
if (cpos[0] == '\0')
break;
}
if (i > 0) {
log_error("requested part of result string not found");
break;
}
/* %{2+}c copies the whole string from the second part on */
if (rest[0] != '+') {
if (cpos)
cpos[0] = '\0';
}
} else {
}
break;
}
case SUBST_ATTR: {
char vbuf[UTIL_NAME_SIZE];
int count;
log_error("missing file parameter for attr");
break;
}
/* try to read the attribute the device */
/* try to read the attribute of the parent device, other matches have selected */
break;
/* strip trailing whitespace, and replace unwanted characters */
if (count > 0)
break;
}
case SUBST_PARENT: {
struct udev_device *dev_parent;
const char *devnode;
if (dev_parent == NULL)
break;
break;
}
case SUBST_DEVNODE:
break;
case SUBST_NAME:
else
break;
case SUBST_LINKS: {
struct udev_list_entry *list_entry;
if (list_entry == NULL)
break;
break;
}
case SUBST_ROOT:
l = strpcpy(&s, l, "/dev");
break;
case SUBST_SYS:
l = strpcpy(&s, l, "/sys");
break;
case SUBST_ENV:
break;
} else {
const char *value;
break;
break;
}
default:
break;
}
}
out:
s[0] = '\0';
return l;
}
int r;
/* discard child output or connect to pipe */
if (fd >= 0) {
if (r < 0)
if (fd_stdout < 0) {
if (r < 0)
}
if (fd_stderr < 0) {
if (r < 0)
}
} else
/* connect pipes to std{out,err} */
if (fd_stdout >= 0) {
if (r < 0)
}
if (fd_stderr >= 0) {
if (r < 0)
}
/* terminate child in case parent goes away */
/* restore sigmask before exec */
(void) reset_signal_mask();
/* exec failed */
return -errno;
}
const char *cmd,
struct epoll_event ep_outpipe = {
};
struct epoll_event ep_errpipe = {
};
int r;
/* read from child if requested */
return;
if (fd_ep < 0) {
return;
}
if (fd_stdout >= 0) {
if (r < 0) {
return;
}
}
if (fd_stderr >= 0) {
if (r < 0) {
return;
}
}
/* read child output */
int timeout;
int fdcount;
int i;
if (timeout_usec > 0) {
if (age_usec >= timeout_usec) {
return;
}
} else {
timeout = -1;
}
if (fdcount < 0) {
continue;
return;
} else if (fdcount == 0) {
return;
}
for (i = 0; i < fdcount; i++) {
if (*fd < 0)
continue;
char buf[4096];
if (count <= 0)
continue;
/* store stdout result */
} else {
}
}
/* log debug output only if we watch stderr */
if (fd_stderr >= 0) {
char *pos;
char *line;
}
}
if (r < 0) {
return;
}
*fd = -1;
}
}
}
/* return the child's stdout string */
}
return 1;
}
log_warning("spawned process '%s' ["PID_FMT"] is taking longer than %s to complete", spawn->cmd, spawn->pid,
return 1;
}
case CLD_EXITED:
return 1;
} else if (spawn->accept_failure)
else
break;
case CLD_KILLED:
case CLD_DUMPED:
break;
default:
}
return 1;
}
bool accept_failure) {
};
int r, ret;
r = sd_event_new(&e);
if (r < 0)
return r;
if (timeout_usec > 0) {
if (age_usec < timeout_usec) {
if (r < 0)
return r;
}
if (r < 0)
return r;
}
}
if (r < 0)
return r;
r = sd_event_loop(e);
if (r < 0)
return r;
r = sd_event_get_exit_code(e, &ret);
if (r < 0)
return r;
return ret;
}
int i = 0;
char *pos;
goto out;
}
if (pos[0] == '\'') {
/* do not separate quotes */
pos++;
while (pos[0] == ' ')
pos++;
} else {
while (pos[0] == ' ')
pos++;
}
i++;
}
out:
if (argc)
*argc = i;
return 0;
}
bool accept_failure,
const char *cmd,
int err = 0;
/* pipes from child to parent */
goto out;
}
}
if (log_get_max_level() >= LOG_INFO) {
goto out;
}
}
switch(pid) {
case 0:
{
char arg[UTIL_PATH_SIZE];
char *argv[128];
char program[UTIL_PATH_SIZE];
/* child closes parent's ends of pipes */
if (argv[0][0] != '/') {
}
_exit(2);
}
case -1:
err = -1;
goto out;
default:
/* parent closed child's ends of pipes */
cmd,
}
out:
return err;
}
const char *oldname;
int r;
if (r < 0)
return 0;
}
struct udev_list *properties_list,
struct udev_rules *rules) {
return;
} else {
/* disable watch during event processing */
}
/* rename a new network interface, if needed */
int r;
r = rename_netif(event);
if (r < 0)
log_warning_errno(r, "could not rename interface '%d' from '%s' to '%s': %m", udev_device_get_ifindex(dev),
else {
if (r < 0)
log_warning_errno(r, "renamed interface '%d' from '%s' to '%s', but could not update udev_device: %m",
else
}
}
bool apply;
if (udev_device_get_devnode_mode(dev) > 0) {
/* kernel supplied value */
/* default 0660 if a group is assigned */
} else {
/* default 0600 */
}
}
apply = streq(udev_device_get_action(dev), "add") || event->owner_set || event->group_set || event->mode_set;
}
/* preserve old, or get new initialization timestamp */
/* (re)write database file */
}
}
void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec) {
struct udev_list_entry *list_entry;
char command[UTIL_PATH_SIZE];
if (builtin_cmd < UDEV_BUILTIN_MAX)
else {
if (event->exec_delay > 0) {
}
}
}
}