1/* 2 * Copyright (C) 2005-2006 Kay Sievers <kay.sievers@vrfy.org> 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by the 6 * Free Software Foundation version 2 of the License. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write to the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 * 17 */ 18 19#include <time.h> 20#include <errno.h> 21#include <stdio.h> 22#include <stdlib.h> 23#include <stddef.h> 24#include <string.h> 25#include <unistd.h> 26#include <sys/types.h> 27#include <sys/socket.h> 28#include <sys/wait.h> 29#include <sys/un.h> 30 31#include "udev.h" 32#include "udevd.h" 33 34static int sock = -1; 35static int udev_log = 0; 36 37#ifdef USE_LOG 38void log_message (int priority, const char *format, ...) 39{ 40 va_list args; 41 42 if (priority > udev_log) 43 return; 44 45 va_start(args, format); 46 vsyslog(priority, format, args); 47 va_end(args); 48} 49#endif 50 51int main(int argc, char *argv[], char *envp[]) 52{ 53 static struct udevd_ctrl_msg ctrl_msg; 54 struct sockaddr_un saddr; 55 socklen_t addrlen; 56 const char *env; 57 const char *arg; 58 const char *val; 59 int *intval; 60 int retval = 1; 61 62 env = getenv("UDEV_LOG"); 63 if (env) 64 udev_log = log_priority(env); 65 66 logging_init("udevcontrol"); 67 dbg("version %s", UDEV_VERSION); 68 69 if (argc < 2) { 70 fprintf(stderr, "missing command\n\n"); 71 goto exit; 72 } 73 memset(&ctrl_msg, 0x00, sizeof(struct udevd_ctrl_msg)); 74 strcpy(ctrl_msg.magic, UDEVD_CTRL_MAGIC); 75 arg = argv[1]; 76 77 if (!strcmp(arg, "stop_exec_queue")) 78 ctrl_msg.type = UDEVD_CTRL_STOP_EXEC_QUEUE; 79 else if (!strcmp(arg, "start_exec_queue")) 80 ctrl_msg.type = UDEVD_CTRL_START_EXEC_QUEUE; 81 else if (!strcmp(arg, "reload_rules")) 82 ctrl_msg.type = UDEVD_CTRL_RELOAD_RULES; 83 else if (!strncmp(arg, "log_priority=", strlen("log_priority="))) { 84 intval = (int *) ctrl_msg.buf; 85 val = &arg[strlen("log_priority=")]; 86 ctrl_msg.type = UDEVD_CTRL_SET_LOG_LEVEL; 87 *intval = log_priority(val); 88 info("send log_priority=%i", *intval); 89 } else if (!strncmp(arg, "max_childs=", strlen("max_childs="))) { 90 char *endp; 91 int count; 92 93 intval = (int *) ctrl_msg.buf; 94 val = &arg[strlen("max_childs=")]; 95 ctrl_msg.type = UDEVD_CTRL_SET_MAX_CHILDS; 96 count = strtoul(val, &endp, 0); 97 if (endp[0] != '\0' || count < 1) { 98 fprintf(stderr, "invalid number\n"); 99 goto exit; 100 } 101 *intval = count; 102 info("send max_childs=%i", *intval); 103 } else if (!strncmp(arg, "max_childs_running=", strlen("max_childs_running="))) { 104 char *endp; 105 int count; 106 107 intval = (int *) ctrl_msg.buf; 108 val = &arg[strlen("max_childs_running=")]; 109 ctrl_msg.type = UDEVD_CTRL_SET_MAX_CHILDS_RUNNING; 110 count = strtoul(val, &endp, 0); 111 if (endp[0] != '\0' || count < 1) { 112 fprintf(stderr, "invalid number\n"); 113 goto exit; 114 } 115 *intval = count; 116 info("send max_childs_running=%i", *intval); 117 } else if (!strncmp(arg, "env", strlen("env"))) { 118 val = argv[2]; 119 if (val == NULL) { 120 fprintf(stderr, "missing key\n"); 121 goto exit; 122 } 123 ctrl_msg.type = UDEVD_CTRL_ENV; 124 strlcpy(ctrl_msg.buf, val, sizeof(ctrl_msg.buf)); 125 info("send env '%s'", val); 126 } else if (strcmp(arg, "help") == 0 || strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) { 127 printf("Usage: udevcontrol COMMAND\n" 128 " log_priority=<level> set the udev log level for the daemon\n" 129 " stop_exec_queue keep udevd from executing events, queue only\n" 130 " start_exec_queue execute events, flush queue\n" 131 " reload_rules reloads the rules files\n" 132 " env <var>=<value> set a global environment variable\n" 133 " max_childs=<N> maximum number of childs\n" 134 " max_childs_running=<N> maximum number of childs running at the same time\n" 135 " help print this help text\n\n"); 136 goto exit; 137 } else { 138 fprintf(stderr, "unrecognized command '%s'\n", arg); 139 goto exit; 140 } 141 142 if (getuid() != 0) { 143 fprintf(stderr, "root privileges required\n"); 144 goto exit; 145 } 146 147 sock = socket(AF_LOCAL, SOCK_DGRAM, 0); 148 if (sock == -1) { 149 err("error getting socket: %s", strerror(errno)); 150 goto exit; 151 } 152 153 memset(&saddr, 0x00, sizeof(struct sockaddr_un)); 154 saddr.sun_family = AF_LOCAL; 155 /* use abstract namespace for socket path */ 156 strcpy(&saddr.sun_path[1], UDEVD_CTRL_SOCK_PATH); 157 addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1; 158 159 retval = sendto(sock, &ctrl_msg, sizeof(ctrl_msg), 0, (struct sockaddr *)&saddr, addrlen); 160 if (retval == -1) { 161 err("error sending message: %s", strerror(errno)); 162 retval = 1; 163 } else { 164 dbg("sent message type=0x%02x, %u bytes sent", ctrl_msg.type, retval); 165 retval = 0; 166 } 167 168 close(sock); 169exit: 170 logging_close(); 171 return retval; 172} 173