mirror of
https://github.com/darlinghq/darling.git
synced 2024-11-23 12:19:43 +00:00
Adding libnotify source, build scripts for libinfo/dns&util
This commit is contained in:
parent
3bab377f74
commit
1638dcc2a1
@ -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
29
libinfo/CMakeLists.txt
Normal 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)
|
18
libinfo/dns.subproj/CMakeLists.txt
Normal file
18
libinfo/dns.subproj/CMakeLists.txt
Normal 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})
|
30
libinfo/lookup.subproj/CMakeLists.txt
Normal file
30
libinfo/lookup.subproj/CMakeLists.txt
Normal 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})
|
15
libinfo/util.subproj/CMakeLists.txt
Normal file
15
libinfo/util.subproj/CMakeLists.txt
Normal 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
372
libnotify/APPLE_LICENSE
Normal 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."
|
698
libnotify/Libnotify.xcodeproj/project.pbxproj
Normal file
698
libnotify/Libnotify.xcodeproj/project.pbxproj
Normal 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
1544
libnotify/libnotify.c
Normal file
File diff suppressed because it is too large
Load Diff
216
libnotify/libnotify.h
Normal file
216
libnotify/libnotify.h
Normal 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
419
libnotify/notify.3
Normal 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
338
libnotify/notify.h
Normal 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__ */
|
1
libnotify/notify_cancel.3
Normal file
1
libnotify/notify_cancel.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
1
libnotify/notify_check.3
Normal file
1
libnotify/notify_check.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
2465
libnotify/notify_client.c
Normal file
2465
libnotify/notify_client.c
Normal file
File diff suppressed because it is too large
Load Diff
1
libnotify/notify_get_state.3
Normal file
1
libnotify/notify_get_state.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
99
libnotify/notify_internal.h
Normal file
99
libnotify/notify_internal.h
Normal 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
373
libnotify/notify_ipc.defs
Normal 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
|
||||
);
|
32
libnotify/notify_ipc_types.h
Normal file
32
libnotify/notify_ipc_types.h
Normal 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
|
1
libnotify/notify_is_valid_token.3
Normal file
1
libnotify/notify_is_valid_token.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
83
libnotify/notify_keys.h
Normal file
83
libnotify/notify_keys.h
Normal 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
1
libnotify/notify_post.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
47
libnotify/notify_private.h
Normal file
47
libnotify/notify_private.h
Normal 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__ */
|
1
libnotify/notify_register_check.3
Normal file
1
libnotify/notify_register_check.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
1
libnotify/notify_register_dispatch.3
Normal file
1
libnotify/notify_register_dispatch.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
1
libnotify/notify_register_file_descriptor.3
Normal file
1
libnotify/notify_register_file_descriptor.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
1
libnotify/notify_register_mach_port.3
Normal file
1
libnotify/notify_register_mach_port.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
1
libnotify/notify_register_signal.3
Normal file
1
libnotify/notify_register_signal.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
1
libnotify/notify_set_state.3
Normal file
1
libnotify/notify_set_state.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/notify.3
|
31
libnotify/notifyd/com.apple.notifyd.plist
Normal file
31
libnotify/notifyd/com.apple.notifyd.plist
Normal 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>
|
10
libnotify/notifyd/notify.conf.MacOSX
Normal file
10
libnotify/notifyd/notify.conf.MacOSX
Normal 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
|
||||
|
7
libnotify/notifyd/notify.conf.iPhone
Normal file
7
libnotify/notifyd/notify.conf.iPhone
Normal 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
|
1623
libnotify/notifyd/notify_proc.c
Normal file
1623
libnotify/notifyd/notify_proc.c
Normal file
File diff suppressed because it is too large
Load Diff
68
libnotify/notifyd/notifyd.8
Normal file
68
libnotify/notifyd/notifyd.8
Normal 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
1265
libnotify/notifyd/notifyd.c
Normal file
File diff suppressed because it is too large
Load Diff
101
libnotify/notifyd/notifyd.h
Normal file
101
libnotify/notifyd/notifyd.h
Normal 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_ */
|
953
libnotify/notifyd/pathwatch.c
Normal file
953
libnotify/notifyd/pathwatch.c
Normal 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;
|
||||
}
|
84
libnotify/notifyd/pathwatch.h
Normal file
84
libnotify/notifyd/pathwatch.h
Normal 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
523
libnotify/notifyd/service.c
Normal 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);
|
||||
}
|
49
libnotify/notifyd/service.h
Normal file
49
libnotify/notifyd/service.h
Normal 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
86
libnotify/notifyd/table.h
Normal 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
465
libnotify/notifyd/timer.c
Normal 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
59
libnotify/notifyd/timer.h
Normal 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);
|
6
libnotify/notifyd/xcodescripts/mk_notify_conf.sh
Executable file
6
libnotify/notifyd/xcodescripts/mk_notify_conf.sh
Executable 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
|
220
libnotify/notifyutil/notifyutil.1
Normal file
220
libnotify/notifyutil/notifyutil.1
Normal 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)
|
751
libnotify/notifyutil/notifyutil.c
Normal file
751
libnotify/notifyutil/notifyutil.c
Normal 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
763
libnotify/table.c
Normal 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
88
libnotify/table.h
Normal 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_ */
|
29
libnotify/xcodeconfig/base.xcconfig
Normal file
29
libnotify/xcodeconfig/base.xcconfig
Normal 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
|
31
libnotify/xcodeconfig/libnotify.xcconfig
Normal file
31
libnotify/xcodeconfig/libnotify.xcconfig
Normal 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
|
5
libnotify/xcodeconfig/notifyd.xcconfig
Normal file
5
libnotify/xcodeconfig/notifyd.xcconfig
Normal file
@ -0,0 +1,5 @@
|
||||
#include "base.xcconfig"
|
||||
|
||||
INSTALL_PATH_ACTUAL = /usr/sbin
|
||||
|
||||
OTHER_LDFLAGS = -lCrashReporterClient
|
4
libnotify/xcodeconfig/notifyutil.xcconfig
Normal file
4
libnotify/xcodeconfig/notifyutil.xcconfig
Normal file
@ -0,0 +1,4 @@
|
||||
#include "base.xcconfig"
|
||||
|
||||
INSTALL_PATH_ACTUAL = /usr/bin
|
||||
|
5
libnotify/xcodescripts/no-sim-man.sh
Executable file
5
libnotify/xcodescripts/no-sim-man.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
if [[ "${PLATFORM_NAME}" =~ "simulator" ]]; then
|
||||
rm -rf ${DSTROOT}${INSTALL_PATH_PREFIX}/usr/share/man
|
||||
fi
|
5
libnotify/xcodescripts/sim-compat-symlink.sh
Executable file
5
libnotify/xcodescripts/sim-compat-symlink.sh
Executable 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
2711
platform-include/dns_sd.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user