mirror of
https://github.com/darlinghq/darling-Libnotify.git
synced 2024-11-23 12:19:43 +00:00
757 lines
16 KiB
C
757 lines
16 KiB
C
/*
|
|
* Copyright (c) 2006-2010 Apple Inc. All rights reserved.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_START@
|
|
*
|
|
* This file contains Original Code and/or Modifications of Original Code
|
|
* as defined in and that are subject to the Apple Public Source License
|
|
* Version 2.0 (the 'License'). You may not use this file except in
|
|
* compliance with the License. Please obtain a copy of the License at
|
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
|
* file.
|
|
*
|
|
* The Original Code and all software distributed under the License are
|
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
* Please see the License for the specific language governing rights and
|
|
* limitations under the License.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_END@
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <sys/time.h>
|
|
#include <mach/mach.h>
|
|
#include <notify.h>
|
|
#include <notify_private.h>
|
|
#include <signal.h>
|
|
#include <dispatch/dispatch.h>
|
|
#include <os/variant_private.h>
|
|
|
|
#define forever for(;;)
|
|
#define IndexNull ((uint32_t)-1)
|
|
|
|
#define PRINT_QUIET 0x00000000
|
|
#define PRINT_KEY 0x00000001
|
|
#define PRINT_STATE 0x00000002
|
|
#define PRINT_TIME 0x00000004
|
|
#define PRINT_TYPE 0x00000008
|
|
#define PRINT_TOKEN 0x00000010
|
|
#define PRINT_VERBOSE 0xffffffff
|
|
|
|
#ifndef USEC_PER_SEC
|
|
#define USEC_PER_SEC 1000000
|
|
#endif
|
|
|
|
#define TYPE_NULL 0
|
|
#define TYPE_PORT 1
|
|
#define TYPE_FILE 2
|
|
#define TYPE_DISPATCH 3
|
|
#define TYPE_SIGNAL 4
|
|
#define TYPE_CHECK 5
|
|
#define TYPE_PLAIN 6
|
|
|
|
static const char *typename[] =
|
|
{
|
|
"unknown",
|
|
"port",
|
|
"file",
|
|
"dispatch",
|
|
"signal",
|
|
"check",
|
|
"plain"
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
uint32_t token;
|
|
uint32_t type;
|
|
uint32_t signum;
|
|
uint32_t count;
|
|
char *name;
|
|
} reg_entry_t;
|
|
|
|
static reg_entry_t *reg;
|
|
static uint32_t reg_count = 0;
|
|
|
|
static int printopt;
|
|
static int port_flag;
|
|
static int file_flag;
|
|
static int watch_file;
|
|
static mach_port_t watch_port;
|
|
static dispatch_source_t timer_src;
|
|
static dispatch_source_t port_src;
|
|
static dispatch_source_t file_src;
|
|
static dispatch_source_t sig_src[__DARWIN_NSIG];
|
|
static dispatch_queue_t watch_queue;
|
|
|
|
static void
|
|
usage(const char *name)
|
|
{
|
|
fprintf(stderr, "usage: %s [-q] [-v] [-z msec] [-M] [-R] [command ...]\n", name);
|
|
fprintf(stderr, " -q quiet mode\n");
|
|
fprintf(stderr, " -v verbose - prints time, key, state value, and type\n");
|
|
fprintf(stderr, " -z msec pause msec milliseconds after posting [default 100]\n");
|
|
fprintf(stderr, " -M multiplex notifications from notifyd over a single mach port\n");
|
|
fprintf(stderr, " -R regenerate registrations if notifyd restarts\n");
|
|
fprintf(stderr, "commands:\n");
|
|
fprintf(stderr, " -port switch to mach port for subsequent registrations [default]\n");
|
|
fprintf(stderr, " -file switch to file descriptor for subsequent registrations\n");
|
|
fprintf(stderr, " -check switch to shared memory for subsequent registrations\n");
|
|
fprintf(stderr, " -signal [#] switch to signal [#] for subsequent registrations\n");
|
|
fprintf(stderr, " initial default for signal is 1 (SIGHUP)\n");
|
|
fprintf(stderr, " -dispatch switch to dispatch for subsequent registrations\n");
|
|
fprintf(stderr, " -p key post a notification for key\n");
|
|
fprintf(stderr, " -w key register for key and report notifications\n");
|
|
fprintf(stderr, " -# key (# is an integer value, eg \"-1\") register for key and report # notifications\n");
|
|
fprintf(stderr, " -g key get state value for key\n");
|
|
fprintf(stderr, " -s key val set state value for key\n");
|
|
|
|
if(os_variant_has_internal_diagnostics(NULL))
|
|
{
|
|
fprintf(stderr, " --dump dumps metadata to a file in /var/run/\n");
|
|
}
|
|
}
|
|
|
|
// Triggers a notifyd dump
|
|
static void
|
|
notifyutil_dump()
|
|
{
|
|
int ret;
|
|
|
|
ret = notify_dump_status("/var/run/notifyd.status");
|
|
|
|
if(ret == NOTIFY_STATUS_OK)
|
|
{
|
|
fprintf(stdout, "Notifyd dump success! New file created at /var/run/notifyd.status\n");
|
|
} else {
|
|
fprintf(stdout, "Notifyd dump failed with %x\n", ret);
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
reg_add(uint32_t tid, uint32_t type, uint32_t signum, uint32_t count, const char *name)
|
|
{
|
|
if (name == NULL) return;
|
|
|
|
reg = (reg_entry_t *)reallocf(reg, (reg_count + 1) * sizeof(reg_entry_t));
|
|
if (reg == NULL)
|
|
{
|
|
fprintf(stderr, "Can't allocate memory!\n");
|
|
reg_count = 0;
|
|
return;
|
|
}
|
|
|
|
reg[reg_count].token = tid;
|
|
reg[reg_count].type = type;
|
|
reg[reg_count].signum = signum;
|
|
reg[reg_count].count = count;
|
|
reg[reg_count].name = strdup(name);
|
|
if (reg[reg_count].name == NULL)
|
|
{
|
|
fprintf(stderr, "Can't allocate memory!\n");
|
|
reg = NULL;
|
|
reg_count = 0;
|
|
return;
|
|
}
|
|
|
|
reg_count++;
|
|
}
|
|
|
|
static void
|
|
reg_delete(uint32_t index)
|
|
{
|
|
uint32_t i;
|
|
|
|
if (index == IndexNull) return;
|
|
if (index >= reg_count) return;
|
|
|
|
free(reg[index].name);
|
|
|
|
for (i = index + 1; i < reg_count; i++) reg[i - 1] = reg[i];
|
|
reg_count--;
|
|
|
|
if (reg_count == 0)
|
|
{
|
|
free(reg);
|
|
reg = NULL;
|
|
}
|
|
else
|
|
{
|
|
reg = (reg_entry_t *)reallocf(reg, reg_count * sizeof(reg_entry_t));
|
|
if (reg == NULL)
|
|
{
|
|
fprintf(stderr, "Can't allocate memory!\n");
|
|
reg_count = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint32_t
|
|
reg_find_token(uint32_t tid)
|
|
{
|
|
uint32_t i;
|
|
|
|
for (i = 0; i < reg_count; i++) if (tid == reg[i].token) return i;
|
|
return IndexNull;
|
|
}
|
|
|
|
static void
|
|
process_event(int tid)
|
|
{
|
|
struct timeval now;
|
|
char tstr[32];
|
|
int status, needspace;
|
|
uint32_t index;
|
|
uint64_t state;
|
|
|
|
gettimeofday(&now, NULL);
|
|
|
|
index = reg_find_token(tid);
|
|
if (index == IndexNull) return;
|
|
|
|
needspace = 0;
|
|
|
|
if (printopt & PRINT_TOKEN)
|
|
{
|
|
printf("[%d]", tid);
|
|
needspace = 1;
|
|
}
|
|
|
|
if (printopt & PRINT_TIME)
|
|
{
|
|
if (needspace) printf(" ");
|
|
snprintf(tstr, sizeof(tstr), "%llu", now.tv_usec + USEC_PER_SEC + 500);
|
|
tstr[4] = '\0';
|
|
printf("%d.%s", (int)now.tv_sec, tstr+1);
|
|
needspace = 1;
|
|
}
|
|
|
|
if (printopt & PRINT_KEY)
|
|
{
|
|
if (needspace) printf(" ");
|
|
printf("%s", reg[index].name);
|
|
needspace = 1;
|
|
}
|
|
|
|
if (printopt & PRINT_STATE)
|
|
{
|
|
if (needspace) printf(" ");
|
|
state = 0;
|
|
status = notify_get_state(tid, &state);
|
|
if (status == NOTIFY_STATUS_OK) printf("%llu",(unsigned long long)state);
|
|
else printf(": Failed with code %d", status);
|
|
needspace = 1;
|
|
}
|
|
|
|
if (printopt & PRINT_TYPE)
|
|
{
|
|
if (needspace) printf(" ");
|
|
printf("%s", typename[reg[index].type]);
|
|
}
|
|
|
|
if (printopt != PRINT_QUIET) printf("\n");
|
|
|
|
if ((reg[index].count != IndexNull) && (reg[index].count != 0)) reg[index].count--;
|
|
if (reg[index].count == 0)
|
|
{
|
|
(void)notify_cancel(tid);
|
|
reg_delete(index);
|
|
}
|
|
fflush(stdout);
|
|
|
|
if (reg_count == 0) exit(0);
|
|
}
|
|
|
|
static void
|
|
file_handler(int fd)
|
|
{
|
|
ssize_t i;
|
|
int tid;
|
|
|
|
if (fd < 0) return;
|
|
|
|
i = read(fd, &tid, sizeof(tid));
|
|
if (i < 0) return;
|
|
|
|
tid = ntohl(tid);
|
|
process_event(tid);
|
|
|
|
if (reg_count == 0) exit(0);
|
|
}
|
|
|
|
static void
|
|
port_handler(mach_port_t port)
|
|
{
|
|
int tid;
|
|
mach_msg_empty_rcv_t msg;
|
|
kern_return_t status;
|
|
|
|
if (port == MACH_PORT_NULL) return;
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
status = mach_msg(&msg.header, MACH_RCV_MSG, 0, sizeof(msg), port, 0, MACH_PORT_NULL);
|
|
if (status != KERN_SUCCESS) return;
|
|
|
|
tid = msg.header.msgh_id;
|
|
process_event(tid);
|
|
|
|
if (reg_count == 0) exit(0);
|
|
}
|
|
|
|
static void
|
|
signal_handler(uint32_t sig)
|
|
{
|
|
uint32_t i, status;
|
|
int check;
|
|
|
|
if (printopt != PRINT_QUIET) printf("SIGNAL %u\n", sig);
|
|
for (i = 0; i < reg_count; i++)
|
|
{
|
|
if ((reg[i].type == TYPE_SIGNAL) && (reg[i].signum == sig))
|
|
{
|
|
check = 0;
|
|
status = notify_check(reg[i].token, &check);
|
|
if ((status == NOTIFY_STATUS_OK) && (check != 0)) process_event(reg[i].token);
|
|
}
|
|
}
|
|
|
|
if (reg_count == 0) exit(0);
|
|
}
|
|
|
|
static void
|
|
dispatch_handler(int x)
|
|
{
|
|
uint32_t index = reg_find_token(x);
|
|
if (index == IndexNull) return;
|
|
|
|
process_event(reg[index].token);
|
|
}
|
|
|
|
static void
|
|
timer_handler(void)
|
|
{
|
|
uint32_t i, status;
|
|
int check;
|
|
|
|
for (i = 0; i < reg_count; i++)
|
|
{
|
|
if ((reg[i].type == TYPE_CHECK) || (reg[i].type == TYPE_PLAIN))
|
|
{
|
|
check = 0;
|
|
status = notify_check(reg[i].token, &check);
|
|
if ((status == NOTIFY_STATUS_OK) && (check != 0)) process_event(reg[i].token);
|
|
}
|
|
}
|
|
|
|
if (reg_count == 0) exit(0);
|
|
}
|
|
|
|
static uint32_t
|
|
do_register(const char *name, uint32_t type, uint32_t signum, uint32_t count)
|
|
{
|
|
int tid, check;
|
|
uint32_t status;
|
|
|
|
switch (type)
|
|
{
|
|
case TYPE_PORT:
|
|
{
|
|
status = notify_register_mach_port(name, &watch_port, port_flag, &tid);
|
|
if (status != NOTIFY_STATUS_OK) return status;
|
|
|
|
port_flag = NOTIFY_REUSE;
|
|
if (port_src == NULL)
|
|
{
|
|
port_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, watch_port, 0, watch_queue);
|
|
dispatch_source_set_event_handler(port_src, ^{
|
|
port_handler(watch_port);
|
|
});
|
|
dispatch_resume(port_src);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case TYPE_FILE:
|
|
{
|
|
status = notify_register_file_descriptor(name, &watch_file, file_flag, &tid);
|
|
if (status != NOTIFY_STATUS_OK) return status;
|
|
|
|
file_flag = NOTIFY_REUSE;
|
|
if (file_src == NULL)
|
|
{
|
|
file_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t)watch_file, 0, watch_queue);
|
|
dispatch_source_set_event_handler(file_src, ^{
|
|
file_handler(watch_file);
|
|
});
|
|
dispatch_resume(file_src);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case TYPE_SIGNAL:
|
|
{
|
|
signal(signum, SIG_IGN);
|
|
|
|
status = notify_register_signal(name, signum, &tid);
|
|
if (status != NOTIFY_STATUS_OK) return status;
|
|
|
|
(void)notify_check(tid, &check);
|
|
|
|
if (sig_src[signum] == NULL)
|
|
{
|
|
sig_src[signum] = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, (uintptr_t)signum, 0, watch_queue);
|
|
dispatch_source_set_event_handler(sig_src[signum], ^{
|
|
signal_handler(signum);
|
|
});
|
|
dispatch_resume(sig_src[signum]);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case TYPE_DISPATCH:
|
|
{
|
|
status = notify_register_dispatch(name, &tid, watch_queue, ^(int x){ dispatch_handler(x); });
|
|
if (status != NOTIFY_STATUS_OK) return status;
|
|
break;
|
|
}
|
|
|
|
case TYPE_CHECK:
|
|
{
|
|
status = notify_register_check(name, &tid);
|
|
if (status != NOTIFY_STATUS_OK) return status;
|
|
|
|
(void)notify_check(tid, &check);
|
|
|
|
if (timer_src == NULL)
|
|
{
|
|
timer_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, watch_queue);
|
|
dispatch_source_set_event_handler(timer_src, ^{
|
|
timer_handler();
|
|
});
|
|
dispatch_source_set_timer(timer_src, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 10), NSEC_PER_SEC / 10, 0);
|
|
dispatch_resume(timer_src);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case TYPE_PLAIN:
|
|
{
|
|
status = notify_register_plain(name, &tid);
|
|
if (status != NOTIFY_STATUS_OK) return status;
|
|
|
|
(void)notify_check(tid, &check);
|
|
|
|
if (timer_src == NULL)
|
|
{
|
|
timer_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, watch_queue);
|
|
dispatch_source_set_event_handler(timer_src, ^{
|
|
timer_handler();
|
|
});
|
|
dispatch_source_set_timer(timer_src, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 10), NSEC_PER_SEC / 10, 0);
|
|
dispatch_resume(timer_src);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default: return NOTIFY_STATUS_FAILED;
|
|
}
|
|
|
|
reg_add(tid, type, signum, count, name);
|
|
return NOTIFY_STATUS_OK;
|
|
}
|
|
|
|
int
|
|
main(int argc, const char *argv[])
|
|
{
|
|
const char *name;
|
|
int i;
|
|
uint32_t n, signum, ntype, status, opts, nap;
|
|
int tid;
|
|
uint64_t state;
|
|
|
|
for (i = 0; i < __DARWIN_NSIG; i++) sig_src[i] = NULL;
|
|
|
|
ntype = TYPE_PORT;
|
|
signum = 1;
|
|
watch_file = -1;
|
|
watch_port = MACH_PORT_NULL;
|
|
printopt = PRINT_KEY;
|
|
opts = 0;
|
|
nap = 100000;
|
|
|
|
watch_queue = dispatch_queue_create("Watch Q", NULL);
|
|
|
|
name = strrchr(argv[0], '/');
|
|
if (name == NULL) name = argv[0];
|
|
else name++;
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if ((!strcmp(argv[i], "-help")) || (!strcmp(argv[i], "-h")))
|
|
{
|
|
usage(name);
|
|
exit(0);
|
|
}
|
|
else if (!strcmp(argv[i], "-q"))
|
|
{
|
|
printopt = PRINT_QUIET;
|
|
}
|
|
else if (!strcmp(argv[i], "-v"))
|
|
{
|
|
printopt |= PRINT_VERBOSE;
|
|
}
|
|
else if (!strcmp(argv[i], "-M"))
|
|
{
|
|
opts |= NOTIFY_OPT_DISPATCH;
|
|
}
|
|
else if (!strcmp(argv[i], "-R"))
|
|
{
|
|
opts |= NOTIFY_OPT_REGEN;
|
|
}
|
|
else if (!strcmp(argv[i], "-z"))
|
|
{
|
|
if ((i + 1) >= argc)
|
|
{
|
|
fprintf(stderr, "timer value must be supplied following -z\n");
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
i++;
|
|
|
|
if ((argv[i][0] < '0') || (argv[i][1] > '9'))
|
|
{
|
|
fprintf(stderr, "-z %s is invalid\n", argv[i]);
|
|
fprintf(stderr, "timer value must be an integer\n");
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
nap = 1000 * atoi(argv[i]);
|
|
}
|
|
else if (!strcmp(argv[i], "-port"))
|
|
{}
|
|
else if (!strcmp(argv[i], "-file"))
|
|
{}
|
|
else if ((!strcmp(argv[i], "-sig")) || (!strcmp(argv[i], "-signal")))
|
|
{
|
|
if ((i + 1) >= argc) continue;
|
|
if (argv[i + 1][0] == '-') continue;
|
|
|
|
i++;
|
|
|
|
if ((argv[i][0] < '0') || (argv[i][1] > '9'))
|
|
{
|
|
fprintf(stderr, "-signal %s is invalid\n", argv[i]);
|
|
fprintf(stderr, "signals must be specified as integer values\n");
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
}
|
|
else if (!strcmp(argv[i], "-dispatch"))
|
|
{}
|
|
else if (!strcmp(argv[i], "-check"))
|
|
{}
|
|
else if (!strcmp(argv[i], "-plain"))
|
|
{}
|
|
else if (!strcmp(argv[i], "-p"))
|
|
{
|
|
if ((i + 1) >= argc)
|
|
{
|
|
fprintf(stderr, "name required following -p\n");
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
else if ((argv[i][0] == '-') && ((argv[i][1] == 'w') || ((argv[i][1] >= '0') && (argv[i][1] <= '9'))))
|
|
{
|
|
if ((i + 1) >= argc)
|
|
{
|
|
fprintf(stderr, "name required following %s\n", argv[i]);
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
else if (!strcmp(argv[i], "-g"))
|
|
{
|
|
if ((i + 1) >= argc)
|
|
{
|
|
fprintf(stderr, "name required following -g\n");
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
else if (!strcmp(argv[i], "-s"))
|
|
{
|
|
if ((i + 1) >= argc)
|
|
{
|
|
fprintf(stderr, "name required following -s\n");
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
i++;
|
|
|
|
if ((i + 1) >= argc)
|
|
{
|
|
fprintf(stderr, "value required following -s name\n");
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
i++;
|
|
state = atoll(argv[i]);
|
|
if ((state == 0) && (strcmp(argv[i], "0")))
|
|
{
|
|
fprintf(stderr, "value following -s name must be a 64-bit integer\n");
|
|
}
|
|
}
|
|
else if (!strcmp(argv[i], "--dump") && os_variant_has_internal_diagnostics(NULL))
|
|
{
|
|
notifyutil_dump();
|
|
exit(0);
|
|
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "unrecognized option: %s\n", argv[i]);
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (opts != 0) notify_set_options(opts);
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if (!strcmp(argv[i], "-port"))
|
|
{
|
|
ntype = TYPE_PORT;
|
|
}
|
|
else if (!strcmp(argv[i], "-file"))
|
|
{
|
|
ntype = TYPE_FILE;
|
|
}
|
|
else if ((!strcmp(argv[i], "-sig")) || (!strcmp(argv[i], "-signal")))
|
|
{
|
|
|
|
ntype = TYPE_SIGNAL;
|
|
if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
|
|
{
|
|
i++;
|
|
signum = atoi(argv[i]);
|
|
}
|
|
}
|
|
else if (!strcmp(argv[i], "-dispatch"))
|
|
{
|
|
ntype = TYPE_DISPATCH;
|
|
}
|
|
else if (!strcmp(argv[i], "-check"))
|
|
{
|
|
ntype = TYPE_CHECK;
|
|
}
|
|
else if (!strcmp(argv[i], "-plain"))
|
|
{
|
|
ntype = TYPE_PLAIN;
|
|
}
|
|
else if (!strcmp(argv[i], "-p"))
|
|
{
|
|
if ((i + 1) >= argc)
|
|
{
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
i++;
|
|
|
|
status = notify_post(argv[i]);
|
|
if (status != NOTIFY_STATUS_OK) printf("%s: Failed with code %d\n", argv[i], status);
|
|
else if (nap > 0) usleep(nap);
|
|
}
|
|
else if ((argv[i][0] == '-') && ((argv[i][1] == 'w') || ((argv[i][1] >= '0') && (argv[i][1] <= '9'))))
|
|
{
|
|
if ((i + 1) >= argc)
|
|
{
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
n = IndexNull;
|
|
if (argv[i][1] != 'w') n = atoi(argv[i] + 1);
|
|
|
|
i++;
|
|
tid = IndexNull;
|
|
|
|
status = do_register(argv[i], ntype, signum, n);
|
|
if (status != NOTIFY_STATUS_OK) printf("%s: Failed with code %d\n", argv[i], status);
|
|
}
|
|
else if (!strcmp(argv[i], "-g"))
|
|
{
|
|
if ((i + 1) >= argc)
|
|
{
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
i++;
|
|
state = 0;
|
|
tid = IndexNull;
|
|
|
|
status = notify_register_plain(argv[i], &tid);
|
|
if (status == NOTIFY_STATUS_OK)
|
|
{
|
|
status = notify_get_state(tid, &state);
|
|
notify_cancel(tid);
|
|
}
|
|
|
|
if (status == NOTIFY_STATUS_OK) printf("%s %llu\n", argv[i], (unsigned long long)state);
|
|
else printf("%s: Failed with code %d\n", argv[i], status);
|
|
}
|
|
else if (!strcmp(argv[i], "-s"))
|
|
{
|
|
if ((i + 2) >= argc)
|
|
{
|
|
usage(name);
|
|
exit(1);
|
|
}
|
|
|
|
i++;
|
|
tid = IndexNull;
|
|
status = notify_register_plain(argv[i], &tid);
|
|
if (status == NOTIFY_STATUS_OK)
|
|
{
|
|
state = atoll(argv[i + 1]);
|
|
status = notify_set_state(tid, state);
|
|
notify_cancel(tid);
|
|
}
|
|
|
|
if (status != NOTIFY_STATUS_OK) printf("%s: Failed with code %d\n", argv[i], status);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
if (reg_count == 0) exit(0);
|
|
|
|
dispatch_main();
|
|
}
|