mirror of
https://github.com/systemd/systemd.git
synced 2024-11-06 08:26:52 +03:00
e5a2989efb
here is a patch on top of your nice improvements. I fixed the whitespace and it hopefully fixes the stupid timestamp bug in udevd. Some stupid OS sets the hwclock to localtime and linux changes it to UTC while starting. If any events are pending they may be delayed by the users time distance from UTC :) So we use the uptime seconds now.
202 lines
4.2 KiB
C
202 lines
4.2 KiB
C
/*
|
|
* udevsend.c
|
|
*
|
|
* Userspace devfs
|
|
*
|
|
* Copyright (C) 2004 Ling, Xiaofeng <xiaofeng.ling@intel.com>
|
|
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation version 2 of the License.
|
|
*
|
|
* 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, write to the Free Software Foundation, Inc.,
|
|
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/un.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <linux/stddef.h>
|
|
|
|
#include "udev.h"
|
|
#include "udev_lib.h"
|
|
#include "udev_version.h"
|
|
#include "udevd.h"
|
|
#include "logging.h"
|
|
|
|
#ifdef LOG
|
|
unsigned char logname[LOGNAME_SIZE];
|
|
void log_message (int level, const char *format, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsyslog(level, format, args);
|
|
va_end(args);
|
|
}
|
|
#endif
|
|
|
|
static void build_hotplugmsg(struct hotplug_msg *msg, char *action,
|
|
char *devpath, char *subsystem, int seqnum)
|
|
{
|
|
memset(msg, 0x00, sizeof(struct hotplug_msg));
|
|
strfieldcpy(msg->magic, UDEV_MAGIC);
|
|
msg->seqnum = seqnum;
|
|
strfieldcpy(msg->action, action);
|
|
strfieldcpy(msg->devpath, devpath);
|
|
strfieldcpy(msg->subsystem, subsystem);
|
|
}
|
|
|
|
static int start_daemon(void)
|
|
{
|
|
pid_t pid;
|
|
pid_t child_pid;
|
|
|
|
pid = fork();
|
|
switch (pid) {
|
|
case 0:
|
|
/* helper child */
|
|
child_pid = fork();
|
|
switch (child_pid) {
|
|
case 0:
|
|
/* daemon */
|
|
setsid();
|
|
chdir("/");
|
|
execl(UDEVD_BIN, "udevd", NULL);
|
|
dbg("exec of daemon failed");
|
|
exit(1);
|
|
case -1:
|
|
dbg("fork of daemon failed");
|
|
return -1;
|
|
default:
|
|
exit(0);
|
|
}
|
|
break;
|
|
case -1:
|
|
dbg("fork of helper failed");
|
|
return -1;
|
|
default:
|
|
wait(NULL);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
struct hotplug_msg msg;
|
|
char *action;
|
|
char *devpath;
|
|
char *subsystem;
|
|
char *seqnum;
|
|
int seq;
|
|
int retval = 1;
|
|
int loop;
|
|
struct timespec tspec;
|
|
int sock;
|
|
struct sockaddr_un saddr;
|
|
socklen_t addrlen;
|
|
int started_daemon = 0;
|
|
|
|
#ifdef DEBUG
|
|
init_logging("udevsend");
|
|
#endif
|
|
dbg("version %s", UDEV_VERSION);
|
|
|
|
subsystem = get_subsystem(argv[1]);
|
|
if (subsystem == NULL) {
|
|
dbg("no subsystem");
|
|
goto exit;
|
|
}
|
|
dbg("subsystem = '%s'", subsystem);
|
|
|
|
devpath = get_devpath();
|
|
if (devpath == NULL) {
|
|
dbg("no devpath");
|
|
goto exit;
|
|
}
|
|
dbg("DEVPATH = '%s'", devpath);
|
|
|
|
action = get_action();
|
|
if (action == NULL) {
|
|
dbg("no action");
|
|
goto exit;
|
|
}
|
|
dbg("ACTION = '%s'", action);
|
|
|
|
seqnum = get_seqnum();
|
|
if (seqnum == NULL)
|
|
seq = -1;
|
|
else
|
|
seq = atoi(seqnum);
|
|
dbg("SEQNUM = '%d'", seq);
|
|
|
|
sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
|
|
if (sock == -1) {
|
|
dbg("error getting socket");
|
|
goto exit;
|
|
}
|
|
|
|
memset(&saddr, 0x00, sizeof(struct sockaddr_un));
|
|
saddr.sun_family = AF_LOCAL;
|
|
/* use abstract namespace for socket path */
|
|
strcpy(&saddr.sun_path[1], UDEVD_SOCK_PATH);
|
|
addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
|
|
|
|
build_hotplugmsg(&msg, action, devpath, subsystem, seq);
|
|
|
|
/* If we can't send, try to start daemon and resend message */
|
|
loop = UDEVSEND_CONNECT_RETRY;
|
|
while (loop--) {
|
|
retval = sendto(sock, &msg, sizeof(struct hotplug_msg), 0,
|
|
(struct sockaddr *)&saddr, addrlen);
|
|
if (retval != -1) {
|
|
retval = 0;
|
|
goto close_and_exit;
|
|
}
|
|
|
|
if (errno != ECONNREFUSED) {
|
|
dbg("error sending message");
|
|
goto close_and_exit;
|
|
}
|
|
|
|
if (!started_daemon) {
|
|
dbg("connect failed, try starting daemon...");
|
|
retval = start_daemon();
|
|
if (retval) {
|
|
dbg("error starting daemon");
|
|
goto exit;
|
|
}
|
|
|
|
dbg("daemon started");
|
|
started_daemon = 1;
|
|
} else {
|
|
dbg("retry to connect %d", UDEVSEND_CONNECT_RETRY - loop);
|
|
tspec.tv_sec = 0;
|
|
tspec.tv_nsec = 100000000; /* 100 millisec */
|
|
nanosleep(&tspec, NULL);
|
|
}
|
|
}
|
|
|
|
close_and_exit:
|
|
close(sock);
|
|
exit:
|
|
return retval;
|
|
}
|