Remove building with NOCRYPTO option
[minix3.git] / minix / commands / devmand / main.c
blobb22cc5dc38a96e0e6503dcd136176cc7940369db
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <getopt.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <lib.h>
7 #include <sys/stat.h>
8 #include <dirent.h>
9 #include <assert.h>
10 #include <signal.h>
11 #include <minix/dmap.h>
12 #include <minix/paths.h>
13 #include "usb_driver.h"
14 #include "proto.h"
16 #define DEVMAN_TYPE_NAME "dev_type"
17 #define PATH_LEN 256
18 #define INVAL_MAJOR -1
19 #define MAX_CONFIG_DIRS 4
21 static void main_loop();
22 static void handle_event();
23 static void cleanup();
24 static void parse_config();
25 static void display_usage();
26 static enum dev_type determine_type(char *path);
27 static int get_major();
28 static void create_pid_file();
29 static void put_major(int major);
30 static struct devmand_usb_driver* match_usb_driver(struct usb_device_id *id);
31 static struct devmand_driver_instance *find_instance(int dev_id);
33 #define dbg(fmt, ... ) \
34 if (args.verbose) \
35 printf("%8s:%4d: %13s()| "fmt"\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__ )
37 static LIST_HEAD(usb_driver_head, devmand_usb_driver) drivers =
38 LIST_HEAD_INITIALIZER(drivers);
39 static LIST_HEAD(usb_driver_inst_head, devmand_driver_instance) instances =
40 LIST_HEAD_INITIALIZER(instances);
43 static int _run = 1;
44 struct global_args {
45 char *path;
46 char *config_dirs[MAX_CONFIG_DIRS];
47 int config_dir_count ;
48 int major_offset;
49 int verbose;
50 int check_config;
53 enum dev_type {
54 DEV_TYPE_USB_DEVICE,
55 DEV_TYPE_USB_INTF,
56 DEV_TYPE_UNKOWN
59 extern FILE *yyin;
61 static struct global_args args = {
62 .path = NULL,
63 .config_dirs = {NULL,NULL,NULL,NULL},
64 .config_dir_count = 0,
65 .major_offset = USB_BASE_MAJOR,
66 .verbose = 0,
67 .check_config = 0};
69 static struct option options[] =
71 {"dir" , required_argument, NULL, 'd'},
72 {"path", required_argument, NULL, 'p'},
73 {"verbose", required_argument, NULL, 'v'},
74 {"check-config", no_argument, NULL, 'x'},
75 {0,0,0,0} /* terminating entry */
78 static char major_bitmap[16]; /* can store up to 128 major number states */
81 /*===========================================================================*
82 * run_upscript *
83 *===========================================================================*/
84 int run_upscript(struct devmand_driver_instance *inst)
86 char cmdl[1024];
87 cmdl[0] = 0;
88 int ret;
90 assert(inst->drv->upscript);
91 assert(inst->label);
93 snprintf(cmdl, 1024, "%s up %s %d %d",
94 inst->drv->upscript, inst->label, inst->major, inst->dev_id);
95 dbg("Running Upscript: \"%s\"", cmdl);
96 ret = system(cmdl);
97 if (ret != 0) {
98 return EINVAL;
100 return 0;
103 /*===========================================================================*
104 * run_cleanscript *
105 *===========================================================================*/
106 int run_cleanscript(struct devmand_usb_driver *drv)
108 char cmdl[1024];
109 cmdl[0] = 0;
110 int ret;
112 assert(drv->upscript);
113 assert(drv->devprefix);
115 snprintf(cmdl, 1024, "%s clean %s ",
116 drv->upscript, drv->devprefix);
117 dbg("Running Upscript: \"%s\"", cmdl);
118 ret = system(cmdl);
120 if (ret != 0) {
121 return EINVAL;
124 return 0;
128 /*===========================================================================*
129 * run_downscript *
130 *===========================================================================*/
131 int run_downscript(struct devmand_driver_instance *inst)
133 char cmdl[1024];
134 cmdl[0] = 0;
135 int ret;
137 assert(inst->drv->downscript);
138 assert(inst->label);
140 snprintf(cmdl, 1024, "%s down %s %d",
141 inst->drv->downscript, inst->label, inst->major);
143 dbg("Running Upscript: \"%s\"", cmdl);
145 ret = system(cmdl);
147 if (ret != 0) {
148 return EINVAL;
151 return 0;
155 /*===========================================================================*
156 * stop_driver *
157 *===========================================================================*/
158 int stop_driver(struct devmand_driver_instance *inst)
160 char cmdl[1024];
161 cmdl[0] = 0;
162 int ret;
164 assert(inst->label);
166 snprintf(cmdl, 1024, "%s down %s %d",
167 _PATH_MINIX_SERVICE, inst->label, inst->dev_id);
168 dbg("executing minix-service: \"%s\"", cmdl);
169 ret = system(cmdl);
170 if (ret != 0)
172 return EINVAL;
174 printf("Stopped driver %s with label %s for device %d.\n",
175 inst->drv->binary, inst->label, inst->dev_id);
177 return 0;
181 /*===========================================================================*
182 * start_driver *
183 *===========================================================================*/
184 int start_driver(struct devmand_driver_instance *inst)
186 char cmdl[1024];
187 cmdl[0] = 0;
188 int ret;
190 /* generate label */
191 ret = snprintf(inst->label, 32, "%s%d", inst->drv->devprefix,
192 inst->dev_id);
193 if (ret < 0 || ret > DEVMAND_DRIVER_LABEL_LEN) {
194 dbg("label too long");
195 return ENOMEM;
198 assert(inst->drv->binary);
199 assert(inst->label);
201 snprintf(cmdl, 1024, "%s up %s -major %d -devid %d -label %s",
202 _PATH_MINIX_SERVICE, inst->drv->binary, inst->major, inst->dev_id,
203 inst->label);
204 dbg("executing minix-service: \"%s\"", cmdl);
206 ret = system(cmdl);
208 if (ret != 0) {
209 return EINVAL;
212 printf("Started driver %s with label %s for device %d.\n",
213 inst->drv->binary, inst->label, inst->dev_id);
215 return 0;
218 /*===========================================================================*
219 * find_instance *
220 *===========================================================================*/
221 static struct devmand_driver_instance *
222 find_instance(int dev_id)
224 struct devmand_driver_instance *inst;
226 LIST_FOREACH(inst, &instances, list) {
227 if (inst->dev_id == dev_id) {
228 return inst;
231 return NULL;
234 /*===========================================================================*
235 * match_usb_driver *
236 *===========================================================================*/
237 static int
238 match_usb_id(struct devmand_usb_match_id *mid, struct usb_device_id *id)
240 int res = 1;
241 unsigned long match = mid->match_flags;
242 struct usb_device_id *_id = &mid->match_id;
244 if (match & USB_MATCH_ID_VENDOR)
245 if (id->idVendor != _id->idVendor) res = 0;
246 if (match & USB_MATCH_ID_PRODUCT)
247 if (id->idProduct != _id->idProduct) res = 0;
248 if (match & USB_MATCH_BCD_DEVICE)
249 if (id->bcdDevice != _id->bcdDevice) res = 0;
250 if (match & USB_MATCH_DEVICE_PROTOCOL)
251 if (id->bDeviceProtocol != _id->bDeviceProtocol) res = 0;
252 if (match & USB_MATCH_DEVICE_SUBCLASS)
253 if (id->bDeviceSubClass != _id->bDeviceSubClass) res = 0;
254 if (match & USB_MATCH_DEVICE_PROTOCOL)
255 if (id->bDeviceProtocol != _id->bDeviceProtocol) res = 0;
256 if (match & USB_MATCH_INTERFACE_CLASS)
257 if (id->bInterfaceClass != _id->bInterfaceClass) res = 0;
258 if (match & USB_MATCH_INTERFACE_SUBCLASS)
259 if (id->bInterfaceSubClass != _id->bInterfaceSubClass) res = 0;
260 if (match & USB_MATCH_INTERFACE_PROTOCOL)
261 if (id->bInterfaceProtocol != _id->bInterfaceProtocol) res = 0;
263 if (match == 0UL) {
264 res = 0;
267 return res;
270 /*===========================================================================*
271 * match_usb_driver *
272 *===========================================================================*/
273 static struct devmand_usb_driver*
274 match_usb_driver(struct usb_device_id *id)
276 struct devmand_usb_driver *driver;
277 struct devmand_usb_match_id *mid;
279 LIST_FOREACH(driver, &drivers, list) {
280 LIST_FOREACH(mid, &driver->ids, list) {
281 if (match_usb_id(mid, id)) {
282 return driver;
286 return NULL;
289 /*===========================================================================*
290 * add_usb_match_id *
291 *===========================================================================*/
292 struct devmand_usb_driver * add_usb_driver(char *name)
294 struct devmand_usb_driver *udrv = (struct devmand_usb_driver*)
295 malloc(sizeof(struct devmand_usb_driver));
297 LIST_INSERT_HEAD(&drivers, udrv, list);
298 LIST_INIT(&udrv->ids);
300 udrv->name = name;
301 return udrv;
304 /*===========================================================================*
305 * add_usb_match_id *
306 *===========================================================================*/
307 struct devmand_usb_match_id *
308 add_usb_match_id
309 (struct devmand_usb_driver *drv)
311 struct devmand_usb_match_id *id = (struct devmand_usb_match_id*)
312 malloc(sizeof(struct devmand_usb_match_id));
314 memset(id, 0, sizeof(struct devmand_usb_match_id));
316 LIST_INSERT_HEAD(&drv->ids, id, list);
318 return id;
322 /*===========================================================================*
323 * parse_config *
324 *===========================================================================*/
325 static void parse_config()
327 int i, status, error;
328 struct stat stats;
329 char * dirname;
331 DIR * dir;
332 struct dirent entry;
333 struct dirent *result;
334 char config_file[PATH_MAX];
336 dbg("Parsing configuration directories... ");
337 /* Next parse the configuration directories */
338 for(i=0; i < args.config_dir_count; i++){
339 dirname = args.config_dirs[i];
340 dbg("Parsing config dir %s ", dirname);
341 status = stat(dirname,&stats);
342 if (status == -1){
343 error = errno;
344 dbg("Failed to read directory '%s':%s (skipping) \n",
345 dirname,strerror(error));
346 continue;
348 if (!S_ISDIR(stats.st_mode)){
349 dbg("Parse configuration skipping %s "
350 "(not a directory) \n",dirname);
351 continue;
353 dir = opendir(dirname);
354 if (dir == NULL){
355 error = errno;
356 dbg("Parse configuration failed to read dir '%s'"
357 "(skipping) :%s\n",dirname, strerror(error));
358 continue;
360 while( (status = readdir_r(dir,&entry,&result)) == 0 ){
361 if (result == NULL){ /* last entry */
362 closedir(dir);
363 break;
366 /* concatenate dir and file name to open it */
367 snprintf(config_file,PATH_MAX, "%s/%s",
368 dirname,entry.d_name);
369 status = stat(config_file, &stats);
370 if (status == -1){
371 error = errno;
372 dbg("Parse configuration Failed to stat file "
373 "'%s': %s (skipping)\n", config_file,
374 strerror(error));
376 if (S_ISREG(stats.st_mode)){
377 dbg("Parsing file %s",config_file);
378 yyin = fopen(config_file, "r");
380 if (yyin == NULL) {
381 dbg("Can not open config file:"
382 " %d.\n", errno);
384 yyparse();
385 dbg("Done.");
386 fclose(yyin);
390 dbg("Parsing configuration directories done... ");
394 /*===========================================================================*
395 * cleanup *
396 *===========================================================================*/
397 static void cleanup() {
398 struct devmand_driver_instance *inst;
399 /* destroy fifo */
400 dbg("cleaning up... ");
401 /* quit all running drivers */
402 LIST_FOREACH(inst, &instances, list) {
403 dbg("stopping driver %s", inst->label);
404 if(inst->drv->downscript) {
405 run_downscript (inst);
407 stop_driver(inst);
409 unlink("/var/run/devmand.pid");
412 static void sig_int(int sig) {
413 dbg("devman: Received SIGINT... cleaning up.");
414 _run = 0;
417 /*===========================================================================*
418 * create_pid_file *
419 *===========================================================================*/
420 void create_pid_file()
422 FILE *fd;
424 fd = fopen("/var/run/devmand.pid", "r");
425 if(fd) {
426 fprintf(stderr, "devmand: /var/run/devmand.pid exists... "
427 "another devmand running?\n");
428 fclose(fd);
429 exit(1);
430 } else {
431 fd = fopen("/var/run/devmand.pid","w");
432 fprintf(fd, "%d", getpid());
433 fclose(fd);
437 /*===========================================================================*
438 * main *
439 *===========================================================================*/
440 int main(int argc, char *argv[])
442 int opt, optindex;
443 struct devmand_usb_driver *driver;
446 /* get command line arguments */
447 while ((opt = getopt_long(argc, argv, "d:p:vxh?", options, &optindex))
448 != -1) {
449 switch (opt) {
450 case 'd':/* config directory */
451 if (args.config_dir_count >= MAX_CONFIG_DIRS){
452 fprintf(stderr,"Parse arguments: Maximum"
453 " of %i configuration directories"
454 " reached skipping directory '%s'\n"
455 , MAX_CONFIG_DIRS, optarg);
456 break;
458 args.config_dirs[args.config_dir_count] = optarg;
459 args.config_dir_count++;
460 break;
461 case 'p': /* sysfs path */
462 args.path = optarg;
463 break;
464 case 'v': /* verbose */
465 args.verbose = 1;
466 break;
467 case 'x': /* check config */
468 args.check_config = 1;
469 break;
470 case 'h': /* help */
471 case '?': /* help */
472 default:
473 display_usage(argv[0]);
474 return 0;
479 /* is path set? */
480 if (args.path == NULL) {
481 args.path = "/sys/";
484 /* is the configuration directory set? */
485 if (args.config_dir_count == 0) {
486 dbg("Using default configuration directory");
487 args.config_dirs[0] = "/etc/devmand";
488 args.config_dir_count = 1;
491 /* If we only check the configuration run and exit imediately */
492 if (args.check_config == 1){
493 fprintf(stdout, "Only parsing configuration\n");
494 parse_config();
495 exit(0);
498 create_pid_file();
500 parse_config();
501 LIST_FOREACH(driver, &drivers, list) {
502 if (driver->upscript) {
503 run_cleanscript(driver);
507 signal(SIGINT, sig_int);
509 main_loop();
511 cleanup();
513 return 0;
516 /*===========================================================================*
517 * determine_type *
518 *===========================================================================*/
519 static enum dev_type determine_type (char *path)
521 FILE * fd;
522 char *mypath;
523 char buf[256];
524 int res;
526 mypath = (char *) calloc(1, strlen(path)+strlen(DEVMAN_TYPE_NAME)+1);
528 if (mypath == NULL) {
529 fprintf(stderr, "ERROR: out of mem\n");
530 cleanup();
531 exit(1);
534 strcat(mypath, path);
535 strcat(mypath, DEVMAN_TYPE_NAME);
537 fd = fopen(mypath, "r");
538 free(mypath);
540 if (fd == NULL) {
541 fprintf(stderr, "WARN: could not open %s\n", mypath);
542 return DEV_TYPE_UNKOWN;
545 res = fscanf(fd , "%255s\n", buf);
546 fclose(fd);
548 if (res != 1) {
549 fprintf(stderr, "WARN: could not parse %s\n", mypath);
550 return DEV_TYPE_UNKOWN;
553 if (strcmp(buf, "USB_DEV") == 0) {
554 return DEV_TYPE_USB_DEVICE;
555 } else if (strcmp(buf, "USB_INTF") == 0) {
556 return DEV_TYPE_USB_INTF;
559 return DEV_TYPE_UNKOWN;
562 /*===========================================================================*
563 * read_hex_uint *
564 *===========================================================================*/
565 static int read_hex_uint(char *base_path, char *name, unsigned int* val )
567 char my_path[PATH_LEN];
568 FILE *fd;
569 memset(my_path,0,PATH_LEN);
570 int ret = 0;
572 strcat(my_path, base_path);
573 strcat(my_path, name);
575 fd = fopen(my_path, "r");
577 if (fd == NULL) {
578 fprintf(stderr, "WARN: could not open %s\n", my_path);
579 return EEXIST;
580 } else if (fscanf(fd, "0x%x\n", val ) != 1) {
581 fprintf(stderr, "WARN: could not parse %s\n", my_path);
582 ret = EINVAL;
584 fclose(fd);
586 return ret;
589 /*===========================================================================*
590 * get_major *
591 *===========================================================================*/
592 static int get_major() {
593 int i, ret = args.major_offset;
595 for (i=0; i < 16; i++) {
596 int j;
597 for (j = 0; j < 8; j++ ) {
598 if ((major_bitmap[i] & (1 << j))) {
599 major_bitmap[i] &= !(1 << j);
600 return ret;
602 ret++;
605 return INVAL_MAJOR;
608 /*===========================================================================*
609 * put_major *
610 *===========================================================================*/
611 static void put_major(int major) {
612 int i;
613 major -= args.major_offset;
614 assert(major >= 0);
616 for (i=0; i < 16; i++) {
617 int j;
618 for (j = 0; j < 8; j++ ) {
619 if (major==0) {
620 assert(!(major_bitmap[i] & (1 <<j)));
621 major_bitmap[i] |= (1 << j);
622 return;
624 major--;
629 /*===========================================================================*
630 * generate_usb_device_id *
631 *===========================================================================*/
632 static struct usb_device_id *
633 generate_usb_device_id(char * path, int is_interface)
635 struct usb_device_id *ret;
636 int res;
637 unsigned int val;
639 ret = (struct usb_device_id *)
640 calloc(1,sizeof (struct usb_device_id));
642 if (is_interface) {
644 res = read_hex_uint(path, "../idVendor", &val);
645 if (res) goto err;
646 ret->idVendor = val;
648 res = read_hex_uint(path, "../idProduct", &val);
649 if (res) goto err;
650 ret->idProduct = val;
651 #if 0
652 res = read_hex_uint(path, "../bcdDevice", &val);
653 if (res) goto err;
654 ret->bcdDevice = val;
655 #endif
656 res = read_hex_uint(path, "../bDeviceClass", &val);
657 if (res) goto err;
658 ret->bDeviceClass = val;
660 res = read_hex_uint(path, "../bDeviceSubClass", &val);
661 if (res) goto err;
662 ret->bDeviceSubClass = val;
664 res = read_hex_uint(path, "../bDeviceProtocol", &val);
665 if (res) goto err;
666 ret->bDeviceProtocol = val;
668 res = read_hex_uint(path, "/bInterfaceClass", &val);
669 if (res) goto err;
670 ret->bInterfaceClass = val;
672 res = read_hex_uint(path, "/bInterfaceSubClass", &val);
673 if (res) goto err;
674 ret->bInterfaceSubClass = val;
676 res = read_hex_uint(path, "/bInterfaceProtocol", &val);
677 if (res) goto err;
678 ret->bInterfaceProtocol = val;
681 return ret;
683 err:
684 free(ret);
685 return NULL;
688 /*===========================================================================*
689 * usb_intf_add_even *
690 *===========================================================================*/
691 static void usb_intf_add_event(char *path, int dev_id)
693 struct usb_device_id *id;
694 struct devmand_usb_driver *drv;
695 struct devmand_driver_instance *drv_inst;
696 int major, ret;
698 /* generate usb_match_id */
699 id = generate_usb_device_id(path,TRUE);
700 if (id == NULL) {
701 fprintf(stderr, "WARN: could not create usb_device id...\n"
702 " ommiting event\n");
703 free(id);
704 return;
707 /* find suitable driver */
708 drv = match_usb_driver(id);
709 free (id);
711 if (drv == NULL) {
712 dbg("INFO: could not find a suitable driver for %s", path);
713 return;
716 /* create instance */
717 drv_inst = (struct devmand_driver_instance *)
718 calloc(1,sizeof(struct devmand_driver_instance));
720 if (drv_inst == NULL) {
721 fprintf(stderr, "ERROR: out of memory");
722 return; /* maybe better quit here. */
726 /* allocate inode number, if device files needed */
727 major = get_major();
728 if (major == INVAL_MAJOR) {
729 fprintf(stderr, "WARN: ran out of major numbers\n"
730 " cannot start driver %s for %s\n",
731 drv->name, path);
732 return;
735 drv_inst->major = major;
736 drv_inst->drv = drv;
737 drv_inst->dev_id = dev_id;
740 /* start driver (invoke minix-service) */
741 start_driver(drv_inst);
744 * run the up action
746 * An up action can be any executable. Before running it devmand
747 * will set certain environment variables so the script can configure
748 * the device (or generate device files, etc). See up_action() for that.
750 if (drv->upscript) {
751 ret = run_upscript(drv_inst);
752 if (ret) {
753 stop_driver(drv_inst);
754 fprintf(stderr, "devmand: warning, could not run up_action\n");
755 free(drv_inst);
756 return;
760 LIST_INSERT_HEAD(&instances,drv_inst,list);
763 /*===========================================================================*
764 * usb_intf_remove_event *
765 *===========================================================================*/
766 static void usb_intf_remove_event(char *path, int dev_id)
768 struct devmand_driver_instance *inst;
769 struct devmand_usb_driver *drv;
770 int ret;
772 /* find the driver instance */
773 inst = find_instance(dev_id);
775 if (inst == NULL) {
776 dbg("No driver running for id: %d", dev_id);
777 return;
779 drv = inst->drv;
781 /* run the down script */
782 if (drv->downscript) {
783 ret = run_downscript(inst);
784 if (ret) {
785 fprintf(stderr, "WARN: error running up_action");
789 /* stop the driver */
790 stop_driver(inst);
792 /* free major */
793 put_major(inst->major);
795 /* free instance */
796 LIST_REMOVE(inst,list);
797 free(inst);
800 /*===========================================================================*
801 * handle_event *
802 *===========================================================================*/
803 static void handle_event(char *event)
805 enum dev_type type;
806 char path[PATH_LEN];
807 char tmp_path[PATH_LEN];
808 int dev_id, res;
810 path[0]=0;
812 if (strncmp("ADD ", event, 4) == 0) {
814 /* read data from event */
815 res = sscanf(event, "ADD %s 0x%x", tmp_path, &dev_id);
817 if (res != 2) {
818 fprintf(stderr, "WARN: could not parse event: %s", event);
819 fprintf(stderr, "WARN: omitting event: %s", event);
822 strcpy(path, args.path);
823 strcat(path, tmp_path);
825 /* what kind of device is added? */
826 type = determine_type(path);
828 switch (type) {
829 case DEV_TYPE_USB_DEVICE:
830 dbg("USB device added: ommited....");
831 /* ommit usb devices for now */
832 break;
833 case DEV_TYPE_USB_INTF:
834 dbg("USB interface added: (%s, devid: = %d)",path, dev_id);
835 usb_intf_add_event(path, dev_id);
836 return;
837 default:
838 dbg("default");
839 fprintf(stderr, "WARN: ommiting event\n");
841 } else if (strncmp("REMOVE ", event, 7) == 0) {
843 /* read data from event */
844 res = sscanf(event,"REMOVE %s 0x%x", tmp_path, &dev_id);
846 if (res != 2) {
847 fprintf(stderr, "WARN: could not parse event: %s", event);
848 fprintf(stderr, "WARN: omitting event: %s", event);
851 usb_intf_remove_event(path, dev_id);
853 #if 0
854 strcpy(path, args.path);
855 strcat(path, tmp_path);
857 /* what kind of device is added? */
858 type = determine_type(path);
860 switch (type) {
861 case DEV_TYPE_USB_DEVICE:
862 /* ommit usb devices for now */
863 break;
864 case DEV_TYPE_USB_INTF:
865 usb_intf_remove_event(path, dev_id);
866 return;
867 default:
868 fprintf(stderr, "WARN: ommiting event\n");
870 #endif
875 /*===========================================================================*
876 * main_loop *
877 *===========================================================================*/
878 static void main_loop()
880 char ev_path[128];
881 char buf[256];
882 int len;
883 FILE* fd;
884 len = strlen(args.path);
886 /* init major numbers */
888 memset(&major_bitmap, 0xff, 16);
890 if (len > 128 - 7 /*len of "events" */) {
891 fprintf(stderr, "pathname to long\n");
892 cleanup();
893 exit(1);
896 strcpy(ev_path, args.path);
897 strcat(ev_path, "events");
900 while (_run) {
902 char *res;
904 fd = fopen(ev_path, "r");
905 if (fd == NULL) {
907 * ENFILE is a temporary failure, often caused by
908 * running the test set. Don't die from that..
910 if (errno == ENFILE) {
911 usleep(50000);
912 continue;
915 fprintf(stderr,"devmand error: could not open event "
916 "file %s bailing out\n", ev_path);
917 cleanup();
918 exit(1);
921 res = fgets(buf, 256, fd);
922 fclose(fd);
924 if (res == NULL) {
925 usleep(50000);
926 continue;
928 dbg("handle_event: %s", buf);
929 handle_event(buf);
933 /*===========================================================================*
934 * display_usage *
935 *===========================================================================*/
936 static void display_usage(const char *name)
938 printf("Usage: %s [{-p|--pathname} PATH_TO_SYS}"
939 " [{-d|--config-dir} CONFIG_DIR] [-v|--verbose]"
940 " [[x||--check-config]\n", name);