]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/sec_action.c
Security-59306.101.1.tar.gz
[apple/security.git] / OSX / utilities / sec_action.c
1 /*
2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <stdlib.h>
25 #include <Block.h>
26 #include <dispatch/dispatch.h>
27
28 #include "sec_action.h"
29
30 struct sec_action_context_s {
31 dispatch_queue_t queue;
32 dispatch_source_t source;
33 dispatch_block_t handler;
34 uint64_t interval;
35 };
36
37 static void _sec_action_event(void *ctx);
38 static void _sec_action_finalize(void *ctx);
39
40 #pragma mark -
41
42 sec_action_t
43 sec_action_create_with_queue(dispatch_queue_t queue, const char *label, uint64_t interval)
44 {
45 dispatch_source_t source;
46 struct sec_action_context_s *context;
47 if (queue) {
48 dispatch_retain(queue);
49 } else {
50 queue = dispatch_queue_create(label, DISPATCH_QUEUE_SERIAL);
51 }
52 source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
53
54 context = malloc(sizeof(*context));
55 context->queue = queue;
56 context->source = source;
57 context->handler = NULL;
58 context->interval = interval;
59 dispatch_set_context(source, context);
60
61 dispatch_source_set_event_handler_f(source, _sec_action_event);
62 dispatch_set_finalizer_f(source, _sec_action_finalize);
63
64 return source;
65 }
66
67 sec_action_t
68 sec_action_create(const char *label, uint64_t interval)
69 {
70 return sec_action_create_with_queue(NULL, label, interval);
71 }
72
73 void
74 sec_action_set_handler(sec_action_t source, dispatch_block_t handler)
75 {
76 struct sec_action_context_s *context;
77
78 context = dispatch_get_context(source);
79 context->handler = Block_copy(handler);
80
81 dispatch_activate(source);
82 }
83
84 void
85 sec_action_perform(sec_action_t source)
86 {
87 dispatch_source_merge_data(source, 1);
88 }
89
90 #pragma mark -
91
92 static void
93 _sec_action_event(void *ctx)
94 {
95 struct sec_action_context_s *context = (struct sec_action_context_s *)ctx;
96
97 if (context->handler != NULL) {
98 context->handler();
99 }
100
101 // Suspend the source; resume after specified interval.
102 dispatch_suspend(context->source);
103 dispatch_after_f(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(context->interval * NSEC_PER_SEC)), context->queue, context->source, (dispatch_function_t)dispatch_resume);
104 }
105
106 static void
107 _sec_action_finalize(void *ctx)
108 {
109 struct sec_action_context_s *context = (struct sec_action_context_s *)ctx;
110
111 dispatch_release(context->queue);
112 if (context->handler != NULL) {
113 Block_release(context->handler);
114 }
115 free(context);
116 }