Adding libnotify source, build scripts for libinfo/dns&util

This commit is contained in:
Lubos Dolezel 2015-04-07 11:49:31 +02:00
parent 3bab377f74
commit 1638dcc2a1
54 changed files with 16732 additions and 0 deletions

View File

@ -17,6 +17,7 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/duct/include")
add_subdirectory(libc)
add_subdirectory(libm)
add_subdirectory(libinfo)
add_subdirectory(libmalloc)
add_subdirectory(libsystem)
add_subdirectory(keymgr)

29
libinfo/CMakeLists.txt Normal file
View File

@ -0,0 +1,29 @@
project(libinfo)
cmake_minimum_required(VERSION 2.4.0)
if(CMAKE_SIZEOF_VOID_P EQUAL 4 OR CMAKE_INSTALL_LIBDIR STREQUAL "lib32")
set(BITS 32)
add_definitions(-DTARGET_CPU_X86=1)
else(CMAKE_SIZEOF_VOID_P EQUAL 4 OR CMAKE_INSTALL_LIBDIR STREQUAL "lib32")
set(BITS 64)
add_definitions(-DTARGET_CPU_X86_64=1)
endif(CMAKE_SIZEOF_VOID_P EQUAL 4 OR CMAKE_INSTALL_LIBDIR STREQUAL "lib32")
add_definitions(-DTARGET_OS_MAC=1)
add_definitions(-DHAVE_STDINT_H=1)
add_definitions(-D__APPLE__ -D__DYNAMIC__)
add_definitions(-D__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__=1080)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc -D__DARWIN_UNIX03 -fPIC -w")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -nostdlib -Wl,--unresolved-symbols=ignore-all")
add_subdirectory(util.subproj)
add_subdirectory(dns.subproj)
#add_subdirectory(lookup.subproj)
add_library(system_info SHARED $<TARGET_OBJECTS:info-util>
$<TARGET_OBJECTS:info-dns>
#$<TARGET_OBJECTS:info-lookup> # lookup doesn't build yet
)
target_link_libraries(system_info system_c)

View File

@ -0,0 +1,18 @@
project(libinfo-dns)
cmake_minimum_required(VERSION 2.4.0)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/locale)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/locale/FreeBSD)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/pthreads)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/stdtime/FreeBSD)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../external/libdispatch/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../lookup.subproj)
set(info-dns_sources
herror.c
res_comp.c
res_query.c
)
add_library(info-dns OBJECT ${info-dns_sources})

View File

@ -0,0 +1,30 @@
project(libinfo-lookup)
cmake_minimum_required(VERSION 2.4.0)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/locale)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/locale/FreeBSD)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/pthreads)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/stdtime/FreeBSD)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../external/libdispatch/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fblocks")
set(info-lookup_sources
cache_module.c
ds_module.c
file_module.c
getnameinfo_link.c
ils.c
kvbuf.c
libinfo.c
mdns_module.c
search_module.c
si_data.c
si_getaddrinfo.c
si_module.c
thread_data.c
)
add_library(info-lookup OBJECT ${info-lookup_sources})

View File

@ -0,0 +1,15 @@
project(libinfo-util)
cmake_minimum_required(VERSION 2.4.0)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/locale)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/locale/FreeBSD)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/pthreads)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libc/stdtime/FreeBSD)
set(info-util_sources
hton.c
rcmd.c
)
add_library(info-util OBJECT ${info-util_sources})

372
libnotify/APPLE_LICENSE Normal file
View File

@ -0,0 +1,372 @@
APPLE PUBLIC SOURCE LICENSE
Version 1.1 - April 19,1999
Please read this License carefully before downloading this software.
By downloading and using this software, you are agreeing to be bound
by the terms of this License. If you do not or cannot agree to the
terms of this License, please do not download or use the software.
1. General; Definitions. This License applies to any program or other
work which Apple Computer, Inc. ("Apple") publicly announces as
subject to this Apple Public Source License and which contains a
notice placed by Apple identifying such program or work as "Original
Code" and stating that it is subject to the terms of this Apple Public
Source License version 1.1 (or subsequent version thereof), as it may
be revised from time to time by Apple ("License"). As used in this
License:
1.1 "Affected Original Code" means only those specific portions of
Original Code that allegedly infringe upon any party's intellectual
property rights or are otherwise the subject of a claim of
infringement.
1.2 "Applicable Patent Rights" mean: (a) in the case where Apple is
the grantor of rights, (i) claims of patents that are now or hereafter
acquired, owned by or assigned to Apple and (ii) that cover subject
matter contained in the Original Code, but only to the extent
necessary to use, reproduce and/or distribute the Original Code
without infringement; and (b) in the case where You are the grantor of
rights, (i) claims of patents that are now or hereafter acquired,
owned by or assigned to You and (ii) that cover subject matter in Your
Modifications, taken alone or in combination with Original Code.
1.3 "Covered Code" means the Original Code, Modifications, the
combination of Original Code and any Modifications, and/or any
respective portions thereof.
1.4 "Deploy" means to use, sublicense or distribute Covered Code other
than for Your internal research and development (R&D), and includes
without limitation, any and all internal use or distribution of
Covered Code within Your business or organization except for R&D use,
as well as direct or indirect sublicensing or distribution of Covered
Code by You to any third party in any form or manner.
1.5 "Larger Work" means a work which combines Covered Code or portions
thereof with code not governed by the terms of this License.
1.6 "Modifications" mean any addition to, deletion from, and/or change
to, the substance and/or structure of Covered Code. When code is
released as a series of files, a Modification is: (a) any addition to
or deletion from the contents of a file containing Covered Code;
and/or (b) any new file or other representation of computer program
statements that contains any part of Covered Code.
1.7 "Original Code" means (a) the Source Code of a program or other
work as originally made available by Apple under this License,
including the Source Code of any updates or upgrades to such programs
or works made available by Apple under this License, and that has been
expressly identified by Apple as such in the header file(s) of such
work; and (b) the object code compiled from such Source Code and
originally made available by Apple under this License.
1.8 "Source Code" means the human readable form of a program or other
work that is suitable for making modifications to it, including all
modules it contains, plus any associated interface definition files,
scripts used to control compilation and installation of an executable
(object code).
1.9 "You" or "Your" means an individual or a legal entity exercising
rights under this License. For legal entities, "You" or "Your"
includes any entity which controls, is controlled by, or is under
common control with, You, where "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of fifty percent
(50%) or more of the outstanding shares or beneficial ownership of
such entity.
2. Permitted Uses; Conditions & Restrictions. Subject to the terms
and conditions of this License, Apple hereby grants You, effective on
the date You accept this License and download the Original Code, a
world-wide, royalty-free, non- exclusive license, to the extent of
Apple's Applicable Patent Rights and copyrights covering the Original
Code, to do the following:
2.1 You may use, copy, modify and distribute Original Code, with or
without Modifications, solely for Your internal research and
development, provided that You must in each instance:
(a) retain and reproduce in all copies of Original Code the copyright
and other proprietary notices and disclaimers of Apple as they appear
in the Original Code, and keep intact all notices in the Original Code
that refer to this License;
(b) include a copy of this License with every copy of Source Code of
Covered Code and documentation You distribute, and You may not offer
or impose any terms on such Source Code that alter or restrict this
License or the recipients' rights hereunder, except as permitted under
Section 6; and
(c) completely and accurately document all Modifications that you have
made and the date of each such Modification, designate the version of
the Original Code you used, prominently include a file carrying such
information with the Modifications, and duplicate the notice in
Exhibit A in each file of the Source Code of all such Modifications.
2.2 You may Deploy Covered Code, provided that You must in each
instance:
(a) satisfy all the conditions of Section 2.1 with respect to the
Source Code of the Covered Code;
(b) make all Your Deployed Modifications publicly available in Source
Code form via electronic distribution (e.g. download from a web site)
under the terms of this License and subject to the license grants set
forth in Section 3 below, and any additional terms You may choose to
offer under Section 6. You must continue to make the Source Code of
Your Deployed Modifications available for as long as you Deploy the
Covered Code or twelve (12) months from the date of initial
Deployment, whichever is longer;
(c) if You Deploy Covered Code containing Modifications made by You,
inform others of how to obtain those Modifications by filling out and
submitting the information found at
http://www.apple.com/publicsource/modifications.html, if available;
and
(d) if You Deploy Covered Code in object code, executable form only,
include a prominent notice, in the code itself as well as in related
documentation, stating that Source Code of the Covered Code is
available under the terms of this License with information on how and
where to obtain such Source Code.
3. Your Grants. In consideration of, and as a condition to, the
licenses granted to You under this License:
(a) You hereby grant to Apple and all third parties a non-exclusive,
royalty-free license, under Your Applicable Patent Rights and other
intellectual property rights owned or controlled by You, to use,
reproduce, modify, distribute and Deploy Your Modifications of the
same scope and extent as Apple's licenses under Sections 2.1 and 2.2;
and
(b) You hereby grant to Apple and its subsidiaries a non-exclusive,
worldwide, royalty-free, perpetual and irrevocable license, under Your
Applicable Patent Rights and other intellectual property rights owned
or controlled by You, to use, reproduce, execute, compile, display,
perform, modify or have modified (for Apple and/or its subsidiaries),
sublicense and distribute Your Modifications, in any form, through
multiple tiers of distribution.
4. Larger Works. You may create a Larger Work by combining Covered
Code with other code not governed by the terms of this License and
distribute the Larger Work as a single product. In each such
instance, You must make sure the requirements of this License are
fulfilled for the Covered Code or any portion thereof.
5. Limitations on Patent License. Except as expressly stated in
Section 2, no other patent rights, express or implied, are granted by
Apple herein. Modifications and/or Larger Works may require
additional patent licenses from Apple which Apple may grant in its
sole discretion.
6. Additional Terms. You may choose to offer, and to charge a fee
for, warranty, support, indemnity or liability obligations and/or
other rights consistent with the scope of the license granted herein
("Additional Terms") to one or more recipients of Covered
Code. However, You may do so only on Your own behalf and as Your sole
responsibility, and not on behalf of Apple. You must obtain the
recipient's agreement that any such Additional Terms are offered by
You alone, and You hereby agree to indemnify, defend and hold Apple
harmless for any liability incurred by or claims asserted against
Apple by reason of any such Additional Terms.
7. Versions of the License. Apple may publish revised and/or new
versions of this License from time to time. Each version will be
given a distinguishing version number. Once Original Code has been
published under a particular version of this License, You may continue
to use it under the terms of that version. You may also choose to use
such Original Code under the terms of any subsequent version of this
License published by Apple. No one other than Apple has the right to
modify the terms applicable to Covered Code created under this
License.
8. NO WARRANTY OR SUPPORT. The Original Code may contain in whole or
in part pre-release, untested, or not fully tested works. The
Original Code may contain errors that could cause failures or loss of
data, and may be incomplete or contain inaccuracies. You expressly
acknowledge and agree that use of the Original Code, or any portion
thereof, is at Your sole and entire risk. THE ORIGINAL CODE IS
PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND
AND APPLE AND APPLE'S LICENSOR(S) (FOR THE PURPOSES OF SECTIONS 8 AND
9, APPLE AND APPLE'S LICENSOR(S) ARE COLLECTIVELY REFERRED TO AS
"APPLE") EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
AND/OR CONDITIONS OF MERCHANTABILITY OR SATISFACTORY QUALITY AND
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
RIGHTS. APPLE DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED IN THE
ORIGINAL CODE WILL MEET YOUR REQUIREMENTS, OR THAT THE OPERATION OF
THE ORIGINAL CODE WILL BE UNINTERRUPTED OR ERROR- FREE, OR THAT
DEFECTS IN THE ORIGINAL CODE WILL BE CORRECTED. NO ORAL OR WRITTEN
INFORMATION OR ADVICE GIVEN BY APPLE OR AN APPLE AUTHORIZED
REPRESENTATIVE SHALL CREATE A WARRANTY OR IN ANY WAY INCREASE THE
SCOPE OF THIS WARRANTY. You acknowledge that the Original Code is not
intended for use in the operation of nuclear facilities, aircraft
navigation, communication systems, or air traffic control machines in
which case the failure of the Original Code could lead to death,
personal injury, or severe physical or environmental damage.
9. Liability.
9.1 Infringement. If any portion of, or functionality implemented by,
the Original Code becomes the subject of a claim of infringement,
Apple may, at its option: (a) attempt to procure the rights necessary
for Apple and You to continue using the Affected Original Code; (b)
modify the Affected Original Code so that it is no longer infringing;
or (c) suspend Your rights to use, reproduce, modify, sublicense and
distribute the Affected Original Code until a final determination of
the claim is made by a court or governmental administrative agency of
competent jurisdiction and Apple lifts the suspension as set forth
below. Such suspension of rights will be effective immediately upon
Apple's posting of a notice to such effect on the Apple web site that
is used for implementation of this License. Upon such final
determination being made, if Apple is legally able, without the
payment of a fee or royalty, to resume use, reproduction,
modification, sublicensing and distribution of the Affected Original
Code, Apple will lift the suspension of rights to the Affected
Original Code by posting a notice to such effect on the Apple web site
that is used for implementation of this License. If Apple suspends
Your rights to Affected Original Code, nothing in this License shall
be construed to restrict You, at Your option and subject to applicable
law, from replacing the Affected Original Code with non-infringing
code or independently negotiating for necessary rights from such third
party.
9.2 LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES SHALL APPLE BE
LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
ARISING OUT OF OR RELATING TO THIS LICENSE OR YOUR USE OR INABILITY TO
USE THE ORIGINAL CODE, OR ANY PORTION THEREOF, WHETHER UNDER A THEORY
OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY
OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF
ANY REMEDY. In no event shall Apple's total liability to You for all
damages under this License exceed the amount of fifty dollars
($50.00).
10. Trademarks. This License does not grant any rights to use the
trademarks or trade names "Apple", "Apple Computer", "Mac OS X", "Mac
OS X Server" or any other trademarks or trade names belonging to Apple
(collectively "Apple Marks") and no Apple Marks may be used to endorse
or promote products derived from the Original Code other than as
permitted by and in strict compliance at all times with Apple's third
party trademark usage guidelines which are posted at
http://www.apple.com/legal/guidelinesfor3rdparties.html.
11. Ownership. Apple retains all rights, title and interest in and to
the Original Code and any Modifications made by or on behalf of Apple
("Apple Modifications"), and such Apple Modifications will not be
automatically subject to this License. Apple may, at its sole
discretion, choose to license such Apple Modifications under this
License, or on different terms from those contained in this License or
may choose not to license them at all. Apple's development, use,
reproduction, modification, sublicensing and distribution of Covered
Code will not be subject to this License.
12. Termination.
12.1 Termination. This License and the rights granted hereunder will
terminate:
(a) automatically without notice from Apple if You fail to comply with
any term(s) of this License and fail to cure such breach within 30
days of becoming aware of such breach; (b) immediately in the event of
the circumstances described in Section 13.5(b); or (c) automatically
without notice from Apple if You, at any time during the term of this
License, commence an action for patent infringement against Apple.
12.2 Effect of Termination. Upon termination, You agree to
immediately stop any further use, reproduction, modification,
sublicensing and distribution of the Covered Code and to destroy all
copies of the Covered Code that are in your possession or control.
All sublicenses to the Covered Code which have been properly granted
prior to termination shall survive any termination of this License.
Provisions which, by their nature, should remain in effect beyond the
termination of this License shall survive, including but not limited
to Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. Neither party will be
liable to the other for compensation, indemnity or damages of any sort
solely as a result of terminating this License in accordance with its
terms, and termination of this License will be without prejudice to
any other right or remedy of either party.
13. Miscellaneous.
13.1 Government End Users. The Covered Code is a "commercial item" as
defined in FAR 2.101. Government software and technical data rights
in the Covered Code include only those rights customarily provided to
the public as defined in this License. This customary commercial
license in technical data and software is provided in accordance with
FAR 12.211 (Technical Data) and 12.212 (Computer Software) and, for
Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
Commercial Items) and 227.7202-3 (Rights in Commercial Computer
Software or Computer Software Documentation). Accordingly, all U.S.
Government End Users acquire Covered Code with only those rights set
forth herein.
13.2 Relationship of Parties. This License will not be construed as
creating an agency, partnership, joint venture or any other form of
legal association between You and Apple, and You will not represent to
the contrary, whether expressly, by implication, appearance or
otherwise.
13.3 Independent Development. Nothing in this License will impair
Apple's right to acquire, license, develop, have others develop for
it, market and/or distribute technology or products that perform the
same or similar functions as, or otherwise compete with,
Modifications, Larger Works, technology or products that You may
develop, produce, market or distribute.
13.4 Waiver; Construction. Failure by Apple to enforce any provision
of this License will not be deemed a waiver of future enforcement of
that or any other provision. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
will not apply to this License.
13.5 Severability. (a) If for any reason a court of competent
jurisdiction finds any provision of this License, or portion thereof,
to be unenforceable, that provision of the License will be enforced to
the maximum extent permissible so as to effect the economic benefits
and intent of the parties, and the remainder of this License will
continue in full force and effect. (b) Notwithstanding the foregoing,
if applicable law prohibits or restricts You from fully and/or
specifically complying with Sections 2 and/or 3 or prevents the
enforceability of either of those Sections, this License will
immediately terminate and You must immediately discontinue any use of
the Covered Code and destroy all copies of it that are in your
possession or control.
13.6 Dispute Resolution. Any litigation or other dispute resolution
between You and Apple relating to this License shall take place in the
Northern District of California, and You and Apple hereby consent to
the personal jurisdiction of, and venue in, the state and federal
courts within that District with respect to this License. The
application of the United Nations Convention on Contracts for the
International Sale of Goods is expressly excluded.
13.7 Entire Agreement; Governing Law. This License constitutes the
entire agreement between the parties with respect to the subject
matter hereof. This License shall be governed by the laws of the
United States and the State of California, except that body of
California law concerning conflicts of law.
Where You are located in the province of Quebec, Canada, the following
clause applies: The parties hereby confirm that they have requested
that this License and all related documents be drafted in English. Les
parties ont exige que le present contrat et tous les documents
connexes soient rediges en anglais.
EXHIBIT A.
"Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
Reserved. 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 1.1 (the "License"). You may not use this file
except in compliance with the License. Please obtain a copy of the
License at http://www.apple.com/publicsource 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 OR NON- INFRINGEMENT. Please see the
License for the specific language governing rights and limitations
under the License."

View File

@ -0,0 +1,698 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 45;
objects = {
/* Begin PBXAggregateTarget section */
3FA21AC7148AA93000099D2F /* cli_apps */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 3FA21AC8148AA93000099D2F /* Build configuration list for PBXAggregateTarget "cli_apps" */;
buildPhases = (
3F947784191C32DC00A93E8E /* No Simulator Man Pages */,
);
dependencies = (
3FA21ACB148AA94A00099D2F /* PBXTargetDependency */,
3FA21ACD148AA94A00099D2F /* PBXTargetDependency */,
);
name = cli_apps;
productName = cli_apps;
};
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
2D312B76102CA2E300F90022 /* libnotify.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D312B73102CA2E300F90022 /* libnotify.c */; };
2D312B77102CA2E300F90022 /* notify_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D312B74102CA2E300F90022 /* notify_client.c */; };
2D312B78102CA2E300F90022 /* table.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D312B75102CA2E300F90022 /* table.c */; };
2D312B7A102CA30200F90022 /* notify_ipc.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2D312B79102CA30200F90022 /* notify_ipc.defs */; settings = {ATTRIBUTES = (Client, ); }; };
2D312B7E102CA32500F90022 /* notify_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D312B7C102CA32500F90022 /* notify_keys.h */; settings = {ATTRIBUTES = (Public, ); }; };
2D312B7F102CA32500F90022 /* notify.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D312B7D102CA32500F90022 /* notify.h */; settings = {ATTRIBUTES = (Public, ); }; };
2D312B82102CA34D00F90022 /* libnotify.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D312B81102CA34D00F90022 /* libnotify.h */; settings = {ATTRIBUTES = (Private, ); }; };
2D312B87102CA36C00F90022 /* table.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D312B85102CA36C00F90022 /* table.h */; };
2D38AA0A102CD88300D3D622 /* notify.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B92102CA38F00F90022 /* notify.3 */; };
2D38AA0B102CD89B00D3D622 /* notify_cancel.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B88102CA38F00F90022 /* notify_cancel.3 */; };
2D38AA0C102CD89B00D3D622 /* notify_check.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B89102CA38F00F90022 /* notify_check.3 */; };
2D38AA0D102CD8B800D3D622 /* notify_get_state.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B8A102CA38F00F90022 /* notify_get_state.3 */; };
2D38AA0E102CD8B800D3D622 /* notify_is_valid_token.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D6D820D18DA602A0034E7B4 /* notify_is_valid_token.3 */; };
2D38AA0F102CD8B800D3D622 /* notify_post.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B8B102CA38F00F90022 /* notify_post.3 */; };
2D38AA10102CD8B800D3D622 /* notify_register_check.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B8C102CA38F00F90022 /* notify_register_check.3 */; };
2D38AA11102CD8B800D3D622 /* notify_register_dispatch.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B8D102CA38F00F90022 /* notify_register_dispatch.3 */; };
2D38AA12102CD8B800D3D622 /* notify_register_file_descriptor.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B8E102CA38F00F90022 /* notify_register_file_descriptor.3 */; };
2D38AA13102CD8B800D3D622 /* notify_register_mach_port.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B8F102CA38F00F90022 /* notify_register_mach_port.3 */; };
2D38AA14102CD8B800D3D622 /* notify_register_signal.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B90102CA38F00F90022 /* notify_register_signal.3 */; };
2D38AA15102CD8B800D3D622 /* notify_set_state.3 in Copy man3 Files */ = {isa = PBXBuildFile; fileRef = 2D312B91102CA38F00F90022 /* notify_set_state.3 */; };
2DCB287210D99ADA00DF3A8D /* notify_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DCB287110D99ADA00DF3A8D /* notify_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
3FA21ACF148AAA5000099D2F /* notify_proc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3FA21A9C148AA7FA00099D2F /* notify_proc.c */; };
3FA21AD0148AAA5000099D2F /* notifyd.c in Sources */ = {isa = PBXBuildFile; fileRef = 3FA21A9E148AA7FA00099D2F /* notifyd.c */; };
3FA21AD1148AAA5000099D2F /* pathwatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 3FA21AA0148AA7FA00099D2F /* pathwatch.c */; };
3FA21AD2148AAA5000099D2F /* service.c in Sources */ = {isa = PBXBuildFile; fileRef = 3FA21AA2148AA7FA00099D2F /* service.c */; };
3FA21AD3148AAA5000099D2F /* timer.c in Sources */ = {isa = PBXBuildFile; fileRef = 3FA21AA5148AA7FA00099D2F /* timer.c */; };
3FA21AD4148AAA5D00099D2F /* notifyd.8 in Install man page */ = {isa = PBXBuildFile; fileRef = 3FA21A9D148AA7FA00099D2F /* notifyd.8 */; };
3FA21AD5148AAA6E00099D2F /* notifyutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 3FA21AA9148AA82700099D2F /* notifyutil.c */; };
3FA21AD6148AAA7500099D2F /* notifyutil.1 in Install man page */ = {isa = PBXBuildFile; fileRef = 3FA21AA8148AA82700099D2F /* notifyutil.1 */; };
3FA21AD8148AAABE00099D2F /* com.apple.notifyd.plist in Install launchd.plist */ = {isa = PBXBuildFile; fileRef = 3FA21A99148AA7FA00099D2F /* com.apple.notifyd.plist */; };
3FA21AE6148AAEAC00099D2F /* notify_ipc.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2D312B79102CA30200F90022 /* notify_ipc.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; };
3FD0DBAD148AB12000C50811 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 3FD0DBAC148AB12000C50811 /* libbsm.dylib */; };
FC7B7A53155781930064D203 /* notify_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = FC7B7A52155781930064D203 /* notify_internal.h */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
3FA21ACA148AA94A00099D2F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 3FA21AAF148AA8E300099D2F;
remoteInfo = notifyd;
};
3FA21ACC148AA94A00099D2F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 3FA21ABD148AA8F000099D2F;
remoteInfo = notifyutil;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
2D38AA09102CD87C00D3D622 /* Copy man3 Files */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = "$(INSTALL_PATH_PREFIX)/usr/share/man/man3";
dstSubfolderSpec = 0;
files = (
2D38AA0A102CD88300D3D622 /* notify.3 in Copy man3 Files */,
2D38AA0B102CD89B00D3D622 /* notify_cancel.3 in Copy man3 Files */,
2D38AA0C102CD89B00D3D622 /* notify_check.3 in Copy man3 Files */,
2D38AA0D102CD8B800D3D622 /* notify_get_state.3 in Copy man3 Files */,
2D38AA0E102CD8B800D3D622 /* notify_is_valid_token.3 in Copy man3 Files */,
2D38AA0F102CD8B800D3D622 /* notify_post.3 in Copy man3 Files */,
2D38AA10102CD8B800D3D622 /* notify_register_check.3 in Copy man3 Files */,
2D38AA11102CD8B800D3D622 /* notify_register_dispatch.3 in Copy man3 Files */,
2D38AA12102CD8B800D3D622 /* notify_register_file_descriptor.3 in Copy man3 Files */,
2D38AA13102CD8B800D3D622 /* notify_register_mach_port.3 in Copy man3 Files */,
2D38AA14102CD8B800D3D622 /* notify_register_signal.3 in Copy man3 Files */,
2D38AA15102CD8B800D3D622 /* notify_set_state.3 in Copy man3 Files */,
);
name = "Copy man3 Files";
runOnlyForDeploymentPostprocessing = 1;
};
3FA21AAE148AA8E300099D2F /* Install man page */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "$(INSTALL_PATH_PREFIX)/usr/share/man/man8";
dstSubfolderSpec = 0;
files = (
3FA21AD4148AAA5D00099D2F /* notifyd.8 in Install man page */,
);
name = "Install man page";
runOnlyForDeploymentPostprocessing = 1;
};
3FA21ABC148AA8F000099D2F /* Install man page */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "$(INSTALL_PATH_PREFIX)/usr/share/man/man1";
dstSubfolderSpec = 0;
files = (
3FA21AD6148AAA7500099D2F /* notifyutil.1 in Install man page */,
);
name = "Install man page";
runOnlyForDeploymentPostprocessing = 1;
};
3FA21AD7148AAAA600099D2F /* Install launchd.plist */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = "$(INSTALL_PATH_PREFIX)/System/Library/LaunchDaemons";
dstSubfolderSpec = 0;
files = (
3FA21AD8148AAABE00099D2F /* com.apple.notifyd.plist in Install launchd.plist */,
);
name = "Install launchd.plist";
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
2D312B73102CA2E300F90022 /* libnotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libnotify.c; sourceTree = "<group>"; };
2D312B74102CA2E300F90022 /* notify_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = notify_client.c; sourceTree = "<group>"; };
2D312B75102CA2E300F90022 /* table.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = table.c; sourceTree = "<group>"; };
2D312B79102CA30200F90022 /* notify_ipc.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = notify_ipc.defs; sourceTree = "<group>"; };
2D312B7C102CA32500F90022 /* notify_keys.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = notify_keys.h; sourceTree = "<group>"; };
2D312B7D102CA32500F90022 /* notify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = notify.h; sourceTree = "<group>"; };
2D312B81102CA34D00F90022 /* libnotify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libnotify.h; sourceTree = "<group>"; };
2D312B84102CA36C00F90022 /* notify_ipc_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = notify_ipc_types.h; sourceTree = "<group>"; };
2D312B85102CA36C00F90022 /* table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = table.h; sourceTree = "<group>"; };
2D312B88102CA38F00F90022 /* notify_cancel.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_cancel.3; sourceTree = "<group>"; };
2D312B89102CA38F00F90022 /* notify_check.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_check.3; sourceTree = "<group>"; };
2D312B8A102CA38F00F90022 /* notify_get_state.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_get_state.3; sourceTree = "<group>"; };
2D312B8B102CA38F00F90022 /* notify_post.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_post.3; sourceTree = "<group>"; };
2D312B8C102CA38F00F90022 /* notify_register_check.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_register_check.3; sourceTree = "<group>"; };
2D312B8D102CA38F00F90022 /* notify_register_dispatch.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_register_dispatch.3; sourceTree = "<group>"; };
2D312B8E102CA38F00F90022 /* notify_register_file_descriptor.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_register_file_descriptor.3; sourceTree = "<group>"; };
2D312B8F102CA38F00F90022 /* notify_register_mach_port.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_register_mach_port.3; sourceTree = "<group>"; };
2D312B90102CA38F00F90022 /* notify_register_signal.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_register_signal.3; sourceTree = "<group>"; };
2D312B91102CA38F00F90022 /* notify_set_state.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_set_state.3; sourceTree = "<group>"; };
2D312B92102CA38F00F90022 /* notify.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify.3; sourceTree = "<group>"; };
2D6D820D18DA602A0034E7B4 /* notify_is_valid_token.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = notify_is_valid_token.3; sourceTree = "<group>"; };
2DCB287110D99ADA00DF3A8D /* notify_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = notify_private.h; sourceTree = "<group>"; };
2DF9EA0B102CF33400DE9E8D /* APPLE_LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = APPLE_LICENSE; sourceTree = "<group>"; };
3F82235D12B18551005DD509 /* libnotify.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = libnotify.xcconfig; sourceTree = "<group>"; };
3F8223B412B18877005DD509 /* libsystem_notify.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_notify.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
3F947780191C322100A93E8E /* no-sim-man.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "no-sim-man.sh"; sourceTree = "<group>"; };
3F947781191C322100A93E8E /* sim-compat-symlink.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "sim-compat-symlink.sh"; sourceTree = "<group>"; };
3F999961185C474E00EAD3A0 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = "<group>"; };
3F999963185C474E00EAD3A0 /* notifyd.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = notifyd.xcconfig; sourceTree = "<group>"; };
3F999964185C474E00EAD3A0 /* notifyutil.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = notifyutil.xcconfig; sourceTree = "<group>"; };
3FA21A99148AA7FA00099D2F /* com.apple.notifyd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.notifyd.plist; sourceTree = "<group>"; };
3FA21A9A148AA7FA00099D2F /* notify.conf */ = {isa = PBXFileReference; lastKnownFileType = text; path = notify.conf; sourceTree = "<group>"; };
3FA21A9B148AA7FA00099D2F /* notify.conf.iPhone */ = {isa = PBXFileReference; lastKnownFileType = text; name = notify.conf.iPhone; path = ../notify.conf.iPhone; sourceTree = "<group>"; };
3FA21A9C148AA7FA00099D2F /* notify_proc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = notify_proc.c; sourceTree = "<group>"; };
3FA21A9D148AA7FA00099D2F /* notifyd.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = notifyd.8; sourceTree = "<group>"; };
3FA21A9E148AA7FA00099D2F /* notifyd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = notifyd.c; sourceTree = "<group>"; };
3FA21A9F148AA7FA00099D2F /* notifyd.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = notifyd.h; sourceTree = "<group>"; };
3FA21AA0148AA7FA00099D2F /* pathwatch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pathwatch.c; sourceTree = "<group>"; };
3FA21AA1148AA7FA00099D2F /* pathwatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pathwatch.h; sourceTree = "<group>"; };
3FA21AA2148AA7FA00099D2F /* service.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = service.c; sourceTree = "<group>"; };
3FA21AA3148AA7FA00099D2F /* service.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = service.h; sourceTree = "<group>"; };
3FA21AA4148AA7FA00099D2F /* table.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = table.h; sourceTree = "<group>"; };
3FA21AA5148AA7FA00099D2F /* timer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = "<group>"; };
3FA21AA6148AA7FA00099D2F /* timer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = timer.h; sourceTree = "<group>"; };
3FA21AA8148AA82700099D2F /* notifyutil.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = notifyutil.1; sourceTree = "<group>"; };
3FA21AA9148AA82700099D2F /* notifyutil.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = notifyutil.c; sourceTree = "<group>"; };
3FA21AB0148AA8E300099D2F /* notifyd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = notifyd; sourceTree = BUILT_PRODUCTS_DIR; };
3FA21ABE148AA8F000099D2F /* notifyutil */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = notifyutil; sourceTree = BUILT_PRODUCTS_DIR; };
3FA21ADD148AABA900099D2F /* mk_notify_conf.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = mk_notify_conf.sh; sourceTree = "<group>"; };
3FA21ADF148AACA000099D2F /* notify.conf.MacOSX */ = {isa = PBXFileReference; lastKnownFileType = text; name = notify.conf.MacOSX; path = notifyd/notify.conf.MacOSX; sourceTree = SOURCE_ROOT; };
3FD0DBAC148AB12000C50811 /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = "<absolute>"; };
FC7B7A52155781930064D203 /* notify_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = notify_internal.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
3FA21AAD148AA8E300099D2F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3FD0DBAD148AB12000C50811 /* libbsm.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
3FA21ABB148AA8F000099D2F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
D289987405E68DCB004EDB86 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
08FB7794FE84155DC02AAC07 /* Libnotify */ = {
isa = PBXGroup;
children = (
3F94777F191C322100A93E8E /* xcodescripts */,
3F999960185C474E00EAD3A0 /* xcodeconfig */,
2D312B79102CA30200F90022 /* notify_ipc.defs */,
3FA21A97148AA7CD00099D2F /* libsystem_notify */,
3FA21AA7148AA82700099D2F /* notifyutil */,
3FA21A98148AA7FA00099D2F /* notifyd */,
2DF9EA0A102CF31700DE9E8D /* Additional Files */,
3FA21ACE148AAA0D00099D2F /* Products */,
);
name = Libnotify;
sourceTree = "<group>";
};
2D312B72102CA2C400F90022 /* Source */ = {
isa = PBXGroup;
children = (
2D312B73102CA2E300F90022 /* libnotify.c */,
2D312B74102CA2E300F90022 /* notify_client.c */,
2D312B75102CA2E300F90022 /* table.c */,
);
name = Source;
sourceTree = "<group>";
};
2D312B7B102CA30600F90022 /* Public Headers */ = {
isa = PBXGroup;
children = (
2D312B7C102CA32500F90022 /* notify_keys.h */,
2D312B7D102CA32500F90022 /* notify.h */,
);
name = "Public Headers";
sourceTree = "<group>";
};
2D312B80102CA33600F90022 /* Private Headers */ = {
isa = PBXGroup;
children = (
2DCB287110D99ADA00DF3A8D /* notify_private.h */,
2D312B81102CA34D00F90022 /* libnotify.h */,
);
name = "Private Headers";
sourceTree = "<group>";
};
2D312B83102CA35300F90022 /* Project Headers */ = {
isa = PBXGroup;
children = (
FC7B7A52155781930064D203 /* notify_internal.h */,
2D312B84102CA36C00F90022 /* notify_ipc_types.h */,
2D312B85102CA36C00F90022 /* table.h */,
);
name = "Project Headers";
sourceTree = "<group>";
};
2DF9EA0A102CF31700DE9E8D /* Additional Files */ = {
isa = PBXGroup;
children = (
2DF9EA0B102CF33400DE9E8D /* APPLE_LICENSE */,
);
name = "Additional Files";
sourceTree = "<group>";
};
3F94777F191C322100A93E8E /* xcodescripts */ = {
isa = PBXGroup;
children = (
3F947780191C322100A93E8E /* no-sim-man.sh */,
3F947781191C322100A93E8E /* sim-compat-symlink.sh */,
);
path = xcodescripts;
sourceTree = "<group>";
};
3F999960185C474E00EAD3A0 /* xcodeconfig */ = {
isa = PBXGroup;
children = (
3F999961185C474E00EAD3A0 /* base.xcconfig */,
3F82235D12B18551005DD509 /* libnotify.xcconfig */,
3F999963185C474E00EAD3A0 /* notifyd.xcconfig */,
3F999964185C474E00EAD3A0 /* notifyutil.xcconfig */,
);
path = xcodeconfig;
sourceTree = "<group>";
};
3FA21A97148AA7CD00099D2F /* libsystem_notify */ = {
isa = PBXGroup;
children = (
2D312B83102CA35300F90022 /* Project Headers */,
2D312B80102CA33600F90022 /* Private Headers */,
2D312B7B102CA30600F90022 /* Public Headers */,
2D312B72102CA2C400F90022 /* Source */,
C6A0FF2B0290797F04C91782 /* Documentation */,
);
name = libsystem_notify;
sourceTree = "<group>";
};
3FA21A98148AA7FA00099D2F /* notifyd */ = {
isa = PBXGroup;
children = (
3FA21ADC148AABA900099D2F /* Build Support */,
3FA21A99148AA7FA00099D2F /* com.apple.notifyd.plist */,
3FA21A9A148AA7FA00099D2F /* notify.conf */,
3FA21AAA148AA85300099D2F /* Source */,
3FA21A9D148AA7FA00099D2F /* notifyd.8 */,
3FA21AAB148AA86600099D2F /* Private Headers */,
);
path = notifyd;
sourceTree = "<group>";
};
3FA21AA7148AA82700099D2F /* notifyutil */ = {
isa = PBXGroup;
children = (
3FA21AA8148AA82700099D2F /* notifyutil.1 */,
3FA21AA9148AA82700099D2F /* notifyutil.c */,
);
path = notifyutil;
sourceTree = "<group>";
};
3FA21AAA148AA85300099D2F /* Source */ = {
isa = PBXGroup;
children = (
3FA21A9C148AA7FA00099D2F /* notify_proc.c */,
3FA21A9E148AA7FA00099D2F /* notifyd.c */,
3FA21AA0148AA7FA00099D2F /* pathwatch.c */,
3FA21AA2148AA7FA00099D2F /* service.c */,
3FA21AA5148AA7FA00099D2F /* timer.c */,
);
name = Source;
sourceTree = "<group>";
};
3FA21AAB148AA86600099D2F /* Private Headers */ = {
isa = PBXGroup;
children = (
3FA21A9F148AA7FA00099D2F /* notifyd.h */,
3FA21AA1148AA7FA00099D2F /* pathwatch.h */,
3FA21AA3148AA7FA00099D2F /* service.h */,
3FA21AA4148AA7FA00099D2F /* table.h */,
3FA21AA6148AA7FA00099D2F /* timer.h */,
);
name = "Private Headers";
sourceTree = "<group>";
};
3FA21ACE148AAA0D00099D2F /* Products */ = {
isa = PBXGroup;
children = (
3F8223B412B18877005DD509 /* libsystem_notify.dylib */,
3FA21AB0148AA8E300099D2F /* notifyd */,
3FA21ABE148AA8F000099D2F /* notifyutil */,
);
name = Products;
sourceTree = "<group>";
};
3FA21ADC148AABA900099D2F /* Build Support */ = {
isa = PBXGroup;
children = (
3FD0DBAC148AB12000C50811 /* libbsm.dylib */,
3FA21ADF148AACA000099D2F /* notify.conf.MacOSX */,
3FA21A9B148AA7FA00099D2F /* notify.conf.iPhone */,
3FA21ADD148AABA900099D2F /* mk_notify_conf.sh */,
);
name = "Build Support";
path = xcodescripts;
sourceTree = "<group>";
};
C6A0FF2B0290797F04C91782 /* Documentation */ = {
isa = PBXGroup;
children = (
2D312B88102CA38F00F90022 /* notify_cancel.3 */,
2D312B89102CA38F00F90022 /* notify_check.3 */,
2D312B8A102CA38F00F90022 /* notify_get_state.3 */,
2D6D820D18DA602A0034E7B4 /* notify_is_valid_token.3 */,
2D312B8B102CA38F00F90022 /* notify_post.3 */,
2D312B8C102CA38F00F90022 /* notify_register_check.3 */,
2D312B8D102CA38F00F90022 /* notify_register_dispatch.3 */,
2D312B8E102CA38F00F90022 /* notify_register_file_descriptor.3 */,
2D312B8F102CA38F00F90022 /* notify_register_mach_port.3 */,
2D312B90102CA38F00F90022 /* notify_register_signal.3 */,
2D312B91102CA38F00F90022 /* notify_set_state.3 */,
2D312B92102CA38F00F90022 /* notify.3 */,
);
name = Documentation;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
D2AAC043055464E500DB518D /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
2D312B7E102CA32500F90022 /* notify_keys.h in Headers */,
2D312B7F102CA32500F90022 /* notify.h in Headers */,
2D312B82102CA34D00F90022 /* libnotify.h in Headers */,
2D312B87102CA36C00F90022 /* table.h in Headers */,
2DCB287210D99ADA00DF3A8D /* notify_private.h in Headers */,
FC7B7A53155781930064D203 /* notify_internal.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
3FA21AAF148AA8E300099D2F /* notifyd */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3FA21AB8148AA8E300099D2F /* Build configuration list for PBXNativeTarget "notifyd" */;
buildPhases = (
3FA21AAC148AA8E300099D2F /* Sources */,
3FA21AAD148AA8E300099D2F /* Frameworks */,
3FA21AAE148AA8E300099D2F /* Install man page */,
3FA21AD7148AAAA600099D2F /* Install launchd.plist */,
3FA21ADB148AAB1C00099D2F /* Install notify.conf */,
);
buildRules = (
);
dependencies = (
);
name = notifyd;
productName = notifyd;
productReference = 3FA21AB0148AA8E300099D2F /* notifyd */;
productType = "com.apple.product-type.tool";
};
3FA21ABD148AA8F000099D2F /* notifyutil */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3FA21AC5148AA8F000099D2F /* Build configuration list for PBXNativeTarget "notifyutil" */;
buildPhases = (
3FA21ABA148AA8F000099D2F /* Sources */,
3FA21ABB148AA8F000099D2F /* Frameworks */,
3FA21ABC148AA8F000099D2F /* Install man page */,
);
buildRules = (
);
dependencies = (
);
name = notifyutil;
productName = notifyutil;
productReference = 3FA21ABE148AA8F000099D2F /* notifyutil */;
productType = "com.apple.product-type.tool";
};
D2AAC045055464E500DB518D /* libnotify */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libnotify" */;
buildPhases = (
D2AAC043055464E500DB518D /* Headers */,
D2AAC044055464E500DB518D /* Sources */,
D289987405E68DCB004EDB86 /* Frameworks */,
2D38AA09102CD87C00D3D622 /* Copy man3 Files */,
3F947782191C324900A93E8E /* No Simulator Man Pages */,
3F947783191C327700A93E8E /* Sim compat symlink */,
);
buildRules = (
);
dependencies = (
);
name = libnotify;
productName = Libnotify;
productReference = 3F8223B412B18877005DD509 /* libsystem_notify.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
};
buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "Libnotify" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
Japanese,
French,
German,
);
mainGroup = 08FB7794FE84155DC02AAC07 /* Libnotify */;
productRefGroup = 08FB7794FE84155DC02AAC07 /* Libnotify */;
projectDirPath = "";
projectRoot = "";
targets = (
D2AAC045055464E500DB518D /* libnotify */,
3FA21AAF148AA8E300099D2F /* notifyd */,
3FA21ABD148AA8F000099D2F /* notifyutil */,
3FA21AC7148AA93000099D2F /* cli_apps */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
3F947782191C324900A93E8E /* No Simulator Man Pages */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
"$(SRCROOT)/xcodescripts/no-sim-man.sh",
);
name = "No Simulator Man Pages";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/bin/bash -e -x";
shellScript = "exec \"${SCRIPT_INPUT_FILE_0}\"";
};
3F947783191C327700A93E8E /* Sim compat symlink */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
"$(SRCROOT)/xcodescripts/sim-compat-symlink.sh",
);
name = "Sim compat symlink";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/bin/bash -e -x";
shellScript = "exec \"${SCRIPT_INPUT_FILE_0}\"";
};
3F947784191C32DC00A93E8E /* No Simulator Man Pages */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
"$(SRCROOT)/xcodescripts/no-sim-man.sh",
);
name = "No Simulator Man Pages";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/bin/bash -e -x";
shellScript = "exec \"${SCRIPT_INPUT_FILE_0}\"";
};
3FA21ADB148AAB1C00099D2F /* Install notify.conf */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
"$(SRCROOT)/notifyd/xcodescripts/mk_notify_conf.sh",
);
name = "Install notify.conf";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/bin/bash -e -x";
shellScript = "exec \"${SCRIPT_INPUT_FILE_0}\"";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
3FA21AAC148AA8E300099D2F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3FA21AE6148AAEAC00099D2F /* notify_ipc.defs in Sources */,
3FA21ACF148AAA5000099D2F /* notify_proc.c in Sources */,
3FA21AD0148AAA5000099D2F /* notifyd.c in Sources */,
3FA21AD1148AAA5000099D2F /* pathwatch.c in Sources */,
3FA21AD2148AAA5000099D2F /* service.c in Sources */,
3FA21AD3148AAA5000099D2F /* timer.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
3FA21ABA148AA8F000099D2F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3FA21AD5148AAA6E00099D2F /* notifyutil.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D2AAC044055464E500DB518D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2D312B7A102CA30200F90022 /* notify_ipc.defs in Sources */,
2D312B76102CA2E300F90022 /* libnotify.c in Sources */,
2D312B77102CA2E300F90022 /* notify_client.c in Sources */,
2D312B78102CA2E300F90022 /* table.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
3FA21ACB148AA94A00099D2F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 3FA21AAF148AA8E300099D2F /* notifyd */;
targetProxy = 3FA21ACA148AA94A00099D2F /* PBXContainerItemProxy */;
};
3FA21ACD148AA94A00099D2F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 3FA21ABD148AA8F000099D2F /* notifyutil */;
targetProxy = 3FA21ACC148AA94A00099D2F /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
1DEB91ED08733DB70010E9CD /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3F82235D12B18551005DD509 /* libnotify.xcconfig */;
buildSettings = {
};
name = Release;
};
1DEB91F108733DB70010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLY_RULES_IN_COPY_FILES = YES;
};
name = Release;
};
3FA21AB9148AA8E300099D2F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3F999963185C474E00EAD3A0 /* notifyd.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
3FA21AC6148AA8F000099D2F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3F999964185C474E00EAD3A0 /* notifyutil.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
3FA21AC9148AA93000099D2F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3F999961185C474E00EAD3A0 /* base.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libnotify" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB91ED08733DB70010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "Libnotify" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB91F108733DB70010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
3FA21AB8148AA8E300099D2F /* Build configuration list for PBXNativeTarget "notifyd" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3FA21AB9148AA8E300099D2F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
3FA21AC5148AA8F000099D2F /* Build configuration list for PBXNativeTarget "notifyutil" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3FA21AC6148AA8F000099D2F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
3FA21AC8148AA93000099D2F /* Build configuration list for PBXAggregateTarget "cli_apps" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3FA21AC9148AA93000099D2F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}

1544
libnotify/libnotify.c Normal file

File diff suppressed because it is too large Load Diff

216
libnotify/libnotify.h Normal file
View File

@ -0,0 +1,216 @@
/*
* Copyright (c) 2003-2012 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@
*/
#ifndef _LIBNOTIFY_H_
#define _LIBNOTIFY_H_
#include <pthread.h>
#include <mach/mach.h>
#include <dispatch/dispatch.h>
#include "table.h"
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR
extern const char *_notify_shm_id();
#define SHM_ID _notify_shm_id()
#else
#define SHM_ID "apple.shm.notification_center"
#endif
#define NOTIFY_IPC_VERSION_NAME "com.apple.system.notify.ipc_version"
#define NOTIFY_IPC_VERSION_NAME_LEN 35
#define NOTIFY_SERVICE_NAME "com.apple.system.notification_center"
#define NOTIFY_SERVICE_NAME_LEN 36
#define COMMON_PORT_KEY "com.apple.system.notify.common"
/* Notification types */
#define NOTIFY_TYPE_NONE 0x00000000
#define NOTIFY_TYPE_MEMORY 0x00000001
#define NOTIFY_TYPE_PLAIN 0x00000002
#define NOTIFY_TYPE_PORT 0x00000004
#define NOTIFY_TYPE_FILE 0x00000008
#define NOTIFY_TYPE_SIGNAL 0x00000010
#define NOTIFY_TYPE_MASK 0x000000ff
#define NOTIFY_FLAG_SELF 0x80000000
#define NOTIFY_FLAG_REGEN 0x40000000
#define NOTIFY_FLAG_RELEASE_SEND 0x20000000
/* Return values for notify_check() */
#define NOTIFY_CHECK_FALSE 0
#define NOTIFY_CHECK_TRUE 1
#define NOTIFY_CHECK_ERROR 2
/* Access control */
#define NOTIFY_ACCESS_READ 1
#define NOTIFY_ACCESS_WRITE 2
#define NOTIFY_ACCESS_OTHER_SHIFT 8
#define NOTIFY_ACCESS_GROUP_SHIFT 4
#define NOTIFY_ACCESS_USER_SHIFT 0
#define NOTIFY_ACCESS_DEFAULT 0x00000333
#define NOTIFY_ACCESS_USER_RW 0x00000003
/* Filesystem Services */
#define NOTIFY_SERVICE_FILE_STATUS_QUO 0x00
#define NOTIFY_SERVICE_FILE_ADD 0x01
#define NOTIFY_SERVICE_FILE_DELETE 0x02
#define NOTIFY_SERVICE_FILE_MODIFY 0x04
#define NOTIFY_SERVICE_FILE_ATTR 0x08
#define NOTIFY_SERVICE_DIR_FILE_ADD 0x10
#define NOTIFY_SERVICE_DIR_FILE_DELETE 0x20
#define NOTIFY_CLIENT_STATE_SUSPENDED 0x00000001
#define NOTIFY_CLIENT_STATE_PENDING 0x00000002
#define NOTIFY_CLIENT_STATE_TIMEOUT 0x00000004
#define NOTIFY_PORT_PROC_TYPE_PORT 0x00000010
#define NOTIFY_PORT_PROC_TYPE_PROC 0x00000020
#define NOTIFY_PORT_PROC_TYPE_MASK 0x000000f0
#define NOTIFY_PORT_PROC_STATE_INVALID 0x00000001
#define NOTIFY_PORT_PROC_STATE_SUSPENDED 0x00000002
#define NOTIFY_PORT_PROC_STATE_MASK 0x0000000f
/* notify state flags */
#define NOTIFY_STATE_USE_LOCKS 0x00000001
#define NOTIFY_STATE_ENABLE_RESEND 0x00000002
#define NOTIFY_CLIENT_SELF 0
#define SIGNAL_NONE -1
#define FD_NONE -1
#define SLOT_NONE -1
#define _notify_lib_port_new(A,B,C,D) _notify_lib_port_proc_new(A,B,0,C,D)
#define _notify_lib_proc_new(A,B,C,D) _notify_lib_port_proc_new(A,MACH_PORT_NULL,B,C,D)
#define _notify_lib_port_find(A,B) _notify_lib_port_proc_find(A,B,0)
#define _notify_lib_proc_find(A,B) _notify_lib_port_proc_find(A,MACH_PORT_NULL,B)
#define _notify_lib_port_release(A,B) _notify_lib_port_proc_release(A,B,0)
#define _notify_lib_proc_release(A,B) _notify_lib_port_proc_release(A,MACH_PORT_NULL,B)
typedef struct
{
char *name;
uint64_t name_id;
uint32_t uid;
uint32_t gid;
uint32_t access;
uint32_t slot;
uint32_t refcount;
uint32_t val;
uint64_t state;
uint64_t state_time;
void *private;
list_t *subscriptions;
} name_info_t;
typedef struct
{
uint64_t client_id;
uint32_t state;
name_info_t *name_info;
uint32_t suspend_count;
uint32_t notify_type;
uint32_t lastval;
mach_port_t port;
int fd;
uint32_t send_val;
uint32_t pid;
uint32_t sig;
void *private;
} client_t;
typedef struct
{
uint32_t refcount;
uint32_t flags;
dispatch_source_t src;
} portproc_data_t;
typedef struct
{
uint32_t flags;
table_t *name_table;
table_t *name_id_table;
table_t *client_table;
table_t *port_table;
table_t *proc_table;
name_info_t **controlled_name;
uint32_t controlled_name_count;
pthread_mutex_t *lock;
int sock;
uint32_t stat_name_alloc;
uint32_t stat_name_free;
uint32_t stat_client_alloc;
uint32_t stat_client_free;
uint32_t stat_portproc_alloc;
uint32_t stat_portproc_free;
} notify_state_t;
notify_state_t *_notify_lib_notify_state_new(uint32_t flags, uint32_t table_size);
void _notify_lib_notify_state_free(notify_state_t *ns);
uint32_t _notify_lib_post(notify_state_t *ns, const char *name, uint32_t uid, uint32_t gid);
uint32_t _notify_lib_post_nid(notify_state_t *ns, uint64_t nid, uid_t uid, gid_t gid);
uint32_t _notify_lib_post_client(notify_state_t *ns, client_t *c);
uint32_t _notify_lib_check(notify_state_t *ns, pid_t pid, int token, int *check);
uint32_t _notify_lib_get_state(notify_state_t *ns, uint64_t nid, uint64_t *state, uint32_t uid, uint32_t gid);
uint32_t _notify_lib_set_state(notify_state_t *ns, uint64_t nid, uint64_t state, uint32_t uid, uint32_t gid);
uint32_t _notify_lib_register_plain(notify_state_t *ns, const char *name, pid_t pid, int token, uint32_t slot, uint32_t uid, uint32_t gid, uint64_t *out_nid);
uint32_t _notify_lib_register_signal(notify_state_t *ns, const char *name, pid_t pid, int token, uint32_t sig, uint32_t uid, uint32_t gid, uint64_t *out_nid);
uint32_t _notify_lib_register_mach_port(notify_state_t *ns, const char *name, pid_t pid, int token, mach_port_t port, uint32_t uid, uint32_t gid, uint64_t *out_nid);
uint32_t _notify_lib_register_file_descriptor(notify_state_t *ns, const char *name, pid_t pid, int token, int fd, uint32_t uid, uint32_t gid, uint64_t *out_nid);
uint32_t _notify_lib_get_owner(notify_state_t *ns, const char *name, uint32_t *uid, uint32_t *gid);
uint32_t _notify_lib_get_access(notify_state_t *ns, const char *name, uint32_t *access);
uint32_t _notify_lib_set_owner(notify_state_t *ns, const char *name, uint32_t uid, uint32_t gid);
uint32_t _notify_lib_set_access(notify_state_t *ns, const char *name, uint32_t access);
uint32_t _notify_lib_release_name(notify_state_t *ns, const char *name, uint32_t uid, uint32_t gid);
void _notify_lib_cancel(notify_state_t *ns, pid_t pid, int token);
void _notify_lib_suspend(notify_state_t *ns, pid_t pid, int token);
uint32_t _notify_lib_resume(notify_state_t *ns, pid_t pid, int token);
void _notify_lib_cancel_proc(notify_state_t *ns, pid_t pid);
void _notify_lib_suspend_proc(notify_state_t *ns, pid_t pid);
void _notify_lib_resume_proc(notify_state_t *ns, pid_t pid);
void _notify_lib_suspend_port(notify_state_t *ns, mach_port_t port);
void _notify_lib_resume_port(notify_state_t *ns, mach_port_t port);
uint32_t _notify_lib_check_controlled_access(notify_state_t *ns, char *name, uid_t uid, gid_t gid, int req);
uint64_t make_client_id(pid_t pid, int token);
uint32_t _notify_lib_port_proc_new(notify_state_t *ns, mach_port_t port, pid_t proc, uint32_t state, dispatch_source_t src);
portproc_data_t *_notify_lib_port_proc_find(notify_state_t *ns, mach_port_t port, pid_t proc);
void _notify_lib_port_proc_release(notify_state_t *ns, mach_port_t port, pid_t proc);
#endif /* _LIBNOTIFY_H_ */

419
libnotify/notify.3 Normal file
View File

@ -0,0 +1,419 @@
.\" Copyright (c) 2003-2014 Apple Inc. All rights reserved.
.\"
.\" @APPLE_LICENSE_HEADER_START@
.\"
.\" Portions Copyright (c) 2003-2010 Apple Inc. All Rights Reserved.
.\"
.\" 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@
.\"
.\"
.Dd September 3, 2008
.Dt notify 3
.Os "Mac OS X"
.Sh NAME
.Nm notify_post ,
.Nm notify_register_check ,
.Nm notify_register_dispatch ,
.Nm notify_register_signal ,
.Nm notify_register_mach_port ,
.Nm notify_register_file_descriptor ,
.Nm notify_check ,
.Nm notify_get_state ,
.Nm notify_set_state ,
.Nm notify_suspend ,
.Nm notify_resume ,
.Nm notify_cancel ,
.Nm notify_is_valid_token
.Nd event distribution functions
.Sh SYNOPSIS
.Fd #include <notify.h>
.Ft uint32_t
.Fn notify_post "const char *name"
.Ft uint32_t
.Fn notify_register_check "const char *name, int *out_token"
.Ft uint32_t
.Fn notify_register_dispatch "const char *name, int *out_token" "dispatch_queue_t queue" "notify_handler_t handler"
.Ft uint32_t
.Fn notify_register_signal "const char *name, int sig, int *out_token"
.Ft uint32_t
.Fn notify_register_mach_port "const char *name, mach_port_t *notify_port, int flags, int *out_token"
.Ft uint32_t
.Fn notify_register_file_descriptor "const char *name, int *notify_fd, int flags, int *out_token"
.Ft uint32_t
.Fn notify_check "int token, int *check"
.Ft uint32_t
.Fn notify_set_state "int token, uint64_t state"
.Ft uint32_t
.Fn notify_get_state "int token, uint64_t *state"
.Ft uint32_t
.Fn notify_suspend "int token"
.Ft uint32_t
.Fn notify_resume "int token"
.Ft uint32_t
.Fn notify_cancel "int token"
.Ft bool
.Fn notify_is_valid_token "int val"
.Sh DESCRIPTION
These routines allow processes to exchange stateless notification events.
Processes post notifications to a single system-wide notification server,
which then distributes notifications to client processes that have
registered to receive those notifications, including processes run by
other users.
.Pp
Notifications are associated with names in a namespace shared by all
clients of the system.
Clients may post notifications for names, and
may monitor names for posted notifications.
Clients may request
notification delivery by a number of different methods.
.Pp
Clients desiring to monitor names in the notification system must
register with the system, providing a name and other information
required for the desired notification delivery method.
Clients are
given an integer token representing the registration.
Token values are zero or positive integers.
.Pp
The kernel provides limited queues for mach message and file descriptor messages.
It is important to make sure that clients read mach ports and file descriptors frequently
to prevent messages from being lost due to resource limitations.
Clients that use signal-based notification should be aware that signals
are not delivered to a process while it is running in a signal handler.
This may affect the delivery of signals in close succession.
.Pp
Notifications may be coalesced in some cases.
Multiple events posted
for a name in rapid succession may result in a single notification sent
to clients registered for notification for that name.
Clients checking
for changes using the notify_check() routine cannot determine if
more than one event has been posted since a previous call to
notify_check() for that name.
.Pp
"False positives" may occur in notify_check() when used with a token
generated by notify_register_check() due to implementation constraints.
This behavior may vary in future releases.
.Ss notify_post
This routine causes the system to send a notification for the given
name to all clients that have registered for notifications of this name.
This is the only API required for an application that only produces
notifications.
.Ss notify_register_check
Registers for passive notification for the given name.
The routine generates
a token that may be used with the
.Fn notify_check
routine to check if any notifications have been posted for the name.
The check is implemented using a shared memory scheme, making the check
very fast and efficient.
The implementation has a limited amount
of shared memory, so developers are encouraged to use this mechanism
sparingly.
It is also important to release the resources consumed
by a registration with
.Fn notify_cancel
when they are no longer required by the application.
.Ss notify_register_dispatch
registers a callback handler in the form of a block which will be
dispatched to the queue when a notification for the given name is
received. This is a convenient way to register callbacks without any
management of file descriptors, mach ports, or signals on the part of
the application. The given queue is retained by the system for the
lifetime of the notification. Use
.Fn notify_cancel
to release the notification and its reference to the queue.
.Ss notify_register_signal
registers a client for notification delivery via a signal.
This fits
well with the design of many UNIX daemons that use a signal such as SIGHUP
to reinitialize of reset internal state information.
Clients may use the
registration token generated by this routine to check for notifications using
.Fn notify_check .
This allows the application to determine if a signal was received as the
result of a notification, or if the signal was generated by some other source.
It also permits the application that registers for signal notification for
multiple names to determine which name was associated with the notification.
.Ss notify_register_mach_port
registers a client for notification delivery via mach messaging.
Notifications are delivered by an empty message sent to a mach port.
By default, a new port is created by a call to this routine.
A mach port
previously created by a call to this routine may be used for notifications
if a pointer to that port is passed in to the routine and NOTIFY_REUSE is
set in the flags parameter.
The notification service must be able to extract
send rights to the port.
.Pp
Note that the kernel limits the size of the message queue for any port.
If it is important that notifications should not be lost due to queue
overflow, clients should service messages quickly, and be cautious in
using the same port for notifications for more than one name.
.Pp
A notification message has an empty message body.
The msgh_id field
in the mach message header will have the value of the notification
token.
If a port is reused for multiple notification registrations,
the msgh_id value may be used to determine which name generated
the notification.
.Ss notify_register_file_descriptor
Register for notification by a write to a file descriptor.
.Pp
By default, a new file descriptor is created and a pointer to it
is returned as the value of the "notify_fd" parameter.
A file descriptor
created by a previous call to this routine may be used for notifications
if a pointer to that file descriptor is passed in to the routine and
NOTIFY_REUSE is set in the flags parameter.
.Pp
Note that the kernel limits the buffer space for queued writes on a
file descriptor.
If it is important that notifications should not be
lost due to queue overflow, clients should service messages quickly,
and be cautious in using the same file descriptor for notifications
for more than one name.
.Pp
Notifications are delivered by an integer value written to the
file descriptor.
The value is sent in network byte order.
When converted to host byte order, for example by using
.Fn ntohl ,
it will match the notification token
for which the notification was generated.
.Ss notify_check
Checks if any notifications have been posted for a name.
The output
parameter "check" is set to 0 for false, 1 for true.
A true indication is
returned the first time notify_check is called for a token.
Subsequent calls
give a true indication when notifications have been posted for the name
associated with the notification token.
.Pp
.Fn notify_check
may be used with any notification token produced by any of the notification
registration routines.
A fast check based on a shared memory implementation
is used when the token was generated by
.Fn notify_register_check .
Other tokens are checked by a call to the notification server.
.Ss notify_set_state
Set a 64-bit unsigned integer variable associated with a token.
.Pp
Each registered notification key has an associated 64-bit integer variable,
which may be set using this routine and examined using the
.Fn notify_get_state
routine.
The state variable is free to be used by clients of the notification API.
It may be used to synchronize state information between cooperating processes or threads.
(Available in Mac OS X 10.5 or later.)
.Ss notify_get_state
Get the 64-bit unsigned integer value associated with a token.
The default value of a state variable is zero.
(Available in Mac OS X 10.5 or later.)
.Ss notify_suspend
Suspends delivery of notifications for a notification token.
Any notifications corresponding to a token that are posted while it is suspended
will be coalesced, and pended until notifications are resumed using
.Fn notify_resume .
.Pp
Calls to
.Fn notify_suspend
may be nested.
Notifications will resume only when a matching number of calls are made to
.Fn notify_resume .
.Ss notify_resume
Removes one level of suspension for a token previously suspended by a call to
.Fn notify_suspend .
When resumed, notifications will be delivered normally.
A single notification will be generated if any notifications were pended while the token was suspended.
.Ss notify_cancel
Cancel notification and free resources associated with a notification
token.
Mach ports and file descriptor associated with a token are released
(deallocated or closed) when all registration tokens associated with
the port or file descriptor have been cancelled.
.Pp
.Ss notify_is_valid_token
Determines if an integer value is valid for a current registration.
Negative integers are never valid.
A positive or zero value is valid if the current process has a registration associated with the given value.
.Sh NAMESPACE CONVENTIONS
Names in the namespace must be NULL-terminated.
Names should be encoded as UTF-8 strings.
.Pp
The namespace supported by the system is unstructured, but users of
this API are highly encouraged to follow the reverse-ICANN domain
name convention used for Java package names and for System Preferences
on Mac OS X.
For example, "com.mydomain.example.event".
.Pp
Apple reserves the portion
of the namespace prefixed by "com.apple.".
This policy is not
enforced in the current implementation, but may be in the future.
.Pp
Names in the space "user.uid.UID", where UID is a numeric user ID number
are reserved for processes with that UID.
Names in this protected space may only be accessed or modified by processes
with the effective UID specified as the UID in the name.
The name "user.uid.UID" is protected for the given UID, as are any
names of the form "user.uid.UID.<sub-path>".
In the latter case, the name must have a dot character following the UID.
.Pp
Third party developers are encouraged to choose a prefix for names
that will avoid conflicts in the shared namespace.
.Pp
The portion of the namespace prefixed by the string "self." is set aside
for private use by applications.
That is, each client may use that part
of the namespace for intra-process notifications.
These notifications
are private to each individual process and are not propagated between
processes.
.Sh USAGE EXAMPLES
A notification producer.
.Pp
#include <notify.h>
...
.Pp
notify_post("com.eg.random.event");
.Pp
A client using notify_check() to determine when to invalidate a cache.
.Pp
#include <stdio.h>
#include <stdlib.h>
#include <notify.h>
.Pp
int
main(int argc, char *argv[])
{
uint32_t status;
int token, check;
.Pp
status = notify_register_check("com.eg.update", &token);
if (status != NOTIFY_STATUS_OK)
{
fprintf(stderr, "registration failed (%u)\\n", status);
exit(status);
}
.Pp
build_my_cache();
.Pp
...
.Pp
status = notify_check(token, &check);
if ((status == NOTIFY_STATUS_OK) && (check != 0))
{
/* An update has occurred - invalidate the cache */
reset_my_cache();
}
.Pp
...
.Pp
A client using file descriptor notifications.
.Pp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <notify.h>
.Pp
int
main(int argc, char *argv[])
{
uint32_t status;
int nf, rtoken, qtoken, t, ret;
fd_set readfds;
.Pp
status = notify_register_file_descriptor("com.eg.random.event",
&nf, 0, &rtoken);
if (status != NOTIFY_STATUS_OK)
{
fprintf(stderr, "registration failed (%u)\\n", status);
exit(status);
}
.Pp
status = notify_register_file_descriptor("com.eg.random.quit",
&nf, NOTIFY_REUSE, &qtoken);
if (status != NOTIFY_STATUS_OK)
{
fprintf(stderr, "registration failed (%u)\\n", status);
exit(status);
}
.Pp
FD_ZERO(&readfds);
FD_SET(nf, &readfds);
.Pp
for (;;)
{
ret = select(nf+1, &readfds, NULL, NULL, NULL);
if (ret <= 0) continue;
if (!FD_ISSET(nf, &readfds)) continue;
.Pp
status = read(nf, &t, sizeof(int));
if (status < 0)
{
perror("read");
break;
}
.Pp
t = ntohl(t);
.Pp
if (t == rtoken) printf("random event\\n");
else if (t == qtoken) break;
}
.Pp
printf("shutting down\\n");
notify_cancel(rtoken);
notify_cancel(qtoken);
exit(0);
}
.Pp
A client using dispatch notifications.
.Pp
#include <stdio.h>
#include <stdlib.h>
#include <notify.h>
#include <dispatch/dispatch.h>
.Pp
int
main(void)
{
uint32_t status;
int token;
.Pp
status = notify_register_dispatch("com.eg.random.event", &token,
dispatch_get_main_queue(), ^(int t) {
printf("com.eg.random.event received!\\n"); });
.Pp
dispatch_main();
exit(0);
}
.Sh HISTORY
These functions first appeared in
Mac OS X 10.3.
.Sh SEE ALSO
.Xr ntohl 3 ,
.Xr read 2 ,
.Xr select 2 ,
.Xr signal 3

338
libnotify/notify.h Normal file
View File

@ -0,0 +1,338 @@
/*
* Copyright (c) 2003-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 2003-2010 Apple Inc. All Rights Reserved.
*
* 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@
*/
#ifndef __NOTIFICATION_H__
#define __NOTIFICATION_H__
#include <sys/cdefs.h>
#include <stdint.h>
#include <mach/message.h>
#include <Availability.h>
#ifdef __BLOCKS__
#include <dispatch/dispatch.h>
#endif /* __BLOCKS__ */
/*! @header
* These routines allow processes to exchange stateless notification events.
* Processes post notifications to a single system-wide notification server,
* which then distributes notifications to client processes that have
* registered to receive those notifications, including processes run by
* other users.
*
* Notifications are associated with names in a namespace shared by all
* clients of the system. Clients may post notifications for names, and
* may monitor names for posted notifications. Clients may request
* notification delivery by a number of different methods.
*
* Clients desiring to monitor names in the notification system must
* register with the system, providing a name and other information
* required for the desired notification delivery method. Clients are
* given an integer token representing the registration.
*
* Note that the kernel provides limited queues for mach message and file
* descriptor messages. It is important to make sure that clients read
* mach ports and file descriptors frequently to prevent messages from
* being lost due to resource limitations. Clients that use signal-based
* notification should be aware that signals are not delivered to
* a process while it is running in a signal handler. This may affect
* the delivery of signals in close succession.
*
* Notifications may be coalesced in some cases. Multiple events posted
* for a name in rapid succession may result in a single notification sent
* to clients registered for notification for that name. Clients checking
* for changes using the notify_check() routine cannot determine if
* more than one event pas been posted since a previous call to
* notify_check() for that name.
*
* "False positives" may occur in notify_check() when used with a token
* generated by notify_register_check() due to implementation constraints.
* This behavior may vary in future releases.
*
* Synchronization between two processes may be achieved using the
* notify_set_state() and notify_get_state() routines.
*/
/*! @defineblock Status Codes
* Status codes returned by the API.
*/
#define NOTIFY_STATUS_OK 0
#define NOTIFY_STATUS_INVALID_NAME 1
#define NOTIFY_STATUS_INVALID_TOKEN 2
#define NOTIFY_STATUS_INVALID_PORT 3
#define NOTIFY_STATUS_INVALID_FILE 4
#define NOTIFY_STATUS_INVALID_SIGNAL 5
#define NOTIFY_STATUS_INVALID_REQUEST 6
#define NOTIFY_STATUS_NOT_AUTHORIZED 7
#define NOTIFY_STATUS_FAILED 1000000
/*! @/defineblock */
/*!
* Flag bits used for registration.
*/
#define NOTIFY_REUSE 0x00000001
/*!
* Token values are zero or positive integers.
* NOTIFY_TOKEN_INVALID is useful as an initial value for
* a token value passed as an in/out parameter to one of
* the registration routines below.
*/
#define NOTIFY_TOKEN_INVALID -1
__BEGIN_DECLS
/*!
* Post a notification for a name.
*
* This is the only call that is required for a notification producer.
* Returns status.
*/
uint32_t notify_post(const char *name);
#ifdef __BLOCKS__
typedef void (^notify_handler_t)(int token);
/*!
* @function notify_register
* @abstract Request notification delivery to a dispatch queue.
* @discussion When notifications are received by the process, the notify
* subsystem will deliver the registered Block to the target
* dispatch queue. Notification blocks are not re-entrant,
* and subsequent notification Blocks will not be delivered
* for the same registration until the previous Block has
* returned.
* @param name (input) The notification name.
* @param out_token (output) The registration token.
* @param queue (input) The dispatch queue to which the Block is submitted.
* The dispatch queue is retained by the notify subsystem while
* the notification is registered, and will be released when
* notification is canceled.
* @param block (input) The Block to invoke on the dispatch queue in response
* to a notification. The notification token is passed to the
* Block as an argument so that the callee can modify the state
* of the notification or cancel the registration.
* @result Returns status.
*/
uint32_t notify_register_dispatch(const char *name, int *out_token, dispatch_queue_t queue, notify_handler_t handler)
__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_3_2);
#endif /* __BLOCKS__ */
/*!
* Creates a registration token be used with notify_check(),
* but no active notifications will be delivered.
*
* @param name
* (input) notification name
* @param out_token
* (output) registration token
* @result Returns status.
*/
uint32_t notify_register_check(const char *name, int *out_token);
/*!
* Request notification delivery by UNIX signal.
*
* A client may request signal notification for multiple names. After a signal
* is delivered, the notify_check() routine may be called with each notification
* token to determine which name (if any) generated the signal notification.
*
* @param name (input) notification name
* @param sig (input) signal number (see signal(3))
* @param out_token (output) notification token
* @result Returns status.
*/
uint32_t notify_register_signal(const char *name, int sig, int *out_token);
/*!
* Request notification by mach message.
*
* Notifications are delivered by an empty message sent to a mach port.
* By default, a new port is allocated and a pointer to it is returned
* as the value of "notify_port". A mach port previously returned by a
* call to this routine may be used for notifications if a pointer to that
* port is passed in to the routine and NOTIFY_REUSE is set in the flags
* parameter. The notification service must be able to extract send
* rights to the port.
*
* Note that the kernel limits the size of the message queue for any port.
* If it is important that notifications should not be lost due to queue
* overflow, clients should service messages quickly, and be careful about
* using the same port for notifications for more than one name.
*
* A notification message has an empty message body. The msgh_id field
* in the mach message header will have the value of the notification
* token. If a port is reused for multiple notification registrations,
* the msgh_id value may be used to determine which name generated
* the notification.
*
* @param name
* (input) notification name
* @param out_token
* (output) notification token
* @param notify_port
* (input/output) pointer to a mach port
* @result Returns status.
*/
uint32_t notify_register_mach_port(const char *name, mach_port_t *notify_port, int flags, int *out_token);
/*
* Request notification by a write to a file descriptor.
*
* Notifications are delivered by a write to a file descriptor.
* By default, a new file descriptor is created and a pointer to it
* is returned as the value of "notify_fd". A file descriptor created
* by a previous call to this routine may be used for notifications if
* a pointer to that file descriptor is passed in to the routine and
* NOTIFY_REUSE is set in the flags parameter.
*
* Note that the kernel limits the buffer space for queued writes on a
* file descriptor. If it is important that notifications should not be
* lost due to queue overflow, clients should service messages quickly,
* and be careful about using the same file descriptor for notifications
* for more than one name.
*
* Notifications are delivered by an integer value written to the
* file descriptor. The value will match the notification token
* for which the notification was generated.
*
* @param name
* (input) notification name
* @param out_token
* (output) notification token
* @param notify_fd
* (input/output) pointer to a file descriptor
* @result Returns status.
*/
uint32_t notify_register_file_descriptor(const char *name, int *notify_fd, int flags, int *out_token);
/*!
* Check if any notifications have been posted.
*
* Output parameter check is set to 0 for false, 1 for true. Returns status.
* check is set to true the first time notify_check is called for a token.
* Subsequent calls set check to true when notifications have been posted for
* the name associated with the notification token. This routine is independent
* of notify_post(). That is, check will be true if an application calls
* notify_post() for a name and then calls notify_check() for a token associated
* with that name.
*
* @param token
* (input)notification token
* @param check
* (output) true/false indication
* @result Returns status.
*/
uint32_t notify_check(int token, int *check);
/*!
* Cancel notification and free resources associated with a notification
* token. Mach ports and file descriptor associated with a token are released
* (deallocated or closed) when all registration tokens associated with
* the port or file descriptor have been cancelled.
*
* @param token
* (input) notification token
* @result Returns status.
*/
uint32_t notify_cancel(int token);
/*!
* Suspend delivery of notifications for a token. Notifications for this token will be
* pended and coalesced, then delivered following a matching call to notify_resume.
* Calls to notify_suspend may be nested. Notifications remain suspended until
* an equal number of calls have been made to notify_resume.
*
* @param token
* (input) notification token
* @result Returns status.
*/
uint32_t notify_suspend(int token)
__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0);
/*!
* Removes one level of suspension for a token previously suspended
* by a call to notify_suspend. Notifications will resume when a matching
* call to notify_resume is made for each previous call to notify_suspend.
* Notifications posted while a token is suspended are coalesced into
* a single notification sent following a resumption.
*
* @param token
* (input) notification token
* @result Returns status.
*/
uint32_t notify_resume(int token)
__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0);
/*!
* Set or get a state value associated with a notification token.
* Each key in the notification namespace has an associated integer value available
* for use by clients as for application-specific purposes. A common usage is to
* allow two processes or threads to synchronize their activities. For example, a
* server process may need send a notification when a resource becomes available.
* A client process can register for the notification, but when it starts up it will
* not know whether the resource is available. The server can set the state value,
* and the client can check the value at startup time to synchronize with the server.
*
* Set the 64-bit integer state value.
*
* @param token
* (input) notification token
* @param state64
* (input) 64-bit unsigned integer value
* @result Returns status.
*/
uint32_t notify_set_state(int token, uint64_t state64)
__OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
/*!
* Get the 64-bit integer state value.
*
* @param token
* (input) notification token
* @param state64
* (output) 64-bit unsigned integer value
* @result Returns status.
*/
uint32_t notify_get_state(int token, uint64_t *state64)
__OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
/*!
* Determine if a token is valid (currently registered).
* Negative integer values are always invalid. Positive or
* zero values are valid only if they are associated with an
* existing registratiom.
*
* @param val
* (input) integer value
* @result Returns true if the value is a valid token, false otherwise.
*/
bool notify_is_valid_token(int val)
__OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0);
__END_DECLS
#endif /* __NOTIFICATION_H__ */

View File

@ -0,0 +1 @@
.so man3/notify.3

1
libnotify/notify_check.3 Normal file
View File

@ -0,0 +1 @@
.so man3/notify.3

2465
libnotify/notify_client.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
.so man3/notify.3

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2012 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 <dispatch/dispatch.h>
#include <mach/mach.h>
#include <pthread.h>
#include <stdint.h>
#include <TargetConditionals.h>
struct notify_globals_s {
// Global lock.
pthread_mutex_t notify_lock;
int32_t notify_ipc_version;
pid_t notify_server_pid;
uint32_t client_opts;
uint32_t saved_opts;
// Last allocated name id.
uint64_t name_id;
dispatch_once_t self_state_once;
notify_state_t *self_state;
dispatch_once_t notify_server_port_once;
mach_port_t notify_server_port;
mach_port_t saved_server_port;
mach_port_t notify_common_port;
int notify_common_token;
dispatch_source_t notify_dispatch_source;
dispatch_source_t server_proc_source;
dispatch_once_t token_table_once;
table_t *token_table;
table_t *token_name_table;
uint32_t token_id;
// File descriptor list.
uint32_t fd_count;
int *fd_clnt;
int *fd_srv;
int *fd_refcount;
// Mach port list.
uint32_t mp_count;
mach_port_t *mp_list;
int *mp_refcount;
int *mp_mine;
// Shared memory base address.
uint32_t *shm_base;
};
typedef struct notify_globals_s *notify_globals_t;
#if __has_include(<os/alloc_once_private.h>)
#include <os/alloc_once_private.h>
#if defined(OS_ALLOC_ONCE_KEY_LIBSYSTEM_NOTIFY)
#define _NOTIFY_HAS_ALLOC_ONCE 1
#endif
#endif
__attribute__((visibility("hidden")))
void _notify_init_globals(void * /* notify_globals_t */ globals);
__attribute__((visibility("hidden")))
notify_globals_t _notify_globals_impl(void);
__attribute__((__pure__))
static inline notify_globals_t
_notify_globals(void) {
#if _NOTIFY_HAS_ALLOC_ONCE
return (notify_globals_t)os_alloc_once(OS_ALLOC_ONCE_KEY_LIBSYSTEM_NOTIFY,
sizeof(struct notify_globals_s), &_notify_init_globals);
#else
return _notify_globals_impl();
#endif
}

373
libnotify/notify_ipc.defs Normal file
View File

@ -0,0 +1,373 @@
/*
* Copyright (c) 2003-2011 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 <mach/std_types.defs>
#include <mach/mach_types.defs>
subsystem notify_ipc 78945668;
serverprefix _;
import <sys/types.h>;
import "notify_ipc_types.h";
type notify_name = ^ array [] of MACH_MSG_TYPE_BYTE
ctype : caddr_t;
routine _notify_server_post
(
server : mach_port_t;
name : notify_name;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_register_plain
(
server : mach_port_t;
name : notify_name;
out token : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_register_check
(
server : mach_port_t;
name : notify_name;
out size : int;
out slot : int;
out token : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_register_signal
(
server : mach_port_t;
name : notify_name;
sig: int;
out token : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_register_file_descriptor
(
server : mach_port_t;
name : notify_name;
fileport : mach_port_move_send_t;
ntoken : int;
out token : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_register_mach_port
(
server : mach_port_t;
name : notify_name;
port : mach_port_move_send_t;
ntoken : int;
out token : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_set_owner
(
server : mach_port_t;
name : notify_name;
user : int;
group : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_get_owner
(
server : mach_port_t;
name : notify_name;
out user : int;
out group : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_set_access
(
server : mach_port_t;
name : notify_name;
mode : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_get_access
(
server : mach_port_t;
name : notify_name;
out mode : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_release_name
(
server : mach_port_t;
name : notify_name;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_cancel
(
server : mach_port_t;
token : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_check
(
server : mach_port_t;
token : int;
out check : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_get_state
(
server : mach_port_t;
token : int;
out state : uint64_t;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_set_state
(
server : mach_port_t;
token : int;
state : uint64_t;
out status : int;
ServerAuditToken audit : audit_token_t
);
skip; /* formerly _notify_server_get_val */
skip; /* formerly _notify_server_set_val */
routine _notify_server_monitor_file
(
server : mach_port_t;
token : int;
path : notify_name;
flags : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_suspend
(
server : mach_port_t;
token : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_resume
(
server : mach_port_t;
token : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_suspend_pid
(
server : mach_port_t;
pid : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_resume_pid
(
server : mach_port_t;
pid : int;
out status : int;
ServerAuditToken audit : audit_token_t
);
simpleroutine _notify_server_simple_post
(
server : mach_port_t;
name : notify_name;
ServerAuditToken audit : audit_token_t
);
/* Additions for version 2 - more async support */
routine _notify_server_post_2
(
server : mach_port_t;
name : notify_name;
out name_id : uint64_t;
out status : int;
ServerAuditToken audit : audit_token_t
);
simpleroutine _notify_server_post_3
(
server : mach_port_t;
name_id : uint64_t;
ServerAuditToken audit : audit_token_t
);
simpleroutine _notify_server_post_4
(
server : mach_port_t;
name : notify_name;
ServerAuditToken audit : audit_token_t
);
simpleroutine _notify_server_register_plain_2
(
server : mach_port_t;
name : notify_name;
token : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_register_check_2
(
server : mach_port_t;
name : notify_name;
token: int;
out size : int;
out slot : int;
out name_id : uint64_t;
out status : int;
ServerAuditToken audit : audit_token_t
);
simpleroutine _notify_server_register_signal_2
(
server : mach_port_t;
name : notify_name;
token : int;
sig: int;
ServerAuditToken audit : audit_token_t
);
simpleroutine _notify_server_register_file_descriptor_2
(
server : mach_port_t;
name : notify_name;
token: int;
fileport : mach_port_move_send_t;
ServerAuditToken audit : audit_token_t
);
simpleroutine _notify_server_register_mach_port_2
(
server : mach_port_t;
name : notify_name;
token: int;
port : mach_port_move_send_t;
ServerAuditToken audit : audit_token_t
);
simpleroutine _notify_server_cancel_2
(
server : mach_port_t;
token : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_get_state_2
(
server : mach_port_t;
name_id : uint64_t;
out state : uint64_t;
out status : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_get_state_3
(
server : mach_port_t;
token : int;
out state : uint64_t;
out nid : uint64_t;
out status : int;
ServerAuditToken audit : audit_token_t
);
simpleroutine _notify_server_set_state_2
(
server : mach_port_t;
name_id : uint64_t;
state : uint64_t;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_set_state_3
(
server : mach_port_t;
token : int;
state : uint64_t;
out nid : uint64_t;
out status : int;
ServerAuditToken audit : audit_token_t
);
simpleroutine _notify_server_monitor_file_2
(
server : mach_port_t;
token : int;
path : notify_name;
flags : int;
ServerAuditToken audit : audit_token_t
);
routine _notify_server_regenerate
(
server : mach_port_t;
name : notify_name;
token : int;
reg_type : uint32_t;
port : mach_port_make_send_t;
sig: int;
prev_slot: int;
prev_state : uint64_t;
prev_time : uint64_t;
path : notify_name;
path_flags: int;
out new_slot : int;
out new_name_id : uint64_t;
out status : int;
ServerAuditToken audit : audit_token_t
);

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2003-2009 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 2003-2009 Apple Inc. All Rights Reserved.
*
* 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@
*/
#ifndef _NOTIFY_IPC_TYPES_H_
#define _NOTIFY_IPC_TYPES_H_
#include <sys/types.h>
typedef char inline_data_t[2048];
#endif

View File

@ -0,0 +1 @@
.so man3/notify.3

83
libnotify/notify_keys.h Normal file
View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2007-2009 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 2007-2009 Apple Inc. All Rights Reserved.
*
* 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@
*/
/*
* This file lists notification keys that are posted using the
* notify_post() API by various Mac OS X system services.
* The exact circumstances under which services post these
* notifications is controlled by those services, and may change
* in future software releases.
*/
/*
* Directory Service notifications
* These are posted by the DirectoryService daemon to advise clients that
* cached data should be invalidated.
*/
#define kNotifyDSCacheInvalidation "com.apple.system.DirectoryService.InvalidateCache"
#define kNotifyDSCacheInvalidationGroup "com.apple.system.DirectoryService.InvalidateCache.group"
#define kNotifyDSCacheInvalidationHost "com.apple.system.DirectoryService.InvalidateCache.host"
#define kNotifyDSCacheInvalidationService "com.apple.system.DirectoryService.InvalidateCache.service"
#define kNotifyDSCacheInvalidationUser "com.apple.system.DirectoryService.InvalidateCache.user"
/*
* File System notifications
* These advise clients of various filesystem events.
*/
#define kNotifyVFSMount "com.apple.system.kernel.mount"
#define kNotifyVFSUnmount "com.apple.system.kernel.unmount"
#define kNotifyVFSUpdate "com.apple.system.kernel.mountupdate"
#define kNotifyVFSLowDiskSpace "com.apple.system.lowdiskspace"
#define kNotifyVFSLowDiskSpaceRootFS "com.apple.system.lowdiskspace.system"
#define kNotifyVFSLowDiskSpaceOtherFS "com.apple.system.lowdiskspace.user"
/*
* System Configuration notifications
* These advise clients of changes in the system configuration
* managed by the system configuration server (configd).
* Note that a much richer set of notifications are available to
* clients using the SCDynamicStore API.
*/
#define kNotifySCHostNameChange "com.apple.system.hostname"
#define kNotifySCNetworkChange "com.apple.system.config.network_change"
/*
* ASL notifications
* Sent by syslogd to advise clients that new log messages have been
* added to the ASL database.
*/
#define kNotifyASLDBUpdate "com.apple.system.logger.message"
/*
* Time Zone change notification
* Sent by notifyd when the system's timezone changes.
*/
#define kNotifyTimeZoneChange "com.apple.system.timezone"
/*
* System clock change notification
* Sent when a process modifies the system clock using the settimeofday system call.
*/
#define kNotifyClockSet "com.apple.system.clock_set"

1
libnotify/notify_post.3 Normal file
View File

@ -0,0 +1 @@
.so man3/notify.3

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2009-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@
*/
#ifndef __NOTIFY_PRIVATE_H__
#define __NOTIFY_PRIVATE_H__
#include <stdint.h>
#include <Availability.h>
#define NOTIFY_OPT_DEMUX 0x00000001
#define NOTIFY_OPT_REGEN 0x00000002
#define NOTIFY_OPT_ENABLE 0x04000000
#define NOTIFY_OPT_DISABLE 0x08000000
uint32_t notify_suspend_pid(pid_t pid)
__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
uint32_t notify_resume_pid(pid_t pid)
__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
uint32_t notify_simple_post(const char *name)
__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_3);
void notify_set_options(uint32_t opts)
__OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_6_0);
#endif /* __NOTIFY_PRIVATE_H__ */

View File

@ -0,0 +1 @@
.so man3/notify.3

View File

@ -0,0 +1 @@
.so man3/notify.3

View File

@ -0,0 +1 @@
.so man3/notify.3

View File

@ -0,0 +1 @@
.so man3/notify.3

View File

@ -0,0 +1 @@
.so man3/notify.3

View File

@ -0,0 +1 @@
.so man3/notify.3

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnableTransactions</key>
<true/>
<key>Label</key>
<string>com.apple.notifyd</string>
<key>EnvironmentVariables</key>
<dict>
<key>ASL_DISABLE</key>
<string>1</string>
</dict>
<key>MachServices</key>
<dict>
<key>com.apple.system.notification_center</key>
<true/>
</dict>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/notifyd</string>
</array>
<key>JetsamProperties</key>
<dict>
<key>JetsamPriority</key>
<integer>-1000</integer>
</dict>
<key>POSIXSpawnType</key>
<string>Interactive</string>
</dict>
</plist>

View File

@ -0,0 +1,10 @@
#
# Notification Center configuration file
#
reserve com.apple.system. 0 0 rwr-r-
monitor com.apple.system.timezone /etc/localtime
monitor com.apple.system.info:/etc/hosts /etc/hosts
monitor com.apple.system.info:/etc/services /etc/services
monitor com.apple.system.info:/etc/protocols /etc/protocols

View File

@ -0,0 +1,7 @@
#
# Notification Center configuration file
#
reserve com.apple.system. 0 0 rwr-r-
reserve com.apple.system.clock_set 0 501 rwrwr-
monitor com.apple.system.timezone /var/db/timezone/localtime

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
.\" Copyright (c) 2003-2013 Apple Inc. All rights reserved.
.\"
.\" @APPLE_LICENSE_HEADER_START@
.\"
.\" Portions Copyright (c) 2003-2010 Apple Inc. All Rights Reserved.
.\"
.\" 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@
.\"
.\"
.Dd March 24, 2003
.Dt notifyd 8
.Os "Mac OS X"
.Sh NAME
.Nm notifyd
.Nd notification server
.Sh SYNOPSIS
.Nm
.Op Fl d
.Op Fl log_file Ar path
.Op Fl shm_pages Ar npages
.Sh DESCRIPTION
.Nm
is the server for the Mac OS X notification system described in
.Xr notify 3 .
The server is started automatically by
.Nm launchd
during system startup.
.Pp
The
.Fl d
option causes
.Nm notifyd
to log debugging messages to a log file.
Messages are not logged to ASL to avoid potential deadlocks,
since the ASL system makes use of the
.Xr notify 3
system.
.Pp
The default log file is
.Pa /var/log/notifyd.log .
An alternate log file path may be specified following the
.Fl log_file
flag.
.Pp
The
.Fl shm_pages Ar npages
option sets the number of shared memory pages used for passive notification.
The default is one page.
If a value of zero is specified,
shared memory is disabled and passive notifications are performed
using IPC between the client and the server.
.Sh SEE ALSO
.Xr notify 3 .

1265
libnotify/notifyd/notifyd.c Normal file

File diff suppressed because it is too large Load Diff

101
libnotify/notifyd/notifyd.h Normal file
View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2003-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@
*/
#ifndef _NOTIFY_DAEMON_H_
#define _NOTIFY_DAEMON_H_
#include <libnotify.h>
#include <mach/mach.h>
#include <launch.h>
#include <dispatch/dispatch.h>
#define NOTIFY_IPC_VERSION 2
struct global_s
{
mach_port_t server_port;
launch_data_t launch_dict;
notify_state_t *notify_state;
dispatch_queue_t work_q;
dispatch_source_t mach_src;
dispatch_source_t sig_usr1_src;
dispatch_source_t sig_usr2_src;
dispatch_source_t sig_winch_src;
uint32_t request_size;
uint32_t reply_size;
uint32_t nslots;
uint32_t slot_id;
uint32_t *shared_memory_base;
uint32_t *shared_memory_refcount;
uint32_t *last_shm_base;
uint32_t log_cutoff;
uint32_t log_default;
char *log_path;
} global;
struct call_statistics_s
{
uint64_t post;
uint64_t post_no_op;
uint64_t post_by_id;
uint64_t post_by_name;
uint64_t post_by_name_and_fetch_id;
uint64_t reg;
uint64_t reg_plain;
uint64_t reg_check;
uint64_t reg_signal;
uint64_t reg_file;
uint64_t reg_port;
uint64_t cancel;
uint64_t suspend;
uint64_t resume;
uint64_t suspend_pid;
uint64_t resume_pid;
uint64_t check;
uint64_t get_state;
uint64_t get_state_by_client;
uint64_t get_state_by_id;
uint64_t get_state_by_client_and_fetch_id;
uint64_t set_state;
uint64_t set_state_by_client;
uint64_t set_state_by_id;
uint64_t set_state_by_client_and_fetch_id;
uint64_t get_owner;
uint64_t set_owner;
uint64_t get_access;
uint64_t set_access;
uint64_t monitor_file;
uint64_t service_timer;
uint64_t service_path;
uint64_t cleanup;
uint64_t regenerate;
} call_statistics;
extern void log_message(int priority, const char *str, ...);
extern uint32_t daemon_post(const char *name, uint32_t u, uint32_t g);
extern uint32_t daemon_post_nid(uint64_t nid, uint32_t u, uint32_t g);
extern void daemon_post_client(uint64_t cid);
extern void daemon_set_state(const char *name, uint64_t val);
extern void dump_status(uint32_t level);
#endif /* _NOTIFY_DAEMON_H_ */

View File

@ -0,0 +1,953 @@
/*
* Copyright (c) 2009-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@
*/
/*
* These routines, accessed through path_node_create() and path_node_release(),
* provide an API for monitoring a path in the filesystem. The path may contain
* directories and symbolic links. The path may not even exist! If the path
* does exist, this code will respond to path deletions, component renaming, and
* access control changes that either delete the path or make it inaccessible to a
* target user/group. A notification will be provided if the path comes back into
* existance or again becomes accessible.
*
* path_node_create() returns a path_node_t object, which contains a dispatch_source_t.
* This source behaves very much like a DISPATCH_SOURCE_TYPE_VNODE, except that it also
* triggers on the creation of a path.
*
* Internally, the work of monitoring a path is done by a set of helper vnode_t
* objects. A vnode_t contains a dispatch_source_t (of type DISPATCH_SOURCE_TYPE_VNODE)
* for a particular vnode. When a path_node_t is created, it creates (or shares)
* vnode_t objects for each component of the desired path. For example, a path_node_t
* for "/a/b/c" will create (or share, if some other path_node_t has already created) a
* dispatch_source_t for "/", "/a", "/a/b", and "/a/b/c". If any of these sources is
* notified of a change, the vnode_t will trigger an update for all path_node_t
* objects that contain that path component.
*
* When a path_node_t update is triggered by a vnode_t component, the node re-evaluates
* the target path that it is charged with monitoring. If the path exists and the end-point
* vnode changed, then the update operation will trigger its dispatch_source_t to notify the
* end-user of the change. If an intermediate path component is removed, renamed, or becomes
* blocked by an access-control change, then the end-point dispatch_source_t is triggered to
* indicate that the path has been deleted. However, the path_node_t remains active and
* monitors the path components that still exist. Eventually, if the path is recreated or
* if access controls change so that the path becomes visible to the target user, then the
* end-point dispatch_source_t is triggered with a PATH_NODE_CREATE bit set in its data flags.
*
* path_node_releases() releases a path_node_t object and all of the vnode_t objects
* that were monitoring components of its target path.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/syscall.h>
#include <sys/kauth.h>
#include <pwd.h>
#include <fcntl.h>
#include <assert.h>
#include <tzfile.h>
#include "pathwatch.h"
#define forever for(;;)
#define streq(A,B) (strcmp(A,B)==0)
#define DISPATCH_VNODE_ALL 0x7f
#define PATH_STAT_OK 0
#define PATH_STAT_FAILED 1
#define PATH_STAT_ACCESS 2
#define VPATH_NODE_TYPE_REG 0
#define VPATH_NODE_TYPE_LINK 1
#define VPATH_NODE_TYPE_DELETED 2
#define DISPATCH_VNODE_UNAVAIL (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE)
/* Libinfo global */
extern uint32_t gL1CacheEnabled;
/*
* vnode_t represents a vnode.
*
* The dispatch source is of type DISPATCH_SOURCE_TYPE_VNODE for file descriptor fd.
* The handler for the source triggers an update routine for all the path_node_t
* objects in the path_node list.
*/
typedef struct
{
char *path;
uint32_t type;
int fd;
struct timespec mtime;
struct timespec ctime;
dispatch_source_t src;
uint32_t path_node_count;
path_node_t **path_node;
} vnode_t;
static struct
{
dispatch_once_t pathwatch_init;
dispatch_queue_t pathwatch_queue;
uint32_t vnode_count;
vnode_t **vnode;
char *tzdir;
size_t tzdir_len;
} _global = {0};
/* forward */
static void _path_node_update(path_node_t *pnode, uint32_t flags, vnode_t *vnode);
/*
* stat() or lstat() a path as a particular user/group.
*/
static int
_path_stat(const char *path, int link, uid_t uid, gid_t gid)
{
struct stat sb;
gid_t orig_gidset[NGROUPS_MAX];
int ngroups, status, stat_status;
struct passwd *p;
uint32_t orig_cache_enabled;
/* disable L1 cache to avoid notification deadlock */
orig_cache_enabled = gL1CacheEnabled;
gL1CacheEnabled = 0;
/* get my group list */
memset(orig_gidset, 0, sizeof(orig_gidset));
ngroups = getgroups(NGROUPS_MAX, orig_gidset);
if (ngroups < 0)
{
return PATH_STAT_FAILED;
}
/* look up user name */
p = getpwuid(uid);
if (p == NULL)
{
gL1CacheEnabled = orig_cache_enabled;
return PATH_STAT_FAILED;
}
/* switch to user's grouplist */
status = initgroups(p->pw_name, gid);
if (status < 0)
{
gL1CacheEnabled = orig_cache_enabled;
return PATH_STAT_FAILED;
}
/* reset gL1CacheEnabled */
gL1CacheEnabled = orig_cache_enabled;
/* set thread credentials */
pthread_setugid_np(uid, gid);
/* stat the file */
stat_status = -1;
if (link != 0)
{
stat_status = lstat(path, &sb);
}
else
{
stat_status = stat(path, &sb);
}
/* unset thread credentials */
pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE);
/* restore original grouplist for UID 0 */
status = syscall(SYS_initgroups, ngroups, orig_gidset, 0);
if (status < 0)
{
return PATH_STAT_FAILED;
}
/* return status */
if (stat_status == 0)
{
return PATH_STAT_OK;
}
if (errno == EACCES)
{
return PATH_STAT_ACCESS;
}
return PATH_STAT_FAILED;
}
/*
* Check access to a path by a particular user/group.
* Sets ftype output parameter if it is non-NULL.
*/
static int
_path_stat_check_access(const char *path, uid_t uid, gid_t gid, uint32_t *ftype)
{
struct stat sb;
char buf[MAXPATHLEN + 1];
int status, t;
if (path == NULL) return PATH_STAT_FAILED;
if (ftype != NULL) *ftype = PATH_NODE_TYPE_GHOST;
/* Paths must be absolute */
if (path[0] != '/') return PATH_STAT_FAILED;
/* Root dir is readable */
if (path[1] == '\0')
{
if (ftype != NULL) *ftype = PATH_NODE_TYPE_DIR;
return PATH_STAT_OK;
}
memset(&sb, 0, sizeof(struct stat));
status = lstat(path, &sb);
if (status != 0) return PATH_STAT_FAILED;
else if ((sb.st_mode & S_IFMT) == S_IFDIR) t = PATH_NODE_TYPE_DIR;
else if ((sb.st_mode & S_IFMT) == S_IFREG) t = PATH_NODE_TYPE_FILE;
else if ((sb.st_mode & S_IFMT) == S_IFLNK) t = PATH_NODE_TYPE_LINK;
else t = PATH_NODE_TYPE_OTHER;
if (ftype != NULL) *ftype = t;
if (t == PATH_NODE_TYPE_OTHER) return PATH_STAT_FAILED;
/* skip access control check if uid is zero */
if (uid == 0) return 0;
/* special case: anything in the timezone directory is OK */
memset(buf, 0, sizeof(buf));
if (realpath(path, buf) == NULL) return PATH_STAT_FAILED;
if ((_global.tzdir != NULL) && (!strncasecmp(buf, _global.tzdir, _global.tzdir_len)))
{
return PATH_STAT_OK;
}
/* call _path_stat to check access as the user/group provided */
if (t == PATH_NODE_TYPE_FILE)
{
status = _path_stat(path, 0, uid, gid);
if ((status == PATH_STAT_ACCESS) && (ftype != NULL)) *ftype = PATH_NODE_TYPE_GHOST;
return status;
}
else if (t == PATH_NODE_TYPE_LINK)
{
status = _path_stat(path, 1, uid, gid);
if ((status == PATH_STAT_ACCESS) && (ftype != NULL)) *ftype = PATH_NODE_TYPE_GHOST;
return status;
}
else if (t == PATH_NODE_TYPE_DIR)
{
snprintf(buf, MAXPATHLEN, "%s/.", path);
status = _path_stat(buf, 0, uid, gid);
if ((status == PATH_STAT_ACCESS) && (ftype != NULL)) *ftype = PATH_NODE_TYPE_GHOST;
return status;
}
/* we don't ever get here, but... */
return PATH_STAT_FAILED;
}
/*
* Uniquely add a pnode to a vnode's list of path nodes.
*/
static void
_vnode_add_pnode(vnode_t *vnode, path_node_t *pnode)
{
uint32_t i;
for (i = 0; i < vnode->path_node_count; i++)
{
if (vnode->path_node[i] == pnode) return;
}
for (i = 0; i < vnode->path_node_count; i++)
{
if (vnode->path_node[i] == NULL)
{
vnode->path_node[i] = pnode;
return;
}
}
if (vnode->path_node_count == 0)
{
vnode->path_node = (path_node_t **)calloc(1, sizeof(path_node_t *));
}
else
{
vnode->path_node = (path_node_t **)reallocf(vnode->path_node, (vnode->path_node_count + 1) * sizeof(path_node_t *));
}
assert(vnode->path_node != NULL);
vnode->path_node[vnode->path_node_count++] = pnode;
}
/*
* Free a vnode_t and cancel/release its dispatch source.
*/
static void
_vnode_free(vnode_t *vnode)
{
dispatch_source_cancel(vnode->src);
/*
* Actually free the vnode on the pathwatch queue. This allows any
* enqueued _vnode_event operations to complete before the vnode disappears.
* _vnode_event() quietly returns if the source has been cancelled.
*/
dispatch_async(_global.pathwatch_queue, ^{
dispatch_release(vnode->src);
free(vnode->path);
free(vnode->path_node);
free(vnode);
});
}
/*
* Handler routine for vnode_t objects.
* Invokes the _path_node_update routine for all of the vnode's pnodes.
*/
static void
_vnode_event(vnode_t *vnode)
{
uint32_t i, flags;
unsigned long ulf;
struct stat sb;
if (vnode == NULL) return;
if ((vnode->src != NULL) && (dispatch_source_testcancel(vnode->src))) return;
ulf = dispatch_source_get_data(vnode->src);
flags = ulf;
memset(&sb, 0, sizeof(struct stat));
if (fstat(vnode->fd, &sb) == 0)
{
if ((vnode->mtime.tv_sec != sb.st_mtimespec.tv_sec) || (vnode->mtime.tv_nsec != sb.st_mtimespec.tv_nsec))
{
flags |= PATH_NODE_MTIME;
vnode->mtime = sb.st_mtimespec;
}
if ((vnode->ctime.tv_sec != sb.st_ctimespec.tv_sec) || (vnode->ctime.tv_nsec != sb.st_ctimespec.tv_nsec))
{
flags |= PATH_NODE_CTIME;
vnode->ctime = sb.st_ctimespec;
}
}
/*
* Flag deleted sources.
* We can't delete them here, since _path_node_update may need them.
* However, _path_node_update will release them and they will get cleaned
* up in a _vnode_sweep later on.
*/
if (flags & DISPATCH_VNODE_DELETE) vnode->type = VPATH_NODE_TYPE_DELETED;
for (i = 0; i < vnode->path_node_count; i++)
{
_path_node_update(vnode->path_node[i], flags, vnode);
}
}
/*
* Creates a vnode_t object.
*/
static vnode_t *
_vnode_create(const char *path, uint32_t type, path_node_t *pnode)
{
int fd, flags;
uint32_t i;
vnode_t *vnode;
dispatch_source_t src;
struct stat sb;
if (path == NULL) path = "/";
if (path[0] == '\0') path = "/";
for (i = 0; i < _global.vnode_count; i++)
{
vnode = _global.vnode[i];
if (vnode == NULL) continue;
if ((vnode->type == type) && (streq(path, vnode->path)))
{
_vnode_add_pnode(vnode, pnode);
return vnode;
}
}
vnode = NULL;
flags = O_EVTONLY;
if (type == VPATH_NODE_TYPE_LINK) flags |= O_SYMLINK;
fd = open(path, flags, 0);
if (fd < 0) return NULL;
src = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, (uintptr_t)fd, DISPATCH_VNODE_ALL, _global.pathwatch_queue);
if (src == NULL)
{
close(fd);
return NULL;
}
vnode = (vnode_t *)calloc(1, sizeof(vnode_t));
assert(vnode != NULL);
vnode->type = type;
vnode->path = strdup(path);
assert(vnode->path != NULL);
vnode->fd = fd;
vnode->src = src;
memset(&sb, 0, sizeof(struct stat));
if (fstat(fd, &sb) == 0)
{
vnode->mtime = sb.st_mtimespec;
vnode->ctime = sb.st_ctimespec;
}
_vnode_add_pnode(vnode, pnode);
dispatch_source_set_event_handler(src, ^{ _vnode_event(vnode); });
dispatch_source_set_cancel_handler(src, ^{ close(fd); });
if (_global.vnode_count == 0)
{
_global.vnode = (vnode_t **)calloc(1, sizeof(vnode_t *));
}
else
{
_global.vnode = (vnode_t **)reallocf(_global.vnode, (_global.vnode_count + 1) * sizeof(vnode_t *));
}
assert(_global.vnode != NULL);
_global.vnode[_global.vnode_count++] = vnode;
dispatch_resume(src);
return vnode;
}
static vnode_t *
_vnode_create_real_path(const char *path, uint32_t type, path_node_t *pnode)
{
char real[MAXPATHLEN + 1];
if (path == NULL) return _vnode_create(path, type, pnode);
if (NULL != realpath(path, real)) return _vnode_create(real, type, pnode);
return NULL;
}
/*
* Examines all the vnode_t objects (held in the _global data),
* frees any that have no path nodes.
*/
static void
_vnode_sweep()
{
uint32_t i, j, new_vnode_count, new_path_node_count;
vnode_t **new_source, *vnode;
path_node_t **new_path_node;
new_source = NULL;
for (i = 0; i < _global.vnode_count; i++)
{
vnode = _global.vnode[i];
if (vnode == NULL) continue;
new_path_node_count = 0;
new_path_node = NULL;
for (j = 0; j < vnode->path_node_count; j++)
{
if (vnode->path_node[j] != NULL) new_path_node_count++;
}
if (new_path_node_count == vnode->path_node_count)
{
/* no change */
continue;
}
else if (new_path_node_count > 0)
{
new_path_node = (path_node_t **)calloc(new_path_node_count, sizeof(path_node_t *));
assert(new_path_node != NULL);
new_path_node_count = 0;
for (j = 0; j < vnode->path_node_count; j++)
{
if (vnode->path_node[j] != NULL)
{
new_path_node[new_path_node_count++] = vnode->path_node[j];
}
}
}
free(vnode->path_node);
vnode->path_node = new_path_node;
vnode->path_node_count = new_path_node_count;
}
new_vnode_count = 0;
for (i = 0; i < _global.vnode_count; i++)
{
vnode = _global.vnode[i];
if (vnode == NULL) continue;
if (vnode->path_node_count > 0) new_vnode_count++;
}
if (new_vnode_count == _global.vnode_count)
{
/* no change */
return;
}
else if (new_vnode_count > 0)
{
new_source = (vnode_t **)calloc(new_vnode_count, sizeof(vnode_t *));
assert(new_source != NULL);
new_vnode_count = 0;
for (i = 0; i < _global.vnode_count; i++)
{
vnode = _global.vnode[i];
if (vnode == NULL) continue;
if (vnode->path_node_count > 0)
{
new_source[new_vnode_count++] = vnode;
}
else
{
_vnode_free(vnode);
}
}
}
free(_global.vnode);
_global.vnode = new_source;
_global.vnode_count = new_vnode_count;
}
/*
* Releases sources that have a particular node on their list.
* This is a deferred release mechanism for vnode_t objects.
* The calling routine must call _vnode_sweep subsequent to
* calling this routine.
* _vnode_sweep will actually free any vnode_t objects
* that have a no path nodes.
*/
static void
_vnode_release_for_node(path_node_t *pnode)
{
uint32_t i, j;
vnode_t *vnode;
for (i = 0; i < _global.vnode_count; i++)
{
vnode = _global.vnode[i];
if (vnode == NULL) continue;
for (j = 0; j < vnode->path_node_count; j++)
{
if (vnode->path_node[j] == pnode)
{
vnode->path_node[j] = NULL;
break;
}
}
}
}
/*
* Retain a path_node_t object.
* Dispatched on _global.pathwatch_queue.
*/
static void
_path_node_retain(path_node_t *pnode)
{
if (pnode == NULL) return;
pnode->refcount++;
}
/*
* Free a path_node_t object.
* Dispatched on _global.pathwatch_queue.
*/
static void
_path_node_free(path_node_t *pnode)
{
uint32_t i, n;
if (pnode == NULL) return;
/*
* Remove this path node from all vnodes.
*/
_vnode_release_for_node(pnode);
_vnode_sweep();
free(pnode->path);
if (pnode->pname != NULL)
{
n = pnode->pname_count;
pnode->pname_count = 0;
for (i = 0; i < n; i++)
{
free(pnode->pname[i]);
pnode->pname[i] = NULL;
}
free(pnode->pname);
}
free(pnode->contextp);
dispatch_release(pnode->src);
dispatch_release(pnode->src_queue);
memset(pnode, 0, sizeof(path_node_t));
free(pnode);
}
/*
* Release a path_node_t object.
*/
static void
_path_node_release(path_node_t *pnode)
{
if (pnode == NULL) return;
/*
* We need to make sure that the node's event handler isn't currently
* executing before freeing the node. We dispatch on the src_queue, so
* that when the block executes there will be no more events in the queue.
* From there, we dispatch async back to the pathwatch_queue to do the
* data structure cleanup.
*/
dispatch_async(pnode->src_queue, ^{
dispatch_async(_global.pathwatch_queue, ^{
if (pnode->refcount > 0) pnode->refcount--;
if (pnode->refcount == 0) _path_node_free(pnode);
});
});
}
/*
* Frees a path_node_t object.
* The work is actually done on the global pathwatch_queue to make this safe.
*/
void
path_node_close(path_node_t *pnode)
{
if (pnode == NULL) return;
if (pnode->src != NULL) dispatch_source_cancel(pnode->src);
_path_node_release(pnode);
}
static void
_pathwatch_init()
{
char buf[MAXPATHLEN];
/* Create serial queue for node creation / deletion operations */
_global.pathwatch_queue = dispatch_queue_create("pathwatch", NULL);
_global.tzdir = NULL;
_global.tzdir_len = 0;
/* Get the real path to TZDIR */
if (realpath(TZDIR, buf) != NULL)
{
_global.tzdir_len = strlen(buf);
_global.tzdir = strdup(buf);
if (_global.tzdir == NULL) _global.tzdir_len = 0;
}
}
/*
* _path_node_init is responsible for allocating a path_node_t structure,
* and for creating the pname array and setting the path component.
* The path is a sanatized version of the caller's path with redundant "/"
* characters stripped out. The pname array contains each "/" separated
* component of the path.
*
* For example, _path_node_init("///foo////bar//baz/") creates:
* pnode->path = "/foo/bar/baz"
* pnode->pname_count = 3
* pnode->pname[0] = "foo"
* pnode->pname[1] = "bar"
* pnode->pname[2] = "baz"
*/
static path_node_t *
_path_node_init(const char *path)
{
size_t len;
uint32_t i;
path_node_t *pnode;
const char *start, *end;
char *name;
if (path == NULL) path = "/";
if (path[0] != '/') return NULL;
pnode = (path_node_t *)calloc(1, sizeof(path_node_t));
assert(pnode != NULL);
pnode->plen = 1;
start = path;
while (*start == '/') start++;
forever
{
end = strchr(start, '/');
if (end == NULL) end = strchr(start, '\0');
len = end - start;
if (len == 0) break;
pnode->plen += (len + 1);
name = NULL;
if (end == NULL)
{
name = strdup(start);
}
else
{
name = malloc(len + 1);
assert(name != NULL);
strncpy(name, start, len);
name[len] = '\0';
}
if (pnode->pname_count == 0)
{
pnode->pname = (char **)calloc(1, sizeof(char *));
}
else
{
pnode->pname = (char **)reallocf(pnode->pname, (pnode->pname_count + 1) * sizeof(char *));
}
assert(pnode->pname != NULL);
pnode->pname[pnode->pname_count] = name;
pnode->pname_count++;
start = end;
if (start != NULL)
{
/* skip '/' chars */
while (*start == '/') start++;
}
}
pnode->path = calloc(1, pnode->plen);
assert(pnode->path != NULL);
/*
* Reconstruct the path here to strip out excess "/" chars.
* This ensures that path comparisons in _path_node_update are correct.
*/
for (i = 0; i < pnode->pname_count; i++)
{
strlcat(pnode->path, "/", pnode->plen);
strlcat(pnode->path, pnode->pname[i], pnode->plen);
}
return pnode;
}
/* dispatched on _global.pathwatch_queue */
static void
_path_node_update(path_node_t *pnode, uint32_t flags, vnode_t *vnode)
{
char *buf, fixed[MAXPATHLEN + 1];
uint32_t i, old_type;
int status;
unsigned long data;
struct stat sb;
if (pnode == NULL) return;
if ((pnode->src != NULL) && (dispatch_source_testcancel(pnode->src))) return;
old_type = pnode->type;
status = _path_stat_check_access(pnode->path, pnode->uid, pnode->gid, &(pnode->type));
if (status == PATH_STAT_ACCESS) flags |= DISPATCH_VNODE_REVOKE;
data = 0;
if (vnode != NULL)
{
/* update status */
if (flags & DISPATCH_VNODE_UNAVAIL)
{
pnode->type = PATH_NODE_TYPE_GHOST;
data |= (flags & DISPATCH_VNODE_UNAVAIL);
data |= DISPATCH_VNODE_DELETE;
}
if ((vnode->path != NULL) && (pnode->path != NULL) && streq(vnode->path, pnode->path))
{
/* this is the target VNODE - transfer flags to src data */
data |= flags;
}
if (old_type == PATH_NODE_TYPE_GHOST)
{
/* transition from ghost to non-ghost */
if (pnode->type != PATH_NODE_TYPE_GHOST)
{
data |= PATH_NODE_CREATE;
}
else
{
data = 0;
}
}
else if (pnode->type == PATH_NODE_TYPE_GHOST)
{
/* transition from non-ghost to ghost */
data |= PATH_NODE_DELETE;
}
data &= (pnode->flags & PATH_NODE_ALL);
if (data != 0)
{
if ((pnode->flags & PATH_SRC_SUSPENDED) == 0)
{
/* suspend pnode->src, and fire it after PNODE_COALESCE_TIME */
pnode->flags |= PATH_SRC_SUSPENDED;
dispatch_suspend(pnode->src);
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, PNODE_COALESCE_TIME);
_path_node_retain(pnode);
dispatch_after(delay, _global.pathwatch_queue, ^{
pnode->flags &= ~PATH_SRC_SUSPENDED;
dispatch_resume(pnode->src);
_path_node_release(pnode);
});
}
dispatch_source_merge_data(pnode->src, data);
}
}
buf = NULL;
if (pnode->plen < MAXPATHLEN) buf = fixed;
else buf = malloc(pnode->plen);
assert(buf != NULL);
/* "autorelease" current sources (_vnode_sweep() will delete those with zero refcount) */
_vnode_release_for_node(pnode);
/* create new sources (may re-use existing sources) */
_vnode_create(NULL, 0, pnode);
memset(buf, 0, pnode->plen);
for (i = 0; i < pnode->pname_count; i++)
{
assert((strlen(buf) + 1) <= pnode->plen);
strlcat(buf, "/", pnode->plen);
assert(pnode->pname[i] != NULL);
assert((strlen(buf) + strlen(pnode->pname[i])) <= pnode->plen);
strlcat(buf, pnode->pname[i], pnode->plen);
memset(&sb, 0, sizeof(struct stat));
if (lstat(buf, &sb) < 0)
{
/* the path stops existing here */
break;
}
if ((sb.st_mode & S_IFMT) == S_IFLNK)
{
/* open the symlink itself */
_vnode_create(buf, VPATH_NODE_TYPE_LINK, pnode);
/* open the symlink target */
_vnode_create_real_path(buf, 0, pnode);
}
else
{
_vnode_create(buf, 0, pnode);
}
}
/* sweep source list (deletes those with zero refcount) */
_vnode_sweep();
if (buf != fixed) free(buf);
}
/*
* Creates a dispatch source that activates when a path changes.
* Internally, creates a data structure (path_node_t) that represents the entire path.
* Also creates dispatch sources (vnode_t) for each path component. These vnodes may
* be shared with other path_node_t structures.
*/
path_node_t *
path_node_create(const char *path, uid_t uid, gid_t gid, uint32_t mask, dispatch_queue_t queue)
{
path_node_t *pnode;
dispatch_once(&(_global.pathwatch_init), ^{ _pathwatch_init(); });
pnode = _path_node_init(path);
if (pnode == NULL) return NULL;
pnode->refcount = 1;
pnode->uid = uid;
pnode->gid = gid;
dispatch_sync(_global.pathwatch_queue, ^{ _path_node_update(pnode, 0, NULL); });
dispatch_retain(queue);
pnode->src = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_OR, 0, 0, queue);
pnode->src_queue = queue;
pnode->flags = mask & PATH_NODE_ALL;
return pnode;
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2009-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@
*/
#ifndef _PATHWATCH_H_
#define _PATHWATCH_H_
#include <dispatch/dispatch.h>
/*
* types for virtual path nodes (path_node_t)
*/
#define PATH_NODE_TYPE_GHOST 0
#define PATH_NODE_TYPE_FILE 1
#define PATH_NODE_TYPE_LINK 2
#define PATH_NODE_TYPE_DIR 3
#define PATH_NODE_TYPE_OTHER 4
enum
{
PATH_NODE_DELETE = 0x0001, /* node or path deleted */
PATH_NODE_WRITE = 0x0002, /* node written */
PATH_NODE_EXTEND = 0x0004, /* node extended */
PATH_NODE_ATTRIB = 0x0008, /* node attributes changed (mtime or ctime) */
PATH_NODE_LINK = 0x0010, /* node link count changed */
PATH_NODE_RENAME = 0x0020, /* node renamed, always accompanied by PATH_NODE_DELETE */
PATH_NODE_REVOKE = 0x0040, /* access revoked, always accompanied by PATH_NODE_DELETE */
PATH_NODE_CREATE = 0x0080, /* path created or access re-acquired */
PATH_NODE_MTIME = 0x0100, /* path mtime changed, always accompanied by PATH_NODE_ATTRIB */
PATH_NODE_CTIME = 0x0200 /* path ctime changed, always accompanied by PATH_NODE_ATTRIB */
};
/* all bits mask */
#define PATH_NODE_ALL 0x000003ff
/* src is suspended */
#define PATH_SRC_SUSPENDED 0x10000000
/* Path changes coalesce for 100 milliseconds */
#define PNODE_COALESCE_TIME 100000000
/*
* path_node_t represents a virtual path
*/
typedef struct
{
char *path;
size_t plen;
uid_t uid;
gid_t gid;
uint32_t pname_count;
char **pname;
uint32_t type;
uint32_t flags;
dispatch_source_t src;
dispatch_queue_t src_queue;
void *contextp;
uint32_t context32;
uint64_t context64;
uint32_t refcount;
} path_node_t;
path_node_t *path_node_create(const char *path, uid_t uid, gid_t gid, uint32_t mask, dispatch_queue_t queue);
void path_node_close(path_node_t *pnode);
#endif /* _PATHWATCH_H_ */

523
libnotify/notifyd/service.c Normal file
View File

@ -0,0 +1,523 @@
/*
* Copyright (c) 2003-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 <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <asl.h>
#include "notify.h"
#include "notifyd.h"
#include "service.h"
#include "pathwatch.h"
#include "timer.h"
#define NOTIFY_PATH_SERVICE "path:"
#define NOTIFY_PATH_SERVICE_LEN 5
#define NOTIFY_TIMER_SERVICE "timer:"
#define NOTIFY_TIMER_SERVICE_LEN 6
/* Libinfo global */
extern uint32_t gL1CacheEnabled;
static uint32_t
service_type(const char *name)
{
uint32_t len;
len = SERVICE_PREFIX_LEN;
if (strncmp(name, SERVICE_PREFIX, len)) return SERVICE_TYPE_NONE;
else if (!strncmp(name + len, NOTIFY_PATH_SERVICE, NOTIFY_PATH_SERVICE_LEN)) return SERVICE_TYPE_PATH_PRIVATE;
else if (!strncmp(name + len, NOTIFY_TIMER_SERVICE, NOTIFY_TIMER_SERVICE_LEN)) return SERVICE_TYPE_TIMER_PRIVATE;
return SERVICE_TYPE_NONE;
}
/*
* Request notifications for changes on a filesystem path.
* This creates a new pathwatch node and sets it to post notifications for
* the specified name.
*
* If the notify name already has a pathwatch node for this path, this routine
* does nothing and allows the client to piggypack on the existing path watcher.
*
* Note that this routine is only called for path monitoring as directed by
* a "monitor" command in /etc/notify.conf, so only an admin can set up a path
* that gets public notifications. A client being serviced by the server-side
* routines in notify_proc.c will only be able to register for a private
* (per-client) notification for a path. This prevents a client from
* piggybacking on another client's notifications, and thus prevents the client
* from getting notifications for a path to which they don't have access.
*/
int
service_open_path(const char *name, const char *path, uid_t uid, gid_t gid)
{
name_info_t *n;
svc_info_t *info;
path_node_t *node;
call_statistics.service_path++;
if (path == NULL) return NOTIFY_STATUS_INVALID_REQUEST;
n = (name_info_t *)_nc_table_find(global.notify_state->name_table, name);
if (n == NULL) return NOTIFY_STATUS_INVALID_NAME;
if (n->private != NULL)
{
/* a notify key may only have one service associated with it */
info = (svc_info_t *)n->private;
if (info->type != SERVICE_TYPE_PATH_PUBLIC) return NOTIFY_STATUS_INVALID_REQUEST;
/* the client must be asking for the same path that is being monitored */
node = (path_node_t *)info->private;
if (strcmp(path, node->path)) return NOTIFY_STATUS_INVALID_REQUEST;
/* the name is already getting notifications for this path */
return NOTIFY_STATUS_OK;
}
node = path_node_create(path, uid, gid, PATH_NODE_ALL, dispatch_get_main_queue());
if (node == NULL) return NOTIFY_STATUS_FAILED;
node->contextp = strdup(name);
info = (svc_info_t *)calloc(1, sizeof(svc_info_t));
assert(info != NULL);
info->type = SERVICE_TYPE_PATH_PUBLIC;
info->private = node;
n->private = info;
dispatch_source_set_event_handler(node->src, ^{
dispatch_async(global.work_q, ^{
if (0 == dispatch_source_testcancel(node->src))
{
daemon_post((const char *)node->contextp, uid, gid);
}
});
});
dispatch_resume(node->src);
return NOTIFY_STATUS_OK;
}
/*
* The private (per-client) path watch service.
*/
int
service_open_path_private(const char *name, client_t *c, const char *path, uid_t uid, gid_t gid, uint32_t flags)
{
name_info_t *n;
svc_info_t *info;
path_node_t *node;
call_statistics.service_path++;
if (path == NULL) return NOTIFY_STATUS_INVALID_REQUEST;
n = (name_info_t *)_nc_table_find(global.notify_state->name_table, name);
if (n == NULL) return NOTIFY_STATUS_INVALID_NAME;
if (c == NULL) return NOTIFY_STATUS_FAILED;
if (c->private != NULL)
{
/* a client may only have one service */
info = (svc_info_t *)c->private;
if (info->type != SERVICE_TYPE_PATH_PRIVATE) return NOTIFY_STATUS_INVALID_REQUEST;
/* the client must be asking for the same path that is being monitored */
node = (path_node_t *)info->private;
if (strcmp(path, node->path)) return NOTIFY_STATUS_INVALID_REQUEST;
/* the client is already getting notifications for this path */
return NOTIFY_STATUS_OK;
}
if (flags == 0) flags = PATH_NODE_ALL;
node = path_node_create(path, uid, gid, flags, dispatch_get_main_queue());
if (node == NULL) return NOTIFY_STATUS_FAILED;
node->context64 = c->client_id;
info = (svc_info_t *)calloc(1, sizeof(svc_info_t));
assert(info != NULL);
info->type = SERVICE_TYPE_PATH_PRIVATE;
info->private = node;
c->private = info;
dispatch_source_set_event_handler(node->src, ^{
dispatch_async(global.work_q, ^{
if (0 == dispatch_source_testcancel(node->src))
{
daemon_post_client(node->context64);
}
});
});
dispatch_resume(node->src);
return NOTIFY_STATUS_OK;
}
/* format: [+]nnnn[s|m|h|d] */
static int
parse_single_arg(const char *arg, int relative_ok, time_t *t)
{
const char *p, *q;
time_t now, val;
if (arg == NULL) return -1;
p = arg;
now = 0;
if ((relative_ok != 0) && ((*p == '+') || (*p == '-')))
{
p++;
now = time(NULL);
}
if ((*p < '0') || (*p > '9')) return -1;
q = strchr(p, '.');
if (q != NULL) q--;
else q = arg + strlen(arg) - 1;
#ifdef __LP64__
val = (time_t)atoll(p);
#else
val = (time_t)atoi(p);
#endif
if ((*q >= '0') && (*q <= '9'))
{}
else if (*q == 's')
{}
else if (*q == 'm')
{
val *= 60;
}
else if (*q == 'h')
{
val *= 3600;
}
else if (*q == 'd')
{
val *= 86400;
}
else
{
return -1;
}
if (*arg == '-') *t = now - val;
else *t = now + val;
return 0;
}
static uint32_t
parse_timer_args(const char *args, time_t *s, time_t *f, time_t *e, int32_t *d)
{
char *p;
uint32_t t;
if (args == NULL) return TIME_EVENT_NONE;
/* first arg is start time */
if (parse_single_arg(args, 1, s) != 0) return TIME_EVENT_NONE;
t = TIME_EVENT_ONESHOT;
p = strchr(args, '.');
if (p != NULL)
{
/* second arg is frequency */
p++;
if (parse_single_arg(p, 0, f) != 0) return TIME_EVENT_NONE;
t = TIME_EVENT_CLOCK;
p = strchr(p, '.');
if (p != NULL)
{
/* third arg is end time */
p++;
if (parse_single_arg(args, 1, e) != 0) return TIME_EVENT_NONE;
p = strchr(p, '.');
if (p != NULL)
{
/* fourth arg is day number */
p++;
*d = atoi(p);
t = TIME_EVENT_CAL;
}
}
}
if (f == 0) t = TIME_EVENT_ONESHOT;
return t;
}
int
service_open_timer(const char *name, const char *args)
{
uint32_t t;
time_t s, f, e;
int32_t d;
name_info_t *n;
svc_info_t *info;
timer_t *timer;
call_statistics.service_timer++;
n = (name_info_t *)_nc_table_find(global.notify_state->name_table, name);
if (n == NULL) return NOTIFY_STATUS_INVALID_NAME;
s = f = e = 0;
d = 0;
t = parse_timer_args(args, &s, &f, &e, &d);
if (t == TIME_EVENT_NONE) return NOTIFY_STATUS_INVALID_REQUEST;
if (n->private != NULL)
{
/* a notify key may only have one service associated with it */
info = (svc_info_t *)n->private;
if (info->type != SERVICE_TYPE_TIMER_PUBLIC) return NOTIFY_STATUS_INVALID_REQUEST;
/* the client must be asking for the same timer that is active */
timer = (timer_t *)info->private;
if ((timer->type != t) || (timer->start != s) || (timer->freq != f) || (timer->end != e) || (timer->day != d)) return NOTIFY_STATUS_INVALID_REQUEST;
/* the name is already getting notifications for this timer */
return NOTIFY_STATUS_OK;
}
switch (t)
{
case TIME_EVENT_ONESHOT:
{
timer = timer_oneshot(s, dispatch_get_main_queue());
break;
}
case TIME_EVENT_CLOCK:
{
timer = timer_clock(s, f, e, dispatch_get_main_queue());
break;
}
case TIME_EVENT_CAL:
{
timer = timer_calendar(s, f, d, e, dispatch_get_main_queue());
break;
}
default:
{
return NOTIFY_STATUS_FAILED;
}
}
if (timer == NULL) return NOTIFY_STATUS_FAILED;
timer->contextp = strdup(name);
info = (svc_info_t *)calloc(1, sizeof(svc_info_t));
assert(info != NULL);
info->type = SERVICE_TYPE_TIMER_PUBLIC;
info->private = timer;
n->private = info;
dispatch_source_set_event_handler(timer->src, ^{
dispatch_async(global.work_q, ^{
if (0 == dispatch_source_testcancel(timer->src))
{
daemon_post((const char *)timer->contextp, 0, 0);
}
});
});
dispatch_resume(timer->src);
return NOTIFY_STATUS_OK;
}
int
service_open_timer_private(const char *name, client_t *c, const char *args)
{
uint32_t t;
time_t s, f, e;
int32_t d;
name_info_t *n;
svc_info_t *info;
timer_t *timer;
call_statistics.service_timer++;
n = (name_info_t *)_nc_table_find(global.notify_state->name_table, name);
if (n == NULL) return NOTIFY_STATUS_INVALID_NAME;
if (c == NULL) return NOTIFY_STATUS_FAILED;
s = f = e = 0;
d = 0;
t = parse_timer_args(args, &s, &f, &e, &d);
if (t == TIME_EVENT_NONE) return NOTIFY_STATUS_INVALID_REQUEST;
if (c->private != NULL)
{
/* a client may only have one service */
info = (svc_info_t *)c->private;
if (info->type != SERVICE_TYPE_TIMER_PRIVATE) return NOTIFY_STATUS_INVALID_REQUEST;
/* the client must be asking for the same timer that is active */
timer = (timer_t *)info->private;
if ((timer->type != t) || (timer->start != s) || (timer->freq != f) || (timer->end != e) || (timer->day != d)) return NOTIFY_STATUS_INVALID_REQUEST;
/* the client is already getting notifications for this timer */
return NOTIFY_STATUS_OK;
}
switch (t)
{
case TIME_EVENT_ONESHOT:
{
timer = timer_oneshot(s, dispatch_get_main_queue());
break;
}
case TIME_EVENT_CLOCK:
{
timer = timer_clock(s, f, e, dispatch_get_main_queue());
break;
}
case TIME_EVENT_CAL:
{
timer = timer_calendar(s, f, d, e, dispatch_get_main_queue());
break;
}
default:
{
return NOTIFY_STATUS_FAILED;
}
}
if (timer == NULL) return NOTIFY_STATUS_FAILED;
timer->context64 = c->client_id;
info = (svc_info_t *)calloc(1, sizeof(svc_info_t));
assert(info != NULL);
info->type = SERVICE_TYPE_TIMER_PRIVATE;
info->private = timer;
c->private = info;
dispatch_source_set_event_handler(timer->src, ^{
dispatch_async(global.work_q, ^{
if (0 == dispatch_source_testcancel(timer->src))
{
daemon_post_client(timer->context64);
}
});
});
dispatch_resume(timer->src);
return NOTIFY_STATUS_OK;
}
/* called from server-side routines in notify_proc - services are private to the client */
int
service_open(const char *name, client_t *client, uint32_t uid, uint32_t gid)
{
uint32_t t, flags;
char *p, *q;
t = service_type(name);
switch (t)
{
case SERVICE_TYPE_NONE:
{
return NOTIFY_STATUS_OK;
}
case SERVICE_TYPE_PATH_PRIVATE:
{
p = strchr(name, ':');
if (p != NULL) p++;
flags = 0;
q = strchr(p, ':');
if (q != NULL)
{
flags = strtol(p, NULL, 0);
p = q + 1;
}
return service_open_path_private(name, client, p, uid, gid, flags);
}
case SERVICE_TYPE_TIMER_PRIVATE:
{
p = strchr(name, ':');
if (p != NULL) p++;
return service_open_timer_private(name, client, p);
}
default:
{
return NOTIFY_STATUS_INVALID_REQUEST;
}
}
return NOTIFY_STATUS_INVALID_REQUEST;
}
void
service_close(svc_info_t *info)
{
if (info == NULL) return;
switch (info->type)
{
case SERVICE_TYPE_PATH_PUBLIC:
case SERVICE_TYPE_PATH_PRIVATE:
{
path_node_close((path_node_t *)info->private);
break;
}
case SERVICE_TYPE_TIMER_PUBLIC:
case SERVICE_TYPE_TIMER_PRIVATE:
{
timer_close((timer_t *)info->private);
break;
}
default:
{
}
}
free(info);
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2003-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@
*/
#ifndef _NOTIFY_SERVICE_H_
#define _NOTIFY_SERVICE_H_
#define SERVICE_TYPE_NONE 0
#define SERVICE_TYPE_PATH_PUBLIC 1
#define SERVICE_TYPE_PATH_PRIVATE 2
#define SERVICE_TYPE_TIMER_PUBLIC 3
#define SERVICE_TYPE_TIMER_PRIVATE 4
#define SERVICE_PREFIX "com.apple.system.notify.service."
#define SERVICE_PREFIX_LEN 32
typedef struct
{
uint32_t type;
void *private;
} svc_info_t;
int service_open(const char *name, client_t *client, uint32_t uid, uint32_t gid);
int service_open_path(const char *name, const char *path, uid_t uid, gid_t gid);
int service_open_path_private(const char *name, client_t *client, const char *path, uid_t uid, gid_t gid, uint32_t flags);
int service_open_timer(const char *name, const char *args);
int service_open_timer_private(const char *name, client_t *client, const char *args);
void service_close(svc_info_t *info);
#endif /* _NOTIFY_SERVICE_H_ */

86
libnotify/notifyd/table.h Normal file
View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2003-2011 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@
*/
#ifndef _NOTIFY_TABLE_H_
#define _NOTIFY_TABLE_H_
#include <stdint.h>
typedef struct __table_private table_t;
typedef struct __list_private list_t;
extern table_t *_nc_table_new(uint32_t n);
extern void _nc_table_insert(table_t *t, const char *key, void *datum);
extern void _nc_table_insert_no_copy(table_t *t, const char *key, void *datum);
extern void _nc_table_insert_n(table_t *t, uint32_t key, void *datum);
extern void _nc_table_insert_64(table_t *t, uint64_t key, void *datum);
extern void *_nc_table_find(table_t *t, const char *key);
extern void *_nc_table_find_n(table_t *t, uint32_t key);
extern void *_nc_table_find_64(table_t *t, uint64_t key);
extern void _nc_table_delete(table_t *t, const char *key);
extern void _nc_table_delete_n(table_t *t, uint32_t key);
extern void _nc_table_delete_64(table_t *t, uint64_t key);
extern void *_nc_table_traverse_start(table_t *tin);
extern void *_nc_table_traverse(table_t *tin, void *ttin);
extern void _nc_table_traverse_end(table_t *tin, void *ttin);
extern void _nc_table_free(table_t *tin);
extern list_t *_nc_list_new(void *d);
extern list_t *_nc_list_retain(list_t *l);
extern list_t *_nc_list_retain_list(list_t *l);
extern void _nc_list_release(list_t *l);
extern void _nc_list_release_list(list_t *l);
extern list_t *_nc_list_prev(list_t *l);
extern list_t *_nc_list_next(list_t *l);
extern void _nc_list_set_next(list_t *l, list_t *n);
extern void _nc_list_set_prev(list_t *l, list_t *p);
extern list_t *_nc_list_head(list_t *l);
extern list_t *_nc_list_tail(list_t *l);
extern list_t *_nc_list_prepend(list_t *l, list_t *n);
extern list_t *_nc_list_append(list_t *l, list_t *n);
extern list_t *_nc_list_concat(list_t *a, list_t *b);
extern void *_nc_list_data(list_t *l);
extern void _nc_list_set_data(list_t *l, void *d);
extern list_t *_nc_list_find(list_t *l, void *d);
extern list_t *_nc_list_find_release(list_t *l, void *d);
extern list_t * _nc_list_reverse(list_t *l);
extern uint32_t _nc_list_count(list_t *l);
extern list_t *_nc_list_extract(list_t *n);
extern list_t *_nc_list_chop(list_t *l);
#endif /* _NOTIFY_TABLE_H_ */

465
libnotify/notifyd/timer.c Normal file
View File

@ -0,0 +1,465 @@
/*
* Copyright (c) 2009-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 <stdlib.h>
#include <string.h>
#include <Block.h>
#include "timer.h"
#define MINUTE 60
#define HOUR 3600
#define DAY 86400
static const uint8_t mlen[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
/*
* Timed events
*
* Supported event types:
*
* Oneshot
* Every n seconds/minutes/hours/days/weeks
* Specific day of the month, every n months
* Specific weekday following specific day of the month, every n months
*
*/
static time_t
timer_next(timer_t *t, time_t now)
{
uint32_t y, m;
int32_t d, x, a, b, dd, wd;
struct tm tmp;
time_t next, tt, tod;
if (t == NULL) return 0;
switch (t->type)
{
case TIME_EVENT_ONESHOT:
{
/*
* oneshot time event
*/
if (t->start < now) return 0;
return t->start;
}
case TIME_EVENT_CLOCK:
{
/*
* event recurs every t->freq seconds
*/
/* t->end is the cut-off. If it's in the past, return 0 */
if ((t->end != 0) && (t->end < now)) return 0;
/* If the start time is in the future, that's the next occurrence */
if (t->start >= now) return t->start;
/* shouldn't happen, as TIME_EVENT_CLOCK should always recur */
if (t->freq == 0) return 0;
x = ((t->freq - 1) + now - t->start) / t->freq;
next = t->start + (x * t->freq);
return next;
}
case TIME_EVENT_CAL:
{
/*
* event recurs every t->freq months
* t->base gives us the starting month and year, and the time of day
* t->day specifies the day of the month (negative means relative to last day of the month)
* t->day is > 100 or < 100, then it means a weekday
* 101 = first monday, 102 = first tuesday, ..., 108 = second monday, and so on
* -101 = last monday, -102 = last tuesday, ..., -108 = second last monday, and so on
*/
/* t->end is the cut-off. If it's in the past, return 0 */
if ((t->end != 0) && (t->end < now)) return 0;
/* If the start time is in the future, that's the next occurrence */
if (t->start >= now) return t->start;
next = t->start;
/* If t->next is set from the last time we ran, and it is in the past, we can start there. */
if ((t->next > 0) && (t->next < now)) next = t->next;
while (next < now)
{
/* determine year, month, and time-of-day (clock time) of the next occurance */
memset(&tmp, 0, sizeof(struct tm));
localtime_r((const time_t *)&(next), &tmp);
y = tmp.tm_year;
m = tmp.tm_mon;
tod = tmp.tm_sec + (MINUTE * tmp.tm_min) + (HOUR * tmp.tm_hour);
m += t->freq;
if (m > 11)
{
y += (m / 12);
m %= 12;
}
/* we now have a year (y), a month (m), and a time of day (tod) */
if (t->day > 0)
{
if (t->day < 100)
{
/* easy case: day is the date of the month */
memset(&tmp, 0, sizeof(struct tm));
tmp.tm_year = y;
tmp.tm_mon = m;
tmp.tm_mday = t->day;
tmp.tm_isdst = -1;
next = mktime(&tmp) + tod;
continue;
}
else
{
/* t->day is a weekday */
wd = t->day - 100;
/* start by finding out the weekday of the first of the month */
memset(&tmp, 0, sizeof(struct tm));
tmp.tm_year = y;
tmp.tm_mon = m;
tmp.tm_mday = 1;
tmp.tm_isdst = -1;
tt = mktime(&tmp);
localtime_r((const time_t *)&tt, &tmp);
if (tmp.tm_wday == 0) tmp.tm_wday = 7;
x = 0;
if (tmp.tm_wday > (wd % 7)) x = (wd + 7) - tmp.tm_wday;
else x = wd - tmp.tm_wday;
tmp.tm_mday += x;
tmp.tm_isdst = -1;
next = mktime(&tmp) + tod;
continue;
}
}
if (t->day > -100)
{
/* nth day from the end of the month */
if (m == 1)
{
/* determine weekday of last day of February (== March 0) */
memset(&tmp, 0, sizeof(struct tm));
tmp.tm_year = y;
tmp.tm_mon = 2;
tmp.tm_mday = 0;
tmp.tm_isdst = -1;
tt = mktime(&tmp);
memset(&tmp, 0, sizeof(struct tm));
localtime_r((const time_t *)&(tt), &tmp);
d = tmp.tm_mday + t->day;
}
else
{
d = mlen[m] + t->day;
}
memset(&tmp, 0, sizeof(struct tm));
tmp.tm_year = y;
tmp.tm_mon = m;
tmp.tm_mday = d;
tmp.tm_isdst = -1;
next = mktime(&tmp) + tod;
continue;
}
/* t->day is a weekday relative to the end of the month */
if (m == 1)
{
/* determine weekday of last day of February (== March 0) */
memset(&tmp, 0, sizeof(struct tm));
tmp.tm_year = y;
tmp.tm_mon = 2;
tmp.tm_mday = 0;
tmp.tm_isdst = -1;
tt = mktime(&tmp);
memset(&tmp, 0, sizeof(struct tm));
localtime_r((const time_t *)&(tt), &tmp);
d = tmp.tm_mday;
}
else
{
d = mlen[m];
}
memset(&tmp, 0, sizeof(struct tm));
tmp.tm_year = y;
tmp.tm_mon = m;
tmp.tm_mday = d;
tmp.tm_isdst = -1;
dd = -1 * (t->day + 100);
a = dd % 7;
b = (dd + 6) / 7;
if (a <= tmp.tm_wday) b--;
tmp.tm_mday = ((a - tmp.tm_wday) + d) - (b * 7);
next = mktime(&tmp) + tod;
}
t->next = next;
return next;
}
default:
{
return 0;
}
}
return 0;
}
/*
* This does the actual free.
* It is dispatched on the timer's dispatch source queue to make it safe.
*/
static void
timer_free(timer_t *t)
{
if (t == NULL) return;
if (t->deactivation_handler != NULL) Block_release(t->deactivation_handler);
if (t->contextp != NULL) free(t->contextp);
dispatch_release(t->t_src);
dispatch_release(t->t_queue);
memset(t, 0, sizeof(timer_t));
free(t);
}
void
timer_close(timer_t *t)
{
if (t == NULL) return;
if (t->t_src != NULL) dispatch_source_cancel(t->t_src);
/*
* We need to make sure that the source's event handler isn't currently running
* before we free the timer. We let the source's queue do the actual free.
*/
dispatch_async(t->t_queue, ^{ timer_free(t); });
}
timer_t *
timer_oneshot(time_t when, dispatch_queue_t queue)
{
timer_t *t;
time_t now;
dispatch_time_t trigger;
/* refuse a trigger time in the past */
now = time(0);
if (when <= now) return NULL;
t = calloc(1, sizeof(timer_t));
if (t == NULL) return NULL;
dispatch_retain(queue);
t->type = TIME_EVENT_ONESHOT;
t->start = when;
t->t_queue = queue;
t->t_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
t->src = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
trigger = dispatch_walltime(NULL, (t->start - now) * NSEC_PER_SEC);
dispatch_source_set_timer(t->t_src, trigger, NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(t->t_src, ^{
dispatch_source_merge_data(t->src, 1);
dispatch_source_cancel(t->t_src);
if (t->deactivation_handler != NULL)
{
dispatch_async(t->t_queue, ^{ t->deactivation_handler(); });
}
});
dispatch_resume(t->t_src);
return t;
}
void
timer_set_deactivation_handler(timer_t *t, void(^handler)())
{
if (t == NULL) return;
if (t->deactivation_handler != NULL) Block_release(t->deactivation_handler);
t->deactivation_handler = Block_copy(handler);
}
timer_t *
timer_clock(time_t first, time_t freq_sec, time_t end, dispatch_queue_t queue)
{
timer_t *t;
time_t now;
dispatch_time_t trigger;
int64_t x;
if (freq_sec == 0) return timer_oneshot(first, queue);
now = time(0);
t = calloc(1, sizeof(timer_t));
if (t == NULL) return NULL;
t->type = TIME_EVENT_CLOCK;
if (first < now)
{
x = ((freq_sec - 1) + now - first) / freq_sec;
t->start = first + (x * freq_sec);
}
else
{
t->start = first;
}
t->end = end;
t->freq = freq_sec;
t->t_queue = queue;
t->t_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
t->src = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
trigger = dispatch_walltime(NULL, (t->start - now) * NSEC_PER_SEC);
dispatch_source_set_timer(t->t_src, trigger, freq_sec * NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(t->t_src, ^{
unsigned long n = dispatch_source_get_data(t->t_src);
dispatch_source_merge_data(t->src, n);
/* deactivate if this is the last time we want to trigger the client source */
if ((t->end > 0) && (t->end < (time(0) + freq_sec)))
{
dispatch_source_cancel(t->t_src);
if (t->deactivation_handler != NULL)
{
dispatch_async(t->t_queue, ^{ t->deactivation_handler(); });
}
}
});
dispatch_resume(t->t_src);
return t;
}
timer_t *
timer_calendar(time_t first, time_t freq_mth, time_t end, int day, dispatch_queue_t queue)
{
timer_t *t;
time_t next, now;
dispatch_time_t trigger;
if (freq_mth == 0) return timer_oneshot(first, queue);
now = time(0);
t = calloc(1, sizeof(timer_t));
if (t == NULL) return NULL;
t->type = TIME_EVENT_CAL;
t->start = first;
t->day = day;
t->end = end;
t->freq = freq_mth;
t->t_queue = queue;
t->t_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
t->src = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
next = timer_next(t, now);
trigger = dispatch_walltime(NULL, (next - now) * NSEC_PER_SEC);
dispatch_source_set_timer(t->t_src, trigger, NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(t->t_src, ^{
unsigned long n = dispatch_source_get_data(t->t_src);
dispatch_source_merge_data(t->src, n);
time_t now = time(0);
time_t x = timer_next(t, now);
/* deactivate when there is no next time */
if (x == 0)
{
dispatch_source_cancel(t->t_src);
if (t->deactivation_handler != NULL)
{
dispatch_async(t->t_queue, ^{ t->deactivation_handler(); });
}
}
else
{
dispatch_source_set_timer(t->t_src, dispatch_walltime(NULL, (x - now) * NSEC_PER_SEC), NSEC_PER_SEC, 0);
}
});
dispatch_resume(t->t_src);
return t;
}
timer_t *
timer_calendar_long(uint32_t start_year, uint32_t start_month, uint32_t start_day, uint32_t start_hour, uint32_t start_min, uint32_t start_sec, time_t freq, int day, uint32_t end_year, uint32_t end_month, uint32_t end_day, uint32_t end_hour, uint32_t end_min, uint32_t end_sec, dispatch_queue_t queue)
{
struct tm tmp;
time_t first, last;
memset(&tmp, 0, sizeof(struct tm));
tmp.tm_year = start_year - 1900;
tmp.tm_mon = start_month;
tmp.tm_mday = start_day;
tmp.tm_isdst = -1;
tmp.tm_hour = start_hour;
tmp.tm_min = start_min;
tmp.tm_sec = start_sec;
first = mktime(&tmp);
if (freq == 0) return timer_oneshot(first, queue);
memset(&tmp, 0, sizeof(struct tm));
tmp.tm_year = end_year;
tmp.tm_mon = end_month;
tmp.tm_mday = end_day;
tmp.tm_isdst = -1;
tmp.tm_hour = end_hour;
tmp.tm_min = end_min;
tmp.tm_sec = end_sec;
last = mktime(&tmp);
return timer_calendar(first, freq, day, last, queue);
}

59
libnotify/notifyd/timer.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2009-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 <time.h>
#include <stdint.h>
#include <dispatch/dispatch.h>
#define TIME_EVENT_NONE 0
#define TIME_EVENT_ONESHOT 1
#define TIME_EVENT_CLOCK 2
#define TIME_EVENT_CAL 3
/*
* Timer Event
*/
typedef struct
{
uint32_t type;
int64_t start;
int64_t end;
uint32_t freq;
int32_t day;
int64_t next;
void (^deactivation_handler)();
dispatch_source_t src;
dispatch_source_t t_src;
dispatch_queue_t t_queue;
void *contextp;
uint32_t context32;
uint64_t context64;
} timer_t;
timer_t *timer_oneshot(time_t when, dispatch_queue_t queue);
timer_t *timer_clock(time_t first, time_t freq_sec, time_t end, dispatch_queue_t queue);
timer_t *timer_calendar(time_t first, time_t freq_mth, time_t end, int day, dispatch_queue_t queue);
timer_t *timer_calendar_long(uint32_t yf, uint32_t mf, uint32_t df, uint32_t hf, uint32_t nf, uint32_t sf, time_t fm, int d, uint32_t ye, uint32_t me, uint32_t de, uint32_t he, uint32_t ne, uint32_t se, dispatch_queue_t queue);
void timer_set_deactivation_handler(timer_t *t, void(^handler)());
void timer_close(timer_t *t);

View File

@ -0,0 +1,6 @@
set -e -x
ETCDIR="$DSTROOT$INSTALL_PATH_PREFIX"/private/etc
install -d -o root -g wheel -m 0755 "$ETCDIR"
install -c -o root -g wheel -m 0644 \
"$SRCROOT"/notifyd/"$NOTIFY_CONFIG" \
"$ETCDIR"/notify.conf

View File

@ -0,0 +1,220 @@
.\" Copyright (c) 2006-2011 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@
.\"
.\"
.Dd November 4, 2011
.Dt notifyutil 1
.Os "Mac OS X"
.Sh NAME
.Nm notifyutil
.Nd notification command line utility
.Sh SYNOPSIS
.Nm
.Op Fl q
.Op Fl v
.Op Fl z Ar msec
.Op Fl M
.Op Fl R
.Op command Li ...
.Pp
.Sh DESCRIPTION
.Nm
is a command-line utility for interacting with the
.Xr notify 3
notification system and the
.Xr notifyd 8
server.
It may be used to post notifications, detect and report notifications,
and to examine and set the state values associated with notification keys.
.Pp
If
.Nm
is used to monitor one or more notification keys,
it prints the notification key when the corresponding notification is received.
The
.Fl v
(verbose)
and
.Fl q
(quiet) flags, if specified, modify the output behavior.
.Pp
The
.Fl v
flag causes
.Nm
to print a time stamp, the notification key, the current state value for that key,
and the type of the notification (port, file, etc).
The
.Fl q
flag supresses any output except for state values fetched following a
.Fl g
command.
.Pp
Commands listed in the table below are processed in left to right order from the command line.
.Pp
.Bl -tag -width "-signal [#]" -compact -offset indent
.It Fl p Ar key
Post a notification for
.Ar key .
.It Fl w Ar key
Register for
.Ar key
and wait forever for notifications.
.It Fl Ar # Ar key
Register for
.Ar key
and wait for
.Ar #
(an integer) notifications.
.It ""
.Li E.g.
.Fl 1 Ar key
waits for a single notification.
.It Fl g Ar key
Get state value for
.Ar key .
.It Fl s Ar key Ar val
Set state value for
.Ar key .
.It Fl port
Use mach port notifications for subsequent
.Fl w
or
.Fl Ar #
registrations.
.It ""
This is the default registration type.
.It Fl file
Use file descriptor notifications for subsequent registrations.
.It Fl check
Use shared memory notifications for subsequent registrations.
.It Fl signal Op Ar #
Use signal notifications for subsequent registrations.
.It ""
Signal 1 (HUP) is the default, but an alternate signal may be specified.
.It Fl dispatch
Use dispatch for subsequent registrations.
.El
.Pp
When invoked with any combination of
.Fl w
and
.Fl Ar #
actions,
.Nm
registers for notification for the specified key(s).
If any key is given with a
.Fl w
action,
.Nm
runs until interrupted with Control-C.
If all registrations are invoked with
.Fl Ar # ,
the program continues to run until the corresponding number of notifications for each key have been received.
.Pp
By default,
.Nm
uses mach port registration (using
.Fn notify_register_mach_port )
for keys given with a
.Fl w
or
.Fl Ar #
flag.
The
.Fl file
command causes
.Nm
to use
.Fn notify_register_file_descriptor
for any subsequent
.Fl w
or
.Fl Ar #
registrations.
Similarly,
.Fl check
causes
.Nm
to use
.Fn notify_register_check
for subsequent registrations,
.Fl signal
switches to
.Fn notify_register_signal ,
and
.Fl dispatch
causes it to use
.Fn notify_register_dispatch
for subsequent registrations.
.Pp
If any registrations are made following the use of the
.Fl check
command,
.Nm
will start a timer and check for shared memory notifications every 100 milliseconds.
An alternate timer value may be set following the
.Fl z
flag.
.Pp
The
.Fl M
flag causes
.Nm
to use multiplex all notifications over a single mach connection with
.Nm notifyd .
Notifications (except shared memory notifications)
are received and redistributed by a dispatch handler.
.Pp
The
.Fl R
flag causes
.Nm notifyutil
to regenerate all its registrations in the unlikely event that
.Nm notifyd
restarts.
.Pp
Note that a notification key and its associated state variable only exist
when there are one or more current registrations for that key.
Setting the state for a key that has no registrations has no effect.
Thus the command
.Pp
.Dl notifyutil -s foo.bar 123 -g foo.bar
.Pp
will print
.Pp
.Dl foo.bar 0
.Pp
unless foo.bar is registered by some other process.
However, the command
.Pp
.Dl notifyutil -w foo.bar -s foo.bar 123 -g foo.bar
.Pp
prints
.Pp
.Dl foo.bar 123
.Pp
since the
.Dq -w foo.bar
registration ensures the key and its state variable exist before the value is set,
and continue to exist when the value is fetched.
.Sh SEE ALSO
notify(3), notifyd(8)

View File

@ -0,0 +1,751 @@
/*
* 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>
#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_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"
};
extern uint32_t notify_register_plain(const char *name, int *out_token);
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;
dispatch_source_t timer_src;
dispatch_source_t port_src;
dispatch_source_t file_src;
dispatch_source_t sig_src[__DARWIN_NSIG];
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 notifcation 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");
}
static const char *
notify_status_strerror(int status)
{
switch (status)
{
case NOTIFY_STATUS_OK: return("OK");
case NOTIFY_STATUS_INVALID_NAME: return "Invalid Name";
case NOTIFY_STATUS_INVALID_TOKEN: return "Invalid Token";
case NOTIFY_STATUS_INVALID_PORT: return "Invalid Port";
case NOTIFY_STATUS_INVALID_FILE: return "Invalid File";
case NOTIFY_STATUS_INVALID_SIGNAL: return "Invalid Signal";
case NOTIFY_STATUS_INVALID_REQUEST: return "Invalid Request";
case NOTIFY_STATUS_NOT_AUTHORIZED: return "Not Authorized";
case NOTIFY_STATUS_FAILED:
default: return "Failed";
}
}
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_name(const char *name)
{
uint32_t i;
for (i = 0; i < reg_count; i++) if (!strcmp(reg[i].name, name)) return i;
return IndexNull;
}
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, index, needspace;
uint64_t state;
gettimeofday(&now, NULL);
index = reg_find_token(tid);
if (index == IndexNull) return;
needspace = 0;
if (printopt & PRINT_TIME)
{
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(": %s", notify_status_strerror(status));
needspace = 1;
}
if (printopt & PRINT_TYPE)
{
if (needspace) printf(" ");
printf("%s", typename[reg[index].type]);
needspace = 1;
}
if (printopt != PRINT_QUIET) printf("\n");
if ((reg[index].count != IndexNull) && (reg[index].count != 0)) reg[index].count--;
if (reg[index].count == 0)
{
status = notify_cancel(tid);
reg_delete(index);
}
}
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(const char *name)
{
uint32_t index = reg_find_name(name);
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;
status = 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(name); });
if (status != NOTIFY_STATUS_OK) return status;
break;
}
case TYPE_CHECK:
{
status = notify_register_check(name, &tid);
if (status != NOTIFY_STATUS_OK) return status;
status = 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;
status = 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;
uint32_t i, n, index, 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_DEMUX;
}
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
{
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: %s\n", argv[i], notify_status_strerror(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;
index = reg_find_name(argv[i]);
if (index != IndexNull)
{
fprintf(stderr, "Already watching for %s\n", argv[i]);
continue;
}
status = do_register(argv[i], ntype, signum, n);
if (status != NOTIFY_STATUS_OK) printf("%s: %s\n", argv[i], notify_status_strerror(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: %s\n", argv[i], notify_status_strerror(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: %s\n", argv[i], notify_status_strerror(status));
i++;
}
}
if (reg_count == 0) exit(0);
dispatch_main();
}

763
libnotify/table.c Normal file
View File

@ -0,0 +1,763 @@
/*
* Copyright (c) 2003-2011 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 <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/types.h>
#include <os/assumes.h>
#include "table.h"
#define KEY_UNKNOWN 0
#define KEY_INT 1
#define KEY_STR_MINE 2
#define KEY_STR_SHARED 3
#define DEFAULT_SIZE 256
typedef struct table_node_s
{
union
{
char *string;
const char *const_string;
uint64_t uint64;
} key;
void *datum;
struct table_node_s *next;
} table_node_t;
typedef struct __table_private
{
uint32_t type;
uint32_t bucket_count;
table_node_t **bucket;
} table_private_t;
typedef struct
{
uint32_t bucket_index;
table_node_t *node;
} table_traverse_t;
typedef struct __list_private
{
struct __list_private *prev;
struct __list_private *next;
uint32_t refcount;
void *data;
} list_private_t;
table_t *
_nc_table_new(uint32_t n)
{
table_private_t *t;
t = (table_t *)malloc(sizeof(table_t));
if (t == NULL) return NULL;
if (n == 0) n = DEFAULT_SIZE;
t->type = KEY_UNKNOWN;
t->bucket_count = n;
t->bucket = (table_node_t **)calloc(t->bucket_count, sizeof(table_node_t *));
if (t->bucket == NULL)
{
free(t);
return NULL;
}
return (table_t *)t;
}
static uint32_t
hash_key(int size, const char *key)
{
uint32_t v;
char *p;
if (key == NULL) return 0;
v = 0;
for (p = (char *)key; *p != '\0'; p++)
{
v = (v << 1) ^ (v ^ *p);
}
v %= size;
return v;
}
static uint32_t
hash_nkey(uint32_t size, uint64_t key)
{
uint32_t x = key;
uint32_t y = key >> 32;
return ((x ^ y) % size);
}
void *
_nc_table_find_get_key(table_t *tin, const char *key, const char **shared_key)
{
table_private_t *t;
table_node_t *n;
uint32_t b;
if (tin == NULL) return NULL;
if (key == NULL) return NULL;
if (shared_key != NULL) *shared_key = NULL;
t = (table_private_t *)tin;
b = hash_key(t->bucket_count, key);
for (n = t->bucket[b]; n != NULL; n = n->next)
{
if ((n->key.string != NULL) && (!strcmp(key, n->key.string)))
{
if (shared_key != NULL) *shared_key = n->key.const_string;
return n->datum;
}
}
return NULL;
}
void *
_nc_table_find(table_t *tin, const char *key)
{
return _nc_table_find_get_key(tin, key, NULL);
}
void *
_nc_table_find_64(table_t *tin, uint64_t key)
{
table_private_t *t;
table_node_t *n;
uint32_t b;
if (tin == NULL) return NULL;
t = (table_private_t *)tin;
b = hash_nkey(t->bucket_count, key);
for (n = t->bucket[b]; n != NULL; n = n->next)
{
if ((n->key.uint64 != (uint64_t)-1) && (key == n->key.uint64)) return n->datum;
}
return NULL;
}
void *
_nc_table_find_n(table_t *tin, uint32_t key)
{
uint64_t n64 = key;
return _nc_table_find_64(tin, n64);
}
static void
_nc_table_insert_type(table_t *tin, int type, char *key, const char *ckey, void *datum)
{
table_private_t *t;
table_node_t *n;
uint32_t b;
if (tin == NULL) return;
if ((key == NULL) && (ckey == NULL)) return;
if (datum == NULL) return;
t = (table_private_t *)tin;
if (t->type == KEY_UNKNOWN) t->type = type;
else os_assumes(t->type == type);
n = (table_node_t *)malloc(sizeof(table_node_t));
if (key != NULL)
{
b = hash_key(t->bucket_count, key);
n->key.string = key;
}
else
{
b = hash_key(t->bucket_count, ckey);
n->key.const_string = ckey;
}
n->datum = datum;
n->next = t->bucket[b];
t->bucket[b] = n;
}
void
_nc_table_insert(table_t *tin, const char *key, void *datum)
{
char *dup;
if (tin == NULL) return;
if (key == NULL) return;
if (datum == NULL) return;
dup = strdup(key);
if (dup == NULL) return;
_nc_table_insert_type(tin, KEY_STR_MINE, dup, NULL, datum);
}
void
_nc_table_insert_no_copy(table_t *tin, const char *key, void *datum)
{
if (tin == NULL) return;
if (key == NULL) return;
if (datum == NULL) return;
_nc_table_insert_type(tin, KEY_STR_SHARED, NULL, key, datum);
}
void
_nc_table_insert_pass(table_t *tin, char *key, void *datum)
{
if (tin == NULL) return;
if (key == NULL) return;
if (datum == NULL) return;
_nc_table_insert_type(tin, KEY_STR_MINE, key, NULL, datum);
}
void
_nc_table_insert_64(table_t *tin, uint64_t key, void *datum)
{
table_private_t *t;
table_node_t *n;
uint32_t b;
if (tin == NULL) return;
if (datum == NULL) return;
t = (table_private_t *)tin;
if (t->type == KEY_UNKNOWN) t->type = KEY_INT;
else os_assumes(t->type == KEY_INT);
b = hash_nkey(t->bucket_count, key);
n = (table_node_t *)malloc(sizeof(table_node_t));
n->key.uint64 = key;
n->datum = datum;
n->next = t->bucket[b];
t->bucket[b] = n;
}
void
_nc_table_insert_n(table_t *tin, uint32_t key, void *datum)
{
uint64_t n64 = key;
_nc_table_insert_64(tin, n64, datum);
}
void
_nc_table_delete(table_t *tin, const char *key)
{
table_private_t *t;
table_node_t *n, *p;
uint32_t b;
if (tin == NULL) return;
if (key == NULL) return;
t = (table_private_t *)tin;
os_assumes((t->type == KEY_STR_MINE) || (t->type == KEY_STR_SHARED));
b = hash_key(t->bucket_count, key);
p = NULL;
for (n = t->bucket[b]; n != NULL; n = n->next)
{
if ((n->key.string != NULL) && (!strcmp(key, n->key.string)))
{
if (p == NULL) t->bucket[b] = n->next;
else p->next = n->next;
if (t->type == KEY_STR_MINE) free(n->key.string);
free(n);
return;
}
p = n;
}
}
void
_nc_table_delete_64(table_t *tin, uint64_t key)
{
table_private_t *t;
table_node_t *n, *p;
uint32_t b;
if (tin == NULL) return;
t = (table_private_t *)tin;
os_assumes(t->type == KEY_INT);
b = hash_nkey(t->bucket_count, key);
p = NULL;
for (n = t->bucket[b]; n != NULL; n = n->next)
{
if ((n->key.uint64 != (uint64_t)-1) && (key == n->key.uint64))
{
if (p == NULL) t->bucket[b] = n->next;
else p->next = n->next;
free(n);
return;
}
p = n;
}
}
void
_nc_table_delete_n(table_t *tin, uint32_t key)
{
uint64_t n64 = key;
_nc_table_delete_64(tin, n64);
}
void *
_nc_table_traverse_start(table_t *tin)
{
table_traverse_t *tt;
table_private_t *t;
uint32_t b;
if (tin == NULL) return NULL;
t = (table_private_t *)tin;
if (t->bucket_count == 0) return NULL;
for (b = 0; b < t->bucket_count; b++)
{
if (t->bucket[b] != NULL)
{
tt = (table_traverse_t *)malloc(sizeof(table_traverse_t));
if (tt == NULL) return NULL;
tt->bucket_index = b;
tt->node = t->bucket[b];
return (void *)tt;
}
}
return NULL;
}
void *
_nc_table_traverse(table_t *tin, void *ttin)
{
table_private_t *t;
table_traverse_t *tt;
void *datum;
uint32_t b;
if (tin == NULL) return NULL;
if (ttin == NULL) return NULL;
t = (table_private_t *)tin;
tt = (table_traverse_t *)ttin;
if (tt->node == NULL) return NULL;
datum = tt->node->datum;
tt->node = tt->node->next;
if (tt->node != NULL) return datum;
for (b = tt->bucket_index + 1; b < t->bucket_count; b++)
{
if (t->bucket[b] != NULL)
{
tt->bucket_index = b;
tt->node = t->bucket[b];
return datum;
}
}
tt->bucket_index = b;
tt->node = NULL;
return datum;
}
void
_nc_table_traverse_end(table_t *tin, void *ttin)
{
if (ttin == NULL) return;
free(ttin);
}
void
_nc_table_free(table_t *tin)
{
table_private_t *t;
table_node_t *n, *x;
uint32_t b;
if (tin == NULL) return;
t = (table_private_t *)tin;
for (b = 0; b < t->bucket_count; b++)
{
x = NULL;
for (n = t->bucket[b]; n != NULL; n = x)
{
x = n->next;
if (t->type == KEY_STR_MINE) free(n->key.string);
free(n);
}
}
free(t->bucket);
free(t);
}
/* Linked List */
/*
* Make a new node
*/
list_t *
_nc_list_new(void *d)
{
list_t *n;
n = (list_t *)calloc(1, sizeof(list_t));
if (n == NULL) return NULL;
n->refcount = 1;
n->data = d;
return n;
}
/*
* Release a node
*/
void
_nc_list_release(list_t *l)
{
if (l == NULL) return;
l->refcount--;
if (l->refcount > 0) return;
free(l);
}
/*
* Retain a node
*/
list_t *
_nc_list_retain(list_t *l)
{
if (l == NULL) return NULL;
l->refcount++;
return l;
}
/*
* Retain a list
*/
list_t *
_nc_list_retain_list(list_t *l)
{
list_t *n;
for (n = l; n != NULL; n = n->next) n->refcount++;
return l;
}
/*
* Get previous node
*/
list_t *
_nc_list_prev(list_t *l)
{
if (l == NULL) return NULL;
return l->prev;
}
/*
* Get next node
*/
list_t *
_nc_list_next(list_t *l)
{
if (l == NULL) return NULL;
return l->next;
}
/*
* Get head (first node) of list
*/
list_t *
_nc_list_head(list_t *l)
{
list_t *p;
if (l == NULL) return NULL;
for (p = l; p->prev != NULL; p = p->prev);
return p;
}
/*
* Get tail (last node) of list
*/
list_t *
_nc_list_tail(list_t *l)
{
list_t *p;
if (l == NULL) return NULL;
for (p = l; p->next != NULL; p = p->next);
return p;
}
/*
* Insert a node in front of another node.
* Cuts list if n is NULL.
*/
list_t *
_nc_list_prepend(list_t *l, list_t *n)
{
if (l == NULL) return n;
if (n != NULL)
{
n->next = l;
n->prev = l->prev;
}
if (l->prev != NULL) l->prev->next = n;
l->prev = n;
return n;
}
/*
* Append a node after another node.
* Cuts list if n is NULL.
*/
list_t *
_nc_list_append(list_t *l, list_t *n)
{
if (l == NULL) return n;
if (n != NULL)
{
n->prev = l;
n->next = l->next;
}
if (l->next != NULL) n->next->prev = n;
l->next = n;
return n;
}
/*
* Set next pointer - use with care.
*/
void
_nc_list_set_next(list_t *l, list_t *n)
{
if (l == NULL) return;
l->next = n;
}
/*
* Set prev pointer - use with care.
*/
void
_nc_list_set_prev(list_t *l, list_t *p)
{
if (l == NULL) return;
l->prev = p;
}
/*
* Concatenate two lists.
* Returns new head.
*/
list_t *
_nc_list_concat(list_t *a, list_t *b)
{
list_t *p;
if (a == NULL) return b;
if (b == NULL) return a;
for (p = a; p->next != NULL; p = p->next);
p->next = b;
b->prev = p;
for (p = a; p->prev != NULL; p = p->prev);
return p;
}
uint32_t
_nc_list_count(list_t *l)
{
uint32_t n;
list_t *p;
n = 0;
for (p = l; p != NULL; p = p->next) n++;
return n;
}
void *
_nc_list_data(list_t *l)
{
if (l == NULL) return NULL;
return l->data;
}
void
_nc_list_set_data(list_t *l, void *d)
{
if (l != NULL) l->data = d;
}
list_t *
_nc_list_find(list_t *l, void *d)
{
list_t *p;
if (l == NULL) return NULL;
for (p = l; p != NULL; p = p->next)
{
if (p->data == d) return p;
}
return NULL;
}
list_t *
_nc_list_find_release(list_t *l, void *d)
{
list_t *p;
if (l == NULL) return NULL;
if (l->data == d)
{
p = l->next;
if (p != NULL) p->prev = NULL;
_nc_list_release(l);
return p;
}
for (p = l->next; p != NULL; p = p->next)
{
if (p->data == d)
{
p->prev->next = p->next;
if (p->next != NULL) p->next->prev = p->prev;
_nc_list_release(p);
return l;
}
}
return l;
}
list_t *
_nc_list_reverse(list_t *l)
{
list_t *x, *s, *r;
if (l == NULL) return NULL;
x = l->prev;
r = l;
s = l->next;
while (s != NULL)
{
s = r->next;
r->next = r->prev;
r->prev = s;
if (s != NULL) r = s;
}
if (x != NULL)
{
x->next = r;
r->prev = x;
}
return r;
}
list_t *
_nc_list_extract(list_t *n)
{
if (n == NULL) return NULL;
if (n->prev != NULL) n->prev->next = n->next;
if (n->next != NULL) n->next->prev = n->prev;
n->prev = NULL;
n->next = NULL;
return n;
}
list_t *
_nc_list_chop(list_t *l)
{
list_t *p;
if (l == NULL) return NULL;
p = l->next;
if (p != NULL) p->prev = NULL;
_nc_list_release(l);
return p;
}
void
_nc_list_release_list(list_t *l)
{
list_t *p, *n;
if (l == NULL) return;
if (l->prev != NULL) l->prev->next = NULL;
p = l;
while (p != NULL)
{
n = p->next;
_nc_list_release(p);
p = n;
}
}

88
libnotify/table.h Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2003-2011 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@
*/
#ifndef _NOTIFY_TABLE_H_
#define _NOTIFY_TABLE_H_
#include <stdint.h>
typedef struct __table_private table_t;
typedef struct __list_private list_t;
extern table_t *_nc_table_new(uint32_t n);
extern void _nc_table_insert(table_t *t, const char *key, void *datum);
extern void _nc_table_insert_no_copy(table_t *t, const char *key, void *datum);
extern void _nc_table_insert_pass(table_t *t, char *key, void *datum);
extern void _nc_table_insert_n(table_t *t, uint32_t key, void *datum);
extern void _nc_table_insert_64(table_t *t, uint64_t key, void *datum);
extern void *_nc_table_find(table_t *t, const char *key);
extern void *_nc_table_find_get_key(table_t *tin, const char *key, const char **shared_key);
extern void *_nc_table_find_n(table_t *t, uint32_t key);
extern void *_nc_table_find_64(table_t *t, uint64_t key);
extern void _nc_table_delete(table_t *t, const char *key);
extern void _nc_table_delete_n(table_t *t, uint32_t key);
extern void _nc_table_delete_64(table_t *t, uint64_t key);
extern void *_nc_table_traverse_start(table_t *tin);
extern void *_nc_table_traverse(table_t *tin, void *ttin);
extern void _nc_table_traverse_end(table_t *tin, void *ttin);
extern void _nc_table_free(table_t *tin);
extern list_t *_nc_list_new(void *d);
extern list_t *_nc_list_retain(list_t *l);
extern list_t *_nc_list_retain_list(list_t *l);
extern void _nc_list_release(list_t *l);
extern void _nc_list_release_list(list_t *l);
extern list_t *_nc_list_prev(list_t *l);
extern list_t *_nc_list_next(list_t *l);
extern void _nc_list_set_next(list_t *l, list_t *n);
extern void _nc_list_set_prev(list_t *l, list_t *p);
extern list_t *_nc_list_head(list_t *l);
extern list_t *_nc_list_tail(list_t *l);
extern list_t *_nc_list_prepend(list_t *l, list_t *n);
extern list_t *_nc_list_append(list_t *l, list_t *n);
extern list_t *_nc_list_concat(list_t *a, list_t *b);
extern void *_nc_list_data(list_t *l);
extern void _nc_list_set_data(list_t *l, void *d);
extern list_t *_nc_list_find(list_t *l, void *d);
extern list_t *_nc_list_find_release(list_t *l, void *d);
extern list_t * _nc_list_reverse(list_t *l);
extern uint32_t _nc_list_count(list_t *l);
extern list_t *_nc_list_extract(list_t *n);
extern list_t *_nc_list_chop(list_t *l);
#endif /* _NOTIFY_TABLE_H_ */

View File

@ -0,0 +1,29 @@
#include "<DEVELOPER_DIR>/Makefiles/CoreOS/Xcode/BSD.xcconfig"
#include "<DEVELOPER_DIR>/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig"
INSTALL_PATH[sdk=macosx*] = $(INSTALL_PATH_ACTUAL)
ALWAYS_SEARCH_USER_PATHS = YES
HEADER_SEARCH_PATHS = $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders $(PROJECT_DIR)
ARCHS = $(ARCHS_STANDARD_32_64_BIT)
CODE_SIGN_IDENTITY = -
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
GCC_ENABLE_CPP_EXCEPTIONS = NO
GCC_ENABLE_CPP_RTTI = NO
GCC_ENABLE_OBJC_EXCEPTIONS = NO
GCC_PREPROCESSOR_DEFINITIONS = __DARWIN_NON_CANCELABLE=1
GCC_C_LANGUAGE_STANDARD = gnu99
GCC_WARN_ABOUT_RETURN_TYPE = YES
GCC_WARN_UNUSED_VARIABLE = YES
//GCC_WARN_64_TO_32_BIT_CONVERSION = YES
//GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES
//GCC_WARN_ABOUT_RETURN_TYPE = YES
OTHER_CFLAGS = -fno-exceptions
OTHER_CFLAGS_debug = -O0
CURRENT_PROJECT_VERSION =
CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion)
VERSION_INFO_PREFIX = __
VERSIONING_SYSTEM = apple-generic
PREBINDING = NO
NOTIFY_CONFIG = notify.conf.MacOSX
NOTIFY_CONFIG[sdk=iphoneos*] = notify.conf.iPhone

View File

@ -0,0 +1,31 @@
#include "base.xcconfig"
PRODUCT_NAME = libsystem_notify
INSTALL_PATH_ACTUAL = /usr/lib/system
PRIVATE_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/local/include
PUBLIC_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/include
DYLIB_CURRENT_VERSION = $(CURRENT_PROJECT_VERSION)
EXECUTABLE_PREFIX =
BUILD_VARIANTS = normal
CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion)
VERSION_INFO_PREFIX = __
VERSIONING_SYSTEM = apple-generic
LINK_WITH_STANDARD_LIBRARIES = NO
OTHER_LDFLAGS = -umbrella System -L/usr/lib/system $(LDFLAGS_DYLD) $(LDFLAGS_COMPILER_RT) $(LDFLAGS_SYSCALL) $(LDFLAGS_PLATFORM) $(LDFLAGS_PTHREAD) $(LDFLAGS_MALLOC) $(LDFLAGS_C) $(LDFLAGS_BLOCKS) $(LDFLAGS_DISPATCH) $(LDFLAGS_XPC)
LDFLAGS_DYLD = -ldyld
LDFLAGS_COMPILER_RT = -lcompiler_rt
LDFLAGS_SYSCALL = -lsystem_kernel
LDFLAGS_SYSCALL[sdk=iphonesimulator*] = -lsystem_sim_kernel
LDFLAGS_PLATFORM = -lsystem_platform
LDFLAGS_PLATFORM[sdk=iphonesimulator*] = -lsystem_sim_platform
LDFLAGS_PTHREAD = -lsystem_pthread
LDFLAGS_PTHREAD[sdk=iphonesimulator*] = -lsystem_sim_pthread
LDFLAGS_MALLOC = -lsystem_malloc
LDFLAGS_C = -lsystem_c
LDFLAGS_C[sdk=iphonesimulator*] = -lsystem_sim_c
LDFLAGS_BLOCKS = -lsystem_blocks
LDFLAGS_BLOCKS[sdk=iphonesimulator*] = -lsystem_sim_blocks
LDFLAGS_DISPATCH = -ldispatch
LDFLAGS_XPC = -lxpc

View File

@ -0,0 +1,5 @@
#include "base.xcconfig"
INSTALL_PATH_ACTUAL = /usr/sbin
OTHER_LDFLAGS = -lCrashReporterClient

View File

@ -0,0 +1,4 @@
#include "base.xcconfig"
INSTALL_PATH_ACTUAL = /usr/bin

View File

@ -0,0 +1,5 @@
#!/bin/bash -ex
if [[ "${PLATFORM_NAME}" =~ "simulator" ]]; then
rm -rf ${DSTROOT}${INSTALL_PATH_PREFIX}/usr/share/man
fi

View File

@ -0,0 +1,5 @@
#!/bin/bash -ex
if [[ "${PLATFORM_NAME}" =~ "simulator" ]]; then
ln -s libsystem_notify.dylib ${DSTROOT}${INSTALL_PATH}/libnotify_sim.dylib
fi

2711
platform-include/dns_sd.h Normal file

File diff suppressed because it is too large Load Diff