Merge branch 'illumos'
This commit is contained in:
commit
83e0598cad
384
COPYING
Normal file
384
COPYING
Normal file
|
@ -0,0 +1,384 @@
|
||||||
|
Unless otherwise noted, all files in this distribution are released
|
||||||
|
under the Common Development and Distribution License (CDDL).
|
||||||
|
Exceptions are noted within the associated source files.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
1.1. "Contributor" means each individual or entity that creates
|
||||||
|
or contributes to the creation of Modifications.
|
||||||
|
|
||||||
|
1.2. "Contributor Version" means the combination of the Original
|
||||||
|
Software, prior Modifications used by a Contributor (if any),
|
||||||
|
and the Modifications made by that particular Contributor.
|
||||||
|
|
||||||
|
1.3. "Covered Software" means (a) the Original Software, or (b)
|
||||||
|
Modifications, or (c) the combination of files containing
|
||||||
|
Original Software with files containing Modifications, in
|
||||||
|
each case including portions thereof.
|
||||||
|
|
||||||
|
1.4. "Executable" means the Covered Software in any form other
|
||||||
|
than Source Code.
|
||||||
|
|
||||||
|
1.5. "Initial Developer" means the individual or entity that first
|
||||||
|
makes Original Software available under this License.
|
||||||
|
|
||||||
|
1.6. "Larger Work" means a work which combines Covered Software or
|
||||||
|
portions thereof with code not governed by the terms of this
|
||||||
|
License.
|
||||||
|
|
||||||
|
1.7. "License" means this document.
|
||||||
|
|
||||||
|
1.8. "Licensable" means having the right to grant, to the maximum
|
||||||
|
extent possible, whether at the time of the initial grant or
|
||||||
|
subsequently acquired, any and all of the rights conveyed
|
||||||
|
herein.
|
||||||
|
|
||||||
|
1.9. "Modifications" means the Source Code and Executable form of
|
||||||
|
any of the following:
|
||||||
|
|
||||||
|
A. Any file that results from an addition to, deletion from or
|
||||||
|
modification of the contents of a file containing Original
|
||||||
|
Software or previous Modifications;
|
||||||
|
|
||||||
|
B. Any new file that contains any part of the Original
|
||||||
|
Software or previous Modifications; or
|
||||||
|
|
||||||
|
C. Any new file that is contributed or otherwise made
|
||||||
|
available under the terms of this License.
|
||||||
|
|
||||||
|
1.10. "Original Software" means the Source Code and Executable
|
||||||
|
form of computer software code that is originally released
|
||||||
|
under this License.
|
||||||
|
|
||||||
|
1.11. "Patent Claims" means any patent claim(s), now owned or
|
||||||
|
hereafter acquired, including without limitation, method,
|
||||||
|
process, and apparatus claims, in any patent Licensable by
|
||||||
|
grantor.
|
||||||
|
|
||||||
|
1.12. "Source Code" means (a) the common form of computer software
|
||||||
|
code in which modifications are made and (b) associated
|
||||||
|
documentation included in or with such code.
|
||||||
|
|
||||||
|
1.13. "You" (or "Your") means an individual or a legal entity
|
||||||
|
exercising rights under, and complying with all of the terms
|
||||||
|
of, this License. For legal entities, "You" includes any
|
||||||
|
entity which controls, is controlled by, or is under common
|
||||||
|
control with You. For purposes of this definition,
|
||||||
|
"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 more than fifty
|
||||||
|
percent (50%) of the outstanding shares or beneficial
|
||||||
|
ownership of such entity.
|
||||||
|
|
||||||
|
2. License Grants.
|
||||||
|
|
||||||
|
2.1. The Initial Developer Grant.
|
||||||
|
|
||||||
|
Conditioned upon Your compliance with Section 3.1 below and
|
||||||
|
subject to third party intellectual property claims, the Initial
|
||||||
|
Developer hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
(a) under intellectual property rights (other than patent or
|
||||||
|
trademark) Licensable by Initial Developer, to use,
|
||||||
|
reproduce, modify, display, perform, sublicense and
|
||||||
|
distribute the Original Software (or portions thereof),
|
||||||
|
with or without Modifications, and/or as part of a Larger
|
||||||
|
Work; and
|
||||||
|
|
||||||
|
(b) under Patent Claims infringed by the making, using or
|
||||||
|
selling of Original Software, to make, have made, use,
|
||||||
|
practice, sell, and offer for sale, and/or otherwise
|
||||||
|
dispose of the Original Software (or portions thereof).
|
||||||
|
|
||||||
|
(c) The licenses granted in Sections 2.1(a) and (b) are
|
||||||
|
effective on the date Initial Developer first distributes
|
||||||
|
or otherwise makes the Original Software available to a
|
||||||
|
third party under the terms of this License.
|
||||||
|
|
||||||
|
(d) Notwithstanding Section 2.1(b) above, no patent license is
|
||||||
|
granted: (1) for code that You delete from the Original
|
||||||
|
Software, or (2) for infringements caused by: (i) the
|
||||||
|
modification of the Original Software, or (ii) the
|
||||||
|
combination of the Original Software with other software
|
||||||
|
or devices.
|
||||||
|
|
||||||
|
2.2. Contributor Grant.
|
||||||
|
|
||||||
|
Conditioned upon Your compliance with Section 3.1 below and
|
||||||
|
subject to third party intellectual property claims, each
|
||||||
|
Contributor hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
(a) under intellectual property rights (other than patent or
|
||||||
|
trademark) Licensable by Contributor to use, reproduce,
|
||||||
|
modify, display, perform, sublicense and distribute the
|
||||||
|
Modifications created by such Contributor (or portions
|
||||||
|
thereof), either on an unmodified basis, with other
|
||||||
|
Modifications, as Covered Software and/or as part of a
|
||||||
|
Larger Work; and
|
||||||
|
|
||||||
|
(b) under Patent Claims infringed by the making, using, or
|
||||||
|
selling of Modifications made by that Contributor either
|
||||||
|
alone and/or in combination with its Contributor Version
|
||||||
|
(or portions of such combination), to make, use, sell,
|
||||||
|
offer for sale, have made, and/or otherwise dispose of:
|
||||||
|
(1) Modifications made by that Contributor (or portions
|
||||||
|
thereof); and (2) the combination of Modifications made by
|
||||||
|
that Contributor with its Contributor Version (or portions
|
||||||
|
of such combination).
|
||||||
|
|
||||||
|
(c) The licenses granted in Sections 2.2(a) and 2.2(b) are
|
||||||
|
effective on the date Contributor first distributes or
|
||||||
|
otherwise makes the Modifications available to a third
|
||||||
|
party.
|
||||||
|
|
||||||
|
(d) Notwithstanding Section 2.2(b) above, no patent license is
|
||||||
|
granted: (1) for any code that Contributor has deleted
|
||||||
|
from the Contributor Version; (2) for infringements caused
|
||||||
|
by: (i) third party modifications of Contributor Version,
|
||||||
|
or (ii) the combination of Modifications made by that
|
||||||
|
Contributor with other software (except as part of the
|
||||||
|
Contributor Version) or other devices; or (3) under Patent
|
||||||
|
Claims infringed by Covered Software in the absence of
|
||||||
|
Modifications made by that Contributor.
|
||||||
|
|
||||||
|
3. Distribution Obligations.
|
||||||
|
|
||||||
|
3.1. Availability of Source Code.
|
||||||
|
|
||||||
|
Any Covered Software that You distribute or otherwise make
|
||||||
|
available in Executable form must also be made available in Source
|
||||||
|
Code form and that Source Code form must be distributed only under
|
||||||
|
the terms of this License. You must include a copy of this
|
||||||
|
License with every copy of the Source Code form of the Covered
|
||||||
|
Software You distribute or otherwise make available. You must
|
||||||
|
inform recipients of any such Covered Software in Executable form
|
||||||
|
as to how they can obtain such Covered Software in Source Code
|
||||||
|
form in a reasonable manner on or through a medium customarily
|
||||||
|
used for software exchange.
|
||||||
|
|
||||||
|
3.2. Modifications.
|
||||||
|
|
||||||
|
The Modifications that You create or to which You contribute are
|
||||||
|
governed by the terms of this License. You represent that You
|
||||||
|
believe Your Modifications are Your original creation(s) and/or
|
||||||
|
You have sufficient rights to grant the rights conveyed by this
|
||||||
|
License.
|
||||||
|
|
||||||
|
3.3. Required Notices.
|
||||||
|
|
||||||
|
You must include a notice in each of Your Modifications that
|
||||||
|
identifies You as the Contributor of the Modification. You may
|
||||||
|
not remove or alter any copyright, patent or trademark notices
|
||||||
|
contained within the Covered Software, or any notices of licensing
|
||||||
|
or any descriptive text giving attribution to any Contributor or
|
||||||
|
the Initial Developer.
|
||||||
|
|
||||||
|
3.4. Application of Additional Terms.
|
||||||
|
|
||||||
|
You may not offer or impose any terms on any Covered Software in
|
||||||
|
Source Code form that alters or restricts the applicable version
|
||||||
|
of this License or the recipients' rights hereunder. You may
|
||||||
|
choose to offer, and to charge a fee for, warranty, support,
|
||||||
|
indemnity or liability obligations to one or more recipients of
|
||||||
|
Covered Software. However, you may do so only on Your own behalf,
|
||||||
|
and not on behalf of the Initial Developer or any Contributor.
|
||||||
|
You must make it absolutely clear that any such warranty, support,
|
||||||
|
indemnity or liability obligation is offered by You alone, and You
|
||||||
|
hereby agree to indemnify the Initial Developer and every
|
||||||
|
Contributor for any liability incurred by the Initial Developer or
|
||||||
|
such Contributor as a result of warranty, support, indemnity or
|
||||||
|
liability terms You offer.
|
||||||
|
|
||||||
|
3.5. Distribution of Executable Versions.
|
||||||
|
|
||||||
|
You may distribute the Executable form of the Covered Software
|
||||||
|
under the terms of this License or under the terms of a license of
|
||||||
|
Your choice, which may contain terms different from this License,
|
||||||
|
provided that You are in compliance with the terms of this License
|
||||||
|
and that the license for the Executable form does not attempt to
|
||||||
|
limit or alter the recipient's rights in the Source Code form from
|
||||||
|
the rights set forth in this License. If You distribute the
|
||||||
|
Covered Software in Executable form under a different license, You
|
||||||
|
must make it absolutely clear that any terms which differ from
|
||||||
|
this License are offered by You alone, not by the Initial
|
||||||
|
Developer or Contributor. You hereby agree to indemnify the
|
||||||
|
Initial Developer and every Contributor for any liability incurred
|
||||||
|
by the Initial Developer or such Contributor as a result of any
|
||||||
|
such terms You offer.
|
||||||
|
|
||||||
|
3.6. Larger Works.
|
||||||
|
|
||||||
|
You may create a Larger Work by combining Covered Software with
|
||||||
|
other code not governed by the terms of this License and
|
||||||
|
distribute the Larger Work as a single product. In such a case,
|
||||||
|
You must make sure the requirements of this License are fulfilled
|
||||||
|
for the Covered Software.
|
||||||
|
|
||||||
|
4. Versions of the License.
|
||||||
|
|
||||||
|
4.1. New Versions.
|
||||||
|
|
||||||
|
Sun Microsystems, Inc. is the initial license steward and may
|
||||||
|
publish revised and/or new versions of this License from time to
|
||||||
|
time. Each version will be given a distinguishing version number.
|
||||||
|
Except as provided in Section 4.3, no one other than the license
|
||||||
|
steward has the right to modify this License.
|
||||||
|
|
||||||
|
4.2. Effect of New Versions.
|
||||||
|
|
||||||
|
You may always continue to use, distribute or otherwise make the
|
||||||
|
Covered Software available under the terms of the version of the
|
||||||
|
License under which You originally received the Covered Software.
|
||||||
|
If the Initial Developer includes a notice in the Original
|
||||||
|
Software prohibiting it from being distributed or otherwise made
|
||||||
|
available under any subsequent version of the License, You must
|
||||||
|
distribute and make the Covered Software available under the terms
|
||||||
|
of the version of the License under which You originally received
|
||||||
|
the Covered Software. Otherwise, You may also choose to use,
|
||||||
|
distribute or otherwise make the Covered Software available under
|
||||||
|
the terms of any subsequent version of the License published by
|
||||||
|
the license steward.
|
||||||
|
|
||||||
|
4.3. Modified Versions.
|
||||||
|
|
||||||
|
When You are an Initial Developer and You want to create a new
|
||||||
|
license for Your Original Software, You may create and use a
|
||||||
|
modified version of this License if You: (a) rename the license
|
||||||
|
and remove any references to the name of the license steward
|
||||||
|
(except to note that the license differs from this License); and
|
||||||
|
(b) otherwise make it clear that the license contains terms which
|
||||||
|
differ from this License.
|
||||||
|
|
||||||
|
5. DISCLAIMER OF WARRANTY.
|
||||||
|
|
||||||
|
COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS"
|
||||||
|
BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
|
||||||
|
INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED
|
||||||
|
SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR
|
||||||
|
PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
|
||||||
|
PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY
|
||||||
|
COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
|
||||||
|
INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
|
||||||
|
NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
|
||||||
|
WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
|
||||||
|
ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS
|
||||||
|
DISCLAIMER.
|
||||||
|
|
||||||
|
6. TERMINATION.
|
||||||
|
|
||||||
|
6.1. This License and the rights granted hereunder will terminate
|
||||||
|
automatically if You fail to comply with terms herein and fail to
|
||||||
|
cure such breach within 30 days of becoming aware of the breach.
|
||||||
|
Provisions which, by their nature, must remain in effect beyond
|
||||||
|
the termination of this License shall survive.
|
||||||
|
|
||||||
|
6.2. If You assert a patent infringement claim (excluding
|
||||||
|
declaratory judgment actions) against Initial Developer or a
|
||||||
|
Contributor (the Initial Developer or Contributor against whom You
|
||||||
|
assert such claim is referred to as "Participant") alleging that
|
||||||
|
the Participant Software (meaning the Contributor Version where
|
||||||
|
the Participant is a Contributor or the Original Software where
|
||||||
|
the Participant is the Initial Developer) directly or indirectly
|
||||||
|
infringes any patent, then any and all rights granted directly or
|
||||||
|
indirectly to You by such Participant, the Initial Developer (if
|
||||||
|
the Initial Developer is not the Participant) and all Contributors
|
||||||
|
under Sections 2.1 and/or 2.2 of this License shall, upon 60 days
|
||||||
|
notice from Participant terminate prospectively and automatically
|
||||||
|
at the expiration of such 60 day notice period, unless if within
|
||||||
|
such 60 day period You withdraw Your claim with respect to the
|
||||||
|
Participant Software against such Participant either unilaterally
|
||||||
|
or pursuant to a written agreement with Participant.
|
||||||
|
|
||||||
|
6.3. In the event of termination under Sections 6.1 or 6.2 above,
|
||||||
|
all end user licenses that have been validly granted by You or any
|
||||||
|
distributor hereunder prior to termination (excluding licenses
|
||||||
|
granted to You by any distributor) shall survive termination.
|
||||||
|
|
||||||
|
7. LIMITATION OF LIABILITY.
|
||||||
|
|
||||||
|
UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
|
||||||
|
(INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
|
||||||
|
INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF
|
||||||
|
COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE
|
||||||
|
LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
|
||||||
|
CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT
|
||||||
|
LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK
|
||||||
|
STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
|
||||||
|
COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
|
||||||
|
INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
|
||||||
|
LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL
|
||||||
|
INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT
|
||||||
|
APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO
|
||||||
|
NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT
|
||||||
|
APPLY TO YOU.
|
||||||
|
|
||||||
|
8. U.S. GOVERNMENT END USERS.
|
||||||
|
|
||||||
|
The Covered Software is a "commercial item," as that term is
|
||||||
|
defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
|
||||||
|
computer software" (as that term is defined at 48
|
||||||
|
C.F.R. 252.227-7014(a)(1)) and "commercial computer software
|
||||||
|
documentation" as such terms are used in 48 C.F.R. 12.212
|
||||||
|
(Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48
|
||||||
|
C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all
|
||||||
|
U.S. Government End Users acquire Covered Software with only those
|
||||||
|
rights set forth herein. This U.S. Government Rights clause is in
|
||||||
|
lieu of, and supersedes, any other FAR, DFAR, or other clause or
|
||||||
|
provision that addresses Government rights in computer software
|
||||||
|
under this License.
|
||||||
|
|
||||||
|
9. MISCELLANEOUS.
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning subject
|
||||||
|
matter hereof. If any provision of this License is held to be
|
||||||
|
unenforceable, such provision shall be reformed only to the extent
|
||||||
|
necessary to make it enforceable. This License shall be governed
|
||||||
|
by the law of the jurisdiction specified in a notice contained
|
||||||
|
within the Original Software (except to the extent applicable law,
|
||||||
|
if any, provides otherwise), excluding such jurisdiction's
|
||||||
|
conflict-of-law provisions. Any litigation relating to this
|
||||||
|
License shall be subject to the jurisdiction of the courts located
|
||||||
|
in the jurisdiction and venue specified in a notice contained
|
||||||
|
within the Original Software, with the losing party responsible
|
||||||
|
for costs, including, without limitation, court costs and
|
||||||
|
reasonable attorneys' fees and expenses. The application of the
|
||||||
|
United Nations Convention on Contracts for the International Sale
|
||||||
|
of Goods is expressly excluded. Any law or regulation which
|
||||||
|
provides that the language of a contract shall be construed
|
||||||
|
against the drafter shall not apply to this License. You agree
|
||||||
|
that You alone are responsible for compliance with the United
|
||||||
|
States export administration regulations (and the export control
|
||||||
|
laws and regulation of any other countries) when You use,
|
||||||
|
distribute or otherwise make available any Covered Software.
|
||||||
|
|
||||||
|
10. RESPONSIBILITY FOR CLAIMS.
|
||||||
|
|
||||||
|
As between Initial Developer and the Contributors, each party is
|
||||||
|
responsible for claims and damages arising, directly or
|
||||||
|
indirectly, out of its utilization of rights under this License
|
||||||
|
and You agree to work with Initial Developer and Contributors to
|
||||||
|
distribute such responsibility on an equitable basis. Nothing
|
||||||
|
herein is intended or shall be deemed to constitute any admission
|
||||||
|
of liability.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND
|
||||||
|
DISTRIBUTION LICENSE (CDDL)
|
||||||
|
|
||||||
|
For Covered Software in this distribution, this License shall
|
||||||
|
be governed by the laws of the State of California (excluding
|
||||||
|
conflict-of-law provisions).
|
||||||
|
|
||||||
|
Any litigation relating to this License shall be subject to the
|
||||||
|
jurisdiction of the Federal Courts of the Northern District of
|
||||||
|
California and the state courts of the State of California, with
|
||||||
|
venue lying in Santa Clara County, California.
|
846
bin/ar.cc
Normal file
846
bin/ar.cc
Normal file
|
@ -0,0 +1,846 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ar.c
|
||||||
|
*
|
||||||
|
* Deal with the lib.a(member.o) and lib.a((entry-point)) notations
|
||||||
|
*
|
||||||
|
* Look inside archives for notations a(b) and a((b))
|
||||||
|
* a(b) is file member b in archive a
|
||||||
|
* a((b)) is entry point b in object archive a
|
||||||
|
*
|
||||||
|
* For 6.0, create a make which can understand all archive
|
||||||
|
* formats. This is kind of tricky, and <ar.h> isnt any help.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <alloca.h> /* alloca() */
|
||||||
|
#include <ar.h>
|
||||||
|
#include <errno.h> /* errno */
|
||||||
|
#include <fcntl.h> /* open() */
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <mksh/misc.h> /* retmem_mb() */
|
||||||
|
|
||||||
|
struct ranlib {
|
||||||
|
union {
|
||||||
|
off_t ran_strx; /* string table index of */
|
||||||
|
char *ran_name; /* symbol defined by */
|
||||||
|
} ran_un;
|
||||||
|
off_t ran_off; /* library member at this offset */
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <unistd.h> /* close() */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined macros
|
||||||
|
*/
|
||||||
|
#ifndef S5EMUL
|
||||||
|
#undef BITSPERBYTE
|
||||||
|
#define BITSPERBYTE 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines for all the different archive formats. See next comment
|
||||||
|
* block for justification for not using <ar.h>s versions.
|
||||||
|
*/
|
||||||
|
#define AR_5_MAGIC "<ar>" /* 5.0 format magic string */
|
||||||
|
#define AR_5_MAGIC_LENGTH 4 /* 5.0 format string length */
|
||||||
|
|
||||||
|
#define AR_PORT_MAGIC "!<arch>\n" /* Port. (6.0) magic string */
|
||||||
|
#define AR_PORT_MAGIC_LENGTH 8 /* Port. (6.0) string length */
|
||||||
|
#define AR_PORT_END_MAGIC "`\n" /* Port. (6.0) end of header */
|
||||||
|
#define AR_PORT_WORD 4 /* Port. (6.0) 'word' length */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* These are the archive file headers for the formats. Note
|
||||||
|
* that it really doesnt matter if these structures are defined
|
||||||
|
* here. They are correct as of the respective archive format
|
||||||
|
* releases. If the archive format is changed, then since backwards
|
||||||
|
* compatability is the desired behavior, a new structure is added
|
||||||
|
* to the list.
|
||||||
|
*/
|
||||||
|
typedef struct { /* 5.0 ar header format: vax family; 3b family */
|
||||||
|
char ar_magic[AR_5_MAGIC_LENGTH]; /* AR_5_MAGIC*/
|
||||||
|
char ar_name[16]; /* Space terminated */
|
||||||
|
char ar_date[AR_PORT_WORD]; /* sgetl() accessed */
|
||||||
|
char ar_syms[AR_PORT_WORD]; /* sgetl() accessed */
|
||||||
|
} Arh_5;
|
||||||
|
|
||||||
|
typedef struct { /* 5.0 ar symbol format: vax family; 3b family */
|
||||||
|
char sym_name[8]; /* Space terminated */
|
||||||
|
char sym_ptr[AR_PORT_WORD]; /* sgetl() accessed */
|
||||||
|
} Ars_5;
|
||||||
|
|
||||||
|
typedef struct { /* 5.0 ar member format: vax family; 3b family */
|
||||||
|
char arf_name[16]; /* Space terminated */
|
||||||
|
char arf_date[AR_PORT_WORD]; /* sgetl() accessed */
|
||||||
|
char arf_uid[AR_PORT_WORD]; /* sgetl() accessed */
|
||||||
|
char arf_gid[AR_PORT_WORD]; /* sgetl() accessed */
|
||||||
|
char arf_mode[AR_PORT_WORD]; /* sgetl() accessed */
|
||||||
|
char arf_size[AR_PORT_WORD]; /* sgetl() accessed */
|
||||||
|
} Arf_5;
|
||||||
|
|
||||||
|
typedef struct { /* Portable (6.0) ar format: vax family; 3b family */
|
||||||
|
char ar_name[16]; /* Space terminated */
|
||||||
|
/* left-adjusted fields; decimal ascii; blank filled */
|
||||||
|
char ar_date[12];
|
||||||
|
char ar_uid[6];
|
||||||
|
char ar_gid[6];
|
||||||
|
char ar_mode[8]; /* octal ascii */
|
||||||
|
char ar_size[10];
|
||||||
|
/* special end-of-header string (AR_PORT_END_MAGIC) */
|
||||||
|
char ar_fmag[2];
|
||||||
|
} Ar_port;
|
||||||
|
|
||||||
|
enum ar_type {
|
||||||
|
AR_5,
|
||||||
|
AR_PORT
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned int ar_port_word; // must be 4-bytes long
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FILE *fd;
|
||||||
|
/* to distiguish ar format */
|
||||||
|
enum ar_type type;
|
||||||
|
/* where first ar member header is at */
|
||||||
|
long first_ar_mem;
|
||||||
|
/* where the symbol lookup starts */
|
||||||
|
long sym_begin;
|
||||||
|
/* the number of symbols available */
|
||||||
|
long num_symbols;
|
||||||
|
/* length of symbol directory file */
|
||||||
|
long sym_size;
|
||||||
|
Arh_5 arh_5;
|
||||||
|
Ars_5 ars_5;
|
||||||
|
Arf_5 arf_5;
|
||||||
|
Ar_port ar_port;
|
||||||
|
} Ar;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
extern timestruc_t& read_archive(register Name target);
|
||||||
|
static Boolean open_archive(char *filename, register Ar *arp);
|
||||||
|
static void close_archive(register Ar *arp);
|
||||||
|
static Boolean read_archive_dir(register Ar *arp, Name library, char **long_names_table);
|
||||||
|
static void translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table);
|
||||||
|
static long sgetl(char *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* read_archive(target)
|
||||||
|
*
|
||||||
|
* Read the contents of an ar file.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The time the member was created
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target The member to find time for
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* empty_name The Name ""
|
||||||
|
*/
|
||||||
|
|
||||||
|
int read_member_header (Ar_port *header, FILE *fd, char* filename);
|
||||||
|
int process_long_names_member (register Ar *arp, char **long_names_table, char *filename);
|
||||||
|
|
||||||
|
timestruc_t&
|
||||||
|
read_archive(register Name target)
|
||||||
|
{
|
||||||
|
register Property member;
|
||||||
|
wchar_t *slash;
|
||||||
|
String_rec true_member_name;
|
||||||
|
wchar_t buffer[STRING_BUFFER_LENGTH];
|
||||||
|
register Name true_member = NULL;
|
||||||
|
Ar ar;
|
||||||
|
char *long_names_table = NULL; /* Table of long
|
||||||
|
member names */
|
||||||
|
|
||||||
|
member = get_prop(target->prop, member_prop);
|
||||||
|
/*
|
||||||
|
* Check if the member has directory component.
|
||||||
|
* If so, remove the dir and see if we know the date.
|
||||||
|
*/
|
||||||
|
if (member->body.member.member != NULL) {
|
||||||
|
Wstring member_string(member->body.member.member);
|
||||||
|
wchar_t * wcb = member_string.get_string();
|
||||||
|
if((slash = (wchar_t *) wcsrchr(wcb, (int) slash_char)) != NULL) {
|
||||||
|
INIT_STRING_FROM_STACK(true_member_name, buffer);
|
||||||
|
append_string(member->body.member.library->string_mb,
|
||||||
|
&true_member_name,
|
||||||
|
FIND_LENGTH);
|
||||||
|
append_char((int) parenleft_char, &true_member_name);
|
||||||
|
append_string(slash + 1, &true_member_name, FIND_LENGTH);
|
||||||
|
append_char((int) parenright_char, &true_member_name);
|
||||||
|
true_member = GETNAME(true_member_name.buffer.start,
|
||||||
|
FIND_LENGTH);
|
||||||
|
if (true_member->stat.time != file_no_time) {
|
||||||
|
target->stat.time = true_member->stat.time;
|
||||||
|
return target->stat.time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (open_archive(member->body.member.library->string_mb, &ar) == failed) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
target->stat.stat_errno = ENOENT;
|
||||||
|
close_archive(&ar);
|
||||||
|
if (member->body.member.member == NULL) {
|
||||||
|
member->body.member.member = empty_name;
|
||||||
|
}
|
||||||
|
return target->stat.time = file_doesnt_exist;
|
||||||
|
} else {
|
||||||
|
fatal(gettext("Can't access archive `%s': %s"),
|
||||||
|
member->body.member.library->string_mb,
|
||||||
|
errmsg(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (target->stat.time == file_no_time) {
|
||||||
|
if (read_archive_dir(&ar, member->body.member.library,
|
||||||
|
&long_names_table)
|
||||||
|
== failed){
|
||||||
|
fatal(gettext("Can't access archive `%s': %s"),
|
||||||
|
member->body.member.library->string_mb,
|
||||||
|
errmsg(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (member->body.member.entry != NULL) {
|
||||||
|
translate_entry(&ar, target, member,&long_names_table);
|
||||||
|
}
|
||||||
|
close_archive(&ar);
|
||||||
|
if (long_names_table) {
|
||||||
|
retmem_mb(long_names_table);
|
||||||
|
}
|
||||||
|
if (true_member != NULL) {
|
||||||
|
target->stat.time = true_member->stat.time;
|
||||||
|
}
|
||||||
|
if (target->stat.time == file_no_time) {
|
||||||
|
target->stat.time = file_doesnt_exist;
|
||||||
|
}
|
||||||
|
return target->stat.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open_archive(filename, arp)
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* Indicates if open failed or not
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* filename The name of the archive we need to read
|
||||||
|
* arp Pointer to ar file description block
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static Boolean
|
||||||
|
open_archive(char *filename, register Ar *arp)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char mag_5[AR_5_MAGIC_LENGTH];
|
||||||
|
char mag_port[AR_PORT_MAGIC_LENGTH];
|
||||||
|
char buffer[4];
|
||||||
|
|
||||||
|
arp->fd = NULL;
|
||||||
|
fd = open_vroot(filename, O_RDONLY, 0, NULL, VROOT_DEFAULT);
|
||||||
|
if ((fd < 0) || ((arp->fd = fdopen(fd, "r")) == NULL)) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
(void) fcntl(fileno(arp->fd), F_SETFD, 1);
|
||||||
|
|
||||||
|
if (fread(mag_port, AR_PORT_MAGIC_LENGTH, 1, arp->fd) != 1) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
if (IS_EQUALN(mag_port, AR_PORT_MAGIC, AR_PORT_MAGIC_LENGTH)) {
|
||||||
|
arp->type = AR_PORT;
|
||||||
|
/*
|
||||||
|
* Read in first member header to find out if there is
|
||||||
|
* a symbol definition table.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ret = read_member_header(&arp->ar_port, arp->fd, filename);
|
||||||
|
if (ret == failed) {
|
||||||
|
return failed;
|
||||||
|
} else if(ret == -1) {
|
||||||
|
/* There is no member header - empty archive */
|
||||||
|
arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
|
||||||
|
arp->first_ar_mem = ftell(arp->fd);
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The following values are the default if there is
|
||||||
|
* no symbol directory and long member names.
|
||||||
|
*/
|
||||||
|
arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
|
||||||
|
arp->first_ar_mem = ftell(arp->fd) - (long) sizeof (Ar_port);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do we have a symbol table? A symbol table is always
|
||||||
|
* the first member in an archive. In 4.1.x it has the
|
||||||
|
* name __.SYMDEF, in SVr4, it has the name "/ "
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
MBSTOWCS(wcs_buffer, "/ ");
|
||||||
|
if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
|
||||||
|
*/
|
||||||
|
if (IS_EQUALN(arp->ar_port.ar_name,
|
||||||
|
"/ ",
|
||||||
|
16)) {
|
||||||
|
if (sscanf(arp->ar_port.ar_size,
|
||||||
|
"%ld",
|
||||||
|
&arp->sym_size) != 1) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
arp->sym_size += (arp->sym_size & 1); /* round up */
|
||||||
|
if (fread(buffer, sizeof buffer, 1, arp->fd) != 1) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
arp->num_symbols = sgetl(buffer);
|
||||||
|
arp->sym_begin = ftell(arp->fd);
|
||||||
|
arp->first_ar_mem = arp->sym_begin +
|
||||||
|
arp->sym_size - sizeof buffer;
|
||||||
|
}
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
fatal(gettext("`%s' is not an archive"), filename);
|
||||||
|
/* NOTREACHED */
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close_archive(arp)
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* arp Pointer to ar file description block
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
close_archive(register Ar *arp)
|
||||||
|
{
|
||||||
|
if (arp->fd != NULL) {
|
||||||
|
(void) fclose(arp->fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* read_archive_dir(arp, library, long_names_table)
|
||||||
|
*
|
||||||
|
* Reads the directory of an archive and enters all
|
||||||
|
* the members into the make symboltable in lib(member) format
|
||||||
|
* with their dates.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* arp Pointer to ar file description block
|
||||||
|
* library Name of lib to enter members for.
|
||||||
|
* Used to form "lib(member)" string.
|
||||||
|
* long_names_table table that contains list of members
|
||||||
|
* with names > 15 characters long
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static Boolean
|
||||||
|
read_archive_dir(register Ar *arp, Name library, char **long_names_table)
|
||||||
|
{
|
||||||
|
wchar_t *name_string;
|
||||||
|
wchar_t *member_string;
|
||||||
|
register long len;
|
||||||
|
register wchar_t *p;
|
||||||
|
register char *q;
|
||||||
|
register Name name;
|
||||||
|
Property member;
|
||||||
|
long ptr;
|
||||||
|
long date;
|
||||||
|
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If any of the members has a name > 15 chars,
|
||||||
|
* it will be found here.
|
||||||
|
*/
|
||||||
|
if (process_long_names_member(arp, long_names_table, library->string_mb) == failed) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
name_string = ALLOC_WC((int) (library->hash.length +
|
||||||
|
(int) ar_member_name_len * 2));
|
||||||
|
(void) mbstowcs(name_string, library->string_mb, (int) library->hash.length);
|
||||||
|
member_string = name_string + library->hash.length;
|
||||||
|
*member_string++ = (int) parenleft_char;
|
||||||
|
|
||||||
|
if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
|
||||||
|
goto read_error;
|
||||||
|
}
|
||||||
|
/* Read the directory using the appropriate format */
|
||||||
|
switch (arp->type) {
|
||||||
|
case AR_5:
|
||||||
|
for (;;) {
|
||||||
|
if (fread((char *) &arp->arf_5, sizeof arp->arf_5, 1, arp->fd)
|
||||||
|
!= 1) {
|
||||||
|
if (feof(arp->fd)) {
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len = sizeof arp->arf_5.arf_name;
|
||||||
|
for (p = member_string, q = arp->arf_5.arf_name;
|
||||||
|
(len > 0) && (*q != (int) nul_char) && !isspace(*q);
|
||||||
|
) {
|
||||||
|
MBTOWC(p, q);
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
*p++ = (int) parenright_char;
|
||||||
|
*p = (int) nul_char;
|
||||||
|
name = GETNAME(name_string, FIND_LENGTH);
|
||||||
|
/*
|
||||||
|
* [tolik] Fix for dmake bug 1234018.
|
||||||
|
* If name->stat.time is already set, then it should not
|
||||||
|
* be changed. (D)make propogates time stamp for one
|
||||||
|
* member, and when it calls exists() for another member,
|
||||||
|
* the first one may be changed.
|
||||||
|
*/
|
||||||
|
if(name->stat.time == file_no_time) {
|
||||||
|
name->stat.time.tv_sec = sgetl(arp->arf_5.arf_date);
|
||||||
|
name->stat.time.tv_nsec = LONG_MAX;
|
||||||
|
}
|
||||||
|
name->is_member = library->is_member;
|
||||||
|
member = maybe_append_prop(name, member_prop);
|
||||||
|
member->body.member.library = library;
|
||||||
|
*--p = (int) nul_char;
|
||||||
|
if (member->body.member.member == NULL) {
|
||||||
|
member->body.member.member =
|
||||||
|
GETNAME(member_string, FIND_LENGTH);
|
||||||
|
}
|
||||||
|
ptr = sgetl(arp->arf_5.arf_size);
|
||||||
|
ptr += (ptr & 1);
|
||||||
|
if (fseek(arp->fd, ptr, 1) != 0) {
|
||||||
|
goto read_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AR_PORT:
|
||||||
|
for (;;) {
|
||||||
|
if ((fread((char *) &arp->ar_port,
|
||||||
|
sizeof arp->ar_port,
|
||||||
|
1,
|
||||||
|
arp->fd) != 1) ||
|
||||||
|
!IS_EQUALN(arp->ar_port.ar_fmag,
|
||||||
|
AR_PORT_END_MAGIC,
|
||||||
|
sizeof arp->ar_port.ar_fmag)) {
|
||||||
|
if (feof(arp->fd)) {
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
fatal(
|
||||||
|
gettext("Read error in archive `%s': invalid archive file member header at 0x%x"),
|
||||||
|
library->string_mb,
|
||||||
|
ftell(arp->fd)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/* If it's a long name, retrieve it from long name table */
|
||||||
|
if (arp->ar_port.ar_name[0] == '/') {
|
||||||
|
/*
|
||||||
|
* "len" is used for hashing the string.
|
||||||
|
* We're using "ar_member_name_len" instead of
|
||||||
|
* the actual name length since it's the longest
|
||||||
|
* string the "ar" command can handle at this
|
||||||
|
* point.
|
||||||
|
*/
|
||||||
|
len = ar_member_name_len;
|
||||||
|
sscanf(arp->ar_port.ar_name + 1,
|
||||||
|
"%ld",
|
||||||
|
&offset);
|
||||||
|
q = *long_names_table + offset;
|
||||||
|
} else {
|
||||||
|
q = arp->ar_port.ar_name;
|
||||||
|
len = sizeof arp->ar_port.ar_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = member_string;
|
||||||
|
(len > 0) &&
|
||||||
|
(*q != (int) nul_char) &&
|
||||||
|
!isspace(*q) &&
|
||||||
|
(*q != (int) slash_char);
|
||||||
|
) {
|
||||||
|
MBTOWC(p, q);
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
*p++ = (int) parenright_char;
|
||||||
|
*p = (int) nul_char;
|
||||||
|
name = GETNAME(name_string, FIND_LENGTH);
|
||||||
|
name->is_member = library->is_member;
|
||||||
|
member = maybe_append_prop(name, member_prop);
|
||||||
|
member->body.member.library = library;
|
||||||
|
*--p = (int) nul_char;
|
||||||
|
if (member->body.member.member == NULL) {
|
||||||
|
member->body.member.member =
|
||||||
|
GETNAME(member_string, FIND_LENGTH);
|
||||||
|
}
|
||||||
|
if (sscanf(arp->ar_port.ar_date, "%ld", &date) != 1) {
|
||||||
|
WCSTOMBS(mbs_buffer, name_string);
|
||||||
|
fatal(gettext("Bad date field for member `%s' in archive `%s'"),
|
||||||
|
mbs_buffer,
|
||||||
|
library->string_mb);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* [tolik] Fix for dmake bug 1234018.
|
||||||
|
*/
|
||||||
|
if(name->stat.time == file_no_time) {
|
||||||
|
name->stat.time.tv_sec = date;
|
||||||
|
name->stat.time.tv_nsec = LONG_MAX;
|
||||||
|
}
|
||||||
|
if (sscanf(arp->ar_port.ar_size, "%ld", &ptr) != 1) {
|
||||||
|
WCSTOMBS(mbs_buffer, name_string);
|
||||||
|
fatal(gettext("Bad size field for member `%s' in archive `%s'"),
|
||||||
|
mbs_buffer,
|
||||||
|
library->string_mb);
|
||||||
|
}
|
||||||
|
ptr += (ptr & 1);
|
||||||
|
if (fseek(arp->fd, ptr, 1) != 0) {
|
||||||
|
goto read_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only here if fread() [or IS_EQUALN()] failed and not at EOF */
|
||||||
|
read_error:
|
||||||
|
fatal(gettext("Read error in archive `%s': %s"),
|
||||||
|
library->string_mb,
|
||||||
|
errmsg(errno));
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* process_long_names_member(arp)
|
||||||
|
*
|
||||||
|
* If the archive contains members with names longer
|
||||||
|
* than 15 characters, then it has a special member
|
||||||
|
* with the name "// " that contains a table
|
||||||
|
* of null-terminated long names. This member
|
||||||
|
* is always the first member, after the symbol table
|
||||||
|
* if it exists.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* arp Pointer to ar file description block
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
process_long_names_member(register Ar *arp, char **long_names_table, char *filename)
|
||||||
|
{
|
||||||
|
Ar_port *ar_member_header;
|
||||||
|
int table_size;
|
||||||
|
|
||||||
|
if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
if ((ar_member_header =
|
||||||
|
(Ar_port *) alloca((int) sizeof(Ar_port))) == NULL){
|
||||||
|
perror(gettext("memory allocation failure"));
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
int ret = read_member_header(ar_member_header, arp->fd, filename);
|
||||||
|
if (ret == failed) {
|
||||||
|
return failed;
|
||||||
|
} else if(ret == -1) {
|
||||||
|
/* There is no member header - empty archive */
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
/* Do we have special member containing long names? */
|
||||||
|
if (IS_EQUALN(ar_member_header->ar_name,
|
||||||
|
"// ",
|
||||||
|
16)){
|
||||||
|
if (sscanf(ar_member_header->ar_size,
|
||||||
|
"%ld",
|
||||||
|
&table_size) != 1) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
*long_names_table = (char *) malloc(table_size);
|
||||||
|
/* Read the list of long member names into the table */
|
||||||
|
if (fread(*long_names_table, table_size, 1, arp->fd) != 1) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
arp->first_ar_mem = ftell(arp->fd);
|
||||||
|
}
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* translate_entry(arp, target, member)
|
||||||
|
*
|
||||||
|
* Finds the member for one lib.a((entry))
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* arp Pointer to ar file description block
|
||||||
|
* target Target to find member name for
|
||||||
|
* member Property to fill in with info
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table)
|
||||||
|
{
|
||||||
|
register int len;
|
||||||
|
register int i;
|
||||||
|
wchar_t *member_string;
|
||||||
|
ar_port_word *offs;
|
||||||
|
int strtablen;
|
||||||
|
char *syms; /* string table */
|
||||||
|
char *csym; /* string table */
|
||||||
|
ar_port_word *offend; /* end of offsets table */
|
||||||
|
int date;
|
||||||
|
register wchar_t *ap;
|
||||||
|
register char *hp;
|
||||||
|
int maxs;
|
||||||
|
int offset;
|
||||||
|
char buffer[4];
|
||||||
|
|
||||||
|
if (arp->sym_begin == 0L || arp->num_symbols == 0L) {
|
||||||
|
fatal(gettext("Cannot find symbol `%s' in archive `%s'"),
|
||||||
|
member->body.member.entry->string_mb,
|
||||||
|
member->body.member.library->string_mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fseek(arp->fd, arp->sym_begin, 0) != 0) {
|
||||||
|
goto read_error;
|
||||||
|
}
|
||||||
|
member_string = ALLOC_WC((int) ((int) ar_member_name_len * 2));
|
||||||
|
|
||||||
|
switch (arp->type) {
|
||||||
|
case AR_5:
|
||||||
|
if ((len = member->body.member.entry->hash.length) > 8) {
|
||||||
|
len = 8;
|
||||||
|
}
|
||||||
|
for (i = 0; i < arp->num_symbols; i++) {
|
||||||
|
if (fread((char *) &arp->ars_5,
|
||||||
|
sizeof arp->ars_5,
|
||||||
|
1,
|
||||||
|
arp->fd) != 1) {
|
||||||
|
goto read_error;
|
||||||
|
}
|
||||||
|
if (IS_EQUALN(arp->ars_5.sym_name,
|
||||||
|
member->body.member.entry->string_mb,
|
||||||
|
len)) {
|
||||||
|
if ((fseek(arp->fd,
|
||||||
|
sgetl(arp->ars_5.sym_ptr),
|
||||||
|
0) != 0) ||
|
||||||
|
(fread((char *) &arp->arf_5,
|
||||||
|
sizeof arp->arf_5,
|
||||||
|
1,
|
||||||
|
arp->fd) != 1)) {
|
||||||
|
goto read_error;
|
||||||
|
}
|
||||||
|
MBSTOWCS(wcs_buffer, arp->arf_5.arf_name);
|
||||||
|
(void) wcsncpy(member_string,
|
||||||
|
wcs_buffer,
|
||||||
|
wcslen(wcs_buffer));
|
||||||
|
member_string[sizeof(arp->arf_5.arf_name)] =
|
||||||
|
(int) nul_char;
|
||||||
|
member->body.member.member =
|
||||||
|
GETNAME(member_string, FIND_LENGTH);
|
||||||
|
target->stat.time.tv_sec = sgetl(arp->arf_5.arf_date);
|
||||||
|
target->stat.time.tv_nsec = LONG_MAX;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AR_PORT:
|
||||||
|
offs = (ar_port_word *) alloca((int) (arp->num_symbols * AR_PORT_WORD));
|
||||||
|
if (fread((char *) offs,
|
||||||
|
AR_PORT_WORD,
|
||||||
|
(int) arp->num_symbols,
|
||||||
|
arp->fd) != arp->num_symbols) {
|
||||||
|
goto read_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;i<arp->num_symbols;i++) {
|
||||||
|
*((int*)buffer)=offs[i];
|
||||||
|
offs[i]=(ar_port_word)sgetl(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
strtablen=arp->sym_size-4-(int) (arp->num_symbols * AR_PORT_WORD);
|
||||||
|
syms = (char *) alloca(strtablen);
|
||||||
|
if (fread(syms,
|
||||||
|
sizeof (char),
|
||||||
|
strtablen,
|
||||||
|
arp->fd) != strtablen) {
|
||||||
|
goto read_error;
|
||||||
|
}
|
||||||
|
offend = &offs[arp->num_symbols];
|
||||||
|
while (offs < offend) {
|
||||||
|
maxs = strlen(member->body.member.entry->string_mb);
|
||||||
|
if(strlen(syms) > maxs)
|
||||||
|
maxs = strlen(syms);
|
||||||
|
if (IS_EQUALN(syms,
|
||||||
|
member->body.member.entry->string_mb,
|
||||||
|
maxs)) {
|
||||||
|
if (fseek(arp->fd,
|
||||||
|
(long) *offs,
|
||||||
|
0) != 0) {
|
||||||
|
goto read_error;
|
||||||
|
}
|
||||||
|
if ((fread((char *) &arp->ar_port,
|
||||||
|
sizeof arp->ar_port,
|
||||||
|
1,
|
||||||
|
arp->fd) != 1) ||
|
||||||
|
!IS_EQUALN(arp->ar_port.ar_fmag,
|
||||||
|
AR_PORT_END_MAGIC,
|
||||||
|
sizeof arp->ar_port.ar_fmag)) {
|
||||||
|
goto read_error;
|
||||||
|
}
|
||||||
|
if (sscanf(arp->ar_port.ar_date,
|
||||||
|
"%ld",
|
||||||
|
&date) != 1) {
|
||||||
|
fatal(gettext("Bad date field for member `%s' in archive `%s'"),
|
||||||
|
arp->ar_port.ar_name,
|
||||||
|
target->string_mb);
|
||||||
|
}
|
||||||
|
/* If it's a long name, retrieve it from long name table */
|
||||||
|
if (arp->ar_port.ar_name[0] == '/') {
|
||||||
|
sscanf(arp->ar_port.ar_name + 1,
|
||||||
|
"%ld",
|
||||||
|
&offset);
|
||||||
|
len = ar_member_name_len;
|
||||||
|
hp = *long_names_table + offset;
|
||||||
|
} else {
|
||||||
|
len = sizeof arp->ar_port.ar_name;
|
||||||
|
hp = arp->ar_port.ar_name;
|
||||||
|
}
|
||||||
|
ap = member_string;
|
||||||
|
while (*hp &&
|
||||||
|
(*hp != (int) slash_char) &&
|
||||||
|
(ap < &member_string[len])) {
|
||||||
|
MBTOWC(ap, hp);
|
||||||
|
ap++;
|
||||||
|
hp++;
|
||||||
|
}
|
||||||
|
*ap = (int) nul_char;
|
||||||
|
member->body.member.member =
|
||||||
|
GETNAME(member_string, FIND_LENGTH);
|
||||||
|
target->stat.time.tv_sec = date;
|
||||||
|
target->stat.time.tv_nsec = LONG_MAX;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
offs++;
|
||||||
|
while(*syms!='\0') syms++;
|
||||||
|
syms++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fatal(gettext("Cannot find symbol `%s' in archive `%s'"),
|
||||||
|
member->body.member.entry->string_mb,
|
||||||
|
member->body.member.library->string_mb);
|
||||||
|
/*NOTREACHED*/
|
||||||
|
|
||||||
|
read_error:
|
||||||
|
if (ferror(arp->fd)) {
|
||||||
|
fatal(gettext("Read error in archive `%s': %s"),
|
||||||
|
member->body.member.library->string_mb,
|
||||||
|
errmsg(errno));
|
||||||
|
} else {
|
||||||
|
fatal(gettext("Read error in archive `%s': Premature EOF"),
|
||||||
|
member->body.member.library->string_mb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sgetl(buffer)
|
||||||
|
*
|
||||||
|
* The intent here is to provide a means to make the value of
|
||||||
|
* bytes in an io-buffer correspond to the value of a long
|
||||||
|
* in the memory while doing the io a long at a time.
|
||||||
|
* Files written and read in this way are machine-independent.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* Long int read from buffer
|
||||||
|
* Parameters:
|
||||||
|
* buffer buffer we need to read long int from
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static long
|
||||||
|
sgetl(register char *buffer)
|
||||||
|
{
|
||||||
|
register long w = 0;
|
||||||
|
register int i = BITSPERBYTE * AR_PORT_WORD;
|
||||||
|
|
||||||
|
while ((i -= BITSPERBYTE) >= 0) {
|
||||||
|
w |= (long) ((unsigned char) *buffer++) << i;
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* read_member_header(header, fd, filename)
|
||||||
|
*
|
||||||
|
* reads the member header for the 4.1.x and SVr4 archives.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* fails if read error or member
|
||||||
|
* header is not the right format
|
||||||
|
* Parameters:
|
||||||
|
* header There's one before each archive member
|
||||||
|
* fd file descriptor for the archive file.
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
read_member_header(Ar_port *header, FILE *fd, char* filename)
|
||||||
|
{
|
||||||
|
int num = fread((char *) header, sizeof (Ar_port), 1, fd);
|
||||||
|
if (num != 1 && feof(fd)) {
|
||||||
|
/* There is no member header - empty archive */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((num != 1) ||
|
||||||
|
!IS_EQUALN(
|
||||||
|
AR_PORT_END_MAGIC,
|
||||||
|
header->ar_fmag,
|
||||||
|
sizeof (header->ar_fmag)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
fatal(
|
||||||
|
gettext("Read error in archive `%s': invalid archive file member header at 0x%x"),
|
||||||
|
filename,
|
||||||
|
ftell(fd)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
|
108
bin/depvar.cc
Normal file
108
bin/depvar.cc
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1995 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <libintl.h>
|
||||||
|
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <mksh/misc.h> /* getmem() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file deals with "Dependency Variables".
|
||||||
|
* The "-V var" command line option is used to indicate
|
||||||
|
* that var is a dependency variable. Used in conjunction with
|
||||||
|
* the -P option the user is asking if the named variables affect
|
||||||
|
* the dependencies of the given target.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _Depvar {
|
||||||
|
Name name; /* Name of variable */
|
||||||
|
struct _Depvar *next; /* Linked list */
|
||||||
|
Boolean cmdline; /* Macro defined on the cmdline? */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _Depvar *Depvar;
|
||||||
|
|
||||||
|
static Depvar depvar_list;
|
||||||
|
static Depvar *bpatch = &depvar_list;
|
||||||
|
static Boolean variant_deps;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a name to the list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
depvar_add_to_list(Name name, Boolean cmdline)
|
||||||
|
{
|
||||||
|
Depvar dv;
|
||||||
|
|
||||||
|
dv = ALLOC(Depvar);
|
||||||
|
dv->name = name;
|
||||||
|
dv->next = NULL;
|
||||||
|
dv->cmdline = cmdline;
|
||||||
|
*bpatch = dv;
|
||||||
|
bpatch = &dv->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The macro `name' has been used in either the left-hand or
|
||||||
|
* right-hand side of a dependency. See if it is in the
|
||||||
|
* list. Two things are looked for. Names given as args
|
||||||
|
* to the -V list are checked so as to set the same/differ
|
||||||
|
* output for the -P option. Names given as macro=value
|
||||||
|
* command-line args are checked and, if found, an NSE
|
||||||
|
* warning is produced.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
depvar_dep_macro_used(Name name)
|
||||||
|
{
|
||||||
|
Depvar dv;
|
||||||
|
|
||||||
|
for (dv = depvar_list; dv != NULL; dv = dv->next) {
|
||||||
|
if (name == dv->name) {
|
||||||
|
variant_deps = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print the results. If any of the Dependency Variables
|
||||||
|
* affected the dependencies then the dependencies potentially
|
||||||
|
* differ because of these variables.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
depvar_print_results(void)
|
||||||
|
{
|
||||||
|
if (variant_deps) {
|
||||||
|
printf(gettext("differ\n"));
|
||||||
|
} else {
|
||||||
|
printf(gettext("same\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
3209
bin/doname.cc
Normal file
3209
bin/doname.cc
Normal file
File diff suppressed because it is too large
Load diff
163
bin/dosys.cc
Normal file
163
bin/dosys.cc
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dosys.cc
|
||||||
|
*
|
||||||
|
* Execute one commandline
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <fcntl.h> /* open() */
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <mksh/dosys.h> /* doshell(), doexec() */
|
||||||
|
#include <mksh/misc.h> /* getmem() */
|
||||||
|
#include <sys/stat.h> /* open() */
|
||||||
|
#include <unistd.h> /* getpid() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static variables
|
||||||
|
*/
|
||||||
|
static int filter_file;
|
||||||
|
static char *filter_file_name;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
static void redirect_stderr(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dosys(command, ignore_error, call_make, silent_error, target)
|
||||||
|
*
|
||||||
|
* Check if command string contains meta chars and dispatch to
|
||||||
|
* the proper routine for executing one command line.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* Indicates if the command execution failed
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* command The command to run
|
||||||
|
* ignore_error Should make abort when an error is seen?
|
||||||
|
* call_make Did command reference $(MAKE) ?
|
||||||
|
* silent_error Should error messages be suppressed for pmake?
|
||||||
|
* target Target we are building
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* do_not_exec_rule Is -n on?
|
||||||
|
* working_on_targets We started processing real targets
|
||||||
|
*/
|
||||||
|
Doname
|
||||||
|
dosys(register Name command, register Boolean ignore_error, register Boolean call_make, Boolean silent_error, Boolean always_exec, Name target)
|
||||||
|
{
|
||||||
|
timestruc_t before;
|
||||||
|
register int length = command->hash.length;
|
||||||
|
Wstring wcb(command);
|
||||||
|
register wchar_t *p = wcb.get_string();
|
||||||
|
register wchar_t *q;
|
||||||
|
Doname result;
|
||||||
|
|
||||||
|
/* Strip spaces from head of command string */
|
||||||
|
while (iswspace(*p)) {
|
||||||
|
p++, length--;
|
||||||
|
}
|
||||||
|
if (*p == (int) nul_char) {
|
||||||
|
return build_failed;
|
||||||
|
}
|
||||||
|
/* If we are faking it we just return */
|
||||||
|
if (do_not_exec_rule &&
|
||||||
|
working_on_targets &&
|
||||||
|
!call_make &&
|
||||||
|
!always_exec) {
|
||||||
|
return build_ok;
|
||||||
|
}
|
||||||
|
/* no_action_was_taken is used to print special message */
|
||||||
|
no_action_was_taken = false;
|
||||||
|
|
||||||
|
/* Copy string to make it OK to write it. */
|
||||||
|
q = ALLOC_WC(length + 1);
|
||||||
|
(void) wcscpy(q, p);
|
||||||
|
/* Write the state file iff this command uses make. */
|
||||||
|
if (call_make && command_changed) {
|
||||||
|
write_state_file(0, false);
|
||||||
|
}
|
||||||
|
make_state->stat.time = file_no_time;
|
||||||
|
(void)exists(make_state);
|
||||||
|
before = make_state->stat.time;
|
||||||
|
/*
|
||||||
|
* Run command directly if it contains no shell meta chars,
|
||||||
|
* else run it using the shell.
|
||||||
|
*/
|
||||||
|
if (await(ignore_error,
|
||||||
|
silent_error,
|
||||||
|
target,
|
||||||
|
wcb.get_string(),
|
||||||
|
command->meta ?
|
||||||
|
doshell(q, ignore_error,
|
||||||
|
stdout_file, stderr_file, 0) :
|
||||||
|
doexec(q, ignore_error,
|
||||||
|
stdout_file, stderr_file,
|
||||||
|
vroot_path, 0),
|
||||||
|
NULL,
|
||||||
|
-1
|
||||||
|
)) {
|
||||||
|
result = build_ok;
|
||||||
|
} else {
|
||||||
|
result = build_failed;
|
||||||
|
}
|
||||||
|
retmem(q);
|
||||||
|
|
||||||
|
if ((report_dependencies_level == 0) &&
|
||||||
|
call_make) {
|
||||||
|
make_state->stat.time = file_no_time;
|
||||||
|
(void)exists(make_state);
|
||||||
|
if (before == make_state->stat.time) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
makefile_type = reading_statefile;
|
||||||
|
if (read_trace_level > 1) {
|
||||||
|
trace_reader = true;
|
||||||
|
}
|
||||||
|
temp_file_number++;
|
||||||
|
(void) read_simple_file(make_state,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true);
|
||||||
|
trace_reader = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
711
bin/files.cc
Normal file
711
bin/files.cc
Normal file
|
@ -0,0 +1,711 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* files.c
|
||||||
|
*
|
||||||
|
* Various file related routines:
|
||||||
|
* Figure out if file exists
|
||||||
|
* Wildcard resolution for directory reader
|
||||||
|
* Directory reader
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <dirent.h> /* opendir() */
|
||||||
|
#include <errno.h> /* errno */
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <mksh/macro.h> /* getvar() */
|
||||||
|
#include <mksh/misc.h> /* get_prop(), append_prop() */
|
||||||
|
#include <sys/stat.h> /* lstat() */
|
||||||
|
#include <libintl.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
extern timestruc_t& exists(register Name target);
|
||||||
|
extern void set_target_stat(register Name target, struct stat buf);
|
||||||
|
static timestruc_t& vpath_exists(register Name target);
|
||||||
|
static Name enter_file_name(wchar_t *name_string, wchar_t *library);
|
||||||
|
static Boolean star_match(register char *string, register char *pattern);
|
||||||
|
static Boolean amatch(register wchar_t *string, register wchar_t *pattern);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exists(target)
|
||||||
|
*
|
||||||
|
* Figure out the timestamp for one target.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The time the target was created
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target The target to check
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* debug_level Should we trace the stat call?
|
||||||
|
* recursion_level Used for tracing
|
||||||
|
* vpath_defined Was the variable VPATH defined in environment?
|
||||||
|
*/
|
||||||
|
timestruc_t&
|
||||||
|
exists(register Name target)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
register int result;
|
||||||
|
|
||||||
|
/* We cache stat information. */
|
||||||
|
if (target->stat.time != file_no_time) {
|
||||||
|
return target->stat.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the target is a member, we have to extract the time
|
||||||
|
* from the archive.
|
||||||
|
*/
|
||||||
|
if (target->is_member &&
|
||||||
|
(get_prop(target->prop, member_prop) != NULL)) {
|
||||||
|
return read_archive(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug_level > 1) {
|
||||||
|
(void) printf("%*sstat(%s)\n",
|
||||||
|
recursion_level,
|
||||||
|
"",
|
||||||
|
target->string_mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = lstat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT);
|
||||||
|
if ((result != -1) && ((buf.st_mode & S_IFMT) == S_IFLNK)) {
|
||||||
|
/*
|
||||||
|
* If the file is a symbolic link, we remember that
|
||||||
|
* and then we get the status for the refd file.
|
||||||
|
*/
|
||||||
|
target->stat.is_sym_link = true;
|
||||||
|
result = stat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT);
|
||||||
|
} else {
|
||||||
|
target->stat.is_sym_link = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
target->stat.time = file_doesnt_exist;
|
||||||
|
target->stat.stat_errno = errno;
|
||||||
|
if ((errno == ENOENT) &&
|
||||||
|
vpath_defined &&
|
||||||
|
/* azv, fixing bug 1262942, VPATH works with a leaf name
|
||||||
|
* but not a directory name.
|
||||||
|
*/
|
||||||
|
(target->string_mb[0] != (int) slash_char) ) {
|
||||||
|
/* BID_1214655 */
|
||||||
|
/* azv */
|
||||||
|
vpath_exists(target);
|
||||||
|
// return vpath_exists(target);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Save all the information we need about the file */
|
||||||
|
target->stat.stat_errno = 0;
|
||||||
|
target->stat.is_file = true;
|
||||||
|
target->stat.mode = buf.st_mode & 0777;
|
||||||
|
target->stat.size = buf.st_size;
|
||||||
|
target->stat.is_dir =
|
||||||
|
BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR);
|
||||||
|
if (target->stat.is_dir) {
|
||||||
|
target->stat.time = file_is_dir;
|
||||||
|
} else {
|
||||||
|
/* target->stat.time = buf.st_mtime; */
|
||||||
|
/* BID_1129806 */
|
||||||
|
/* vis@nbsp.nsk.su */
|
||||||
|
target->stat.time = MAX(buf.st_mtim, file_min_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((target->colon_splits > 0) &&
|
||||||
|
(get_prop(target->prop, time_prop) == NULL)) {
|
||||||
|
append_prop(target, time_prop)->body.time.time =
|
||||||
|
target->stat.time;
|
||||||
|
}
|
||||||
|
return target->stat.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set_target_stat( target, buf)
|
||||||
|
*
|
||||||
|
* Called by exists() to set some stat fields in the Name structure
|
||||||
|
* to those read by the stat_vroot() call (from disk).
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target The target whose stat field is set
|
||||||
|
* buf stat values (on disk) of the file
|
||||||
|
* represented by target.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
set_target_stat(register Name target, struct stat buf)
|
||||||
|
{
|
||||||
|
target->stat.stat_errno = 0;
|
||||||
|
target->stat.is_file = true;
|
||||||
|
target->stat.mode = buf.st_mode & 0777;
|
||||||
|
target->stat.size = buf.st_size;
|
||||||
|
target->stat.is_dir =
|
||||||
|
BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR);
|
||||||
|
if (target->stat.is_dir) {
|
||||||
|
target->stat.time = file_is_dir;
|
||||||
|
} else {
|
||||||
|
/* target->stat.time = buf.st_mtime; */
|
||||||
|
/* BID_1129806 */
|
||||||
|
/* vis@nbsp.nsk.su */
|
||||||
|
target->stat.time = MAX(buf.st_mtim, file_min_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vpath_exists(target)
|
||||||
|
*
|
||||||
|
* Called if exists() discovers that there is a VPATH defined.
|
||||||
|
* This function stats the VPATH translation of the target.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The time the target was created
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target The target to check
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* vpath_name The Name "VPATH", used to get macro value
|
||||||
|
*/
|
||||||
|
static timestruc_t&
|
||||||
|
vpath_exists(register Name target)
|
||||||
|
{
|
||||||
|
wchar_t *vpath;
|
||||||
|
wchar_t file_name[MAXPATHLEN];
|
||||||
|
wchar_t *name_p;
|
||||||
|
Name alias;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To avoid recursive search through VPATH when exists(alias) is called
|
||||||
|
*/
|
||||||
|
vpath_defined = false;
|
||||||
|
|
||||||
|
Wstring wcb(getvar(vpath_name));
|
||||||
|
Wstring wcb1(target);
|
||||||
|
|
||||||
|
vpath = wcb.get_string();
|
||||||
|
|
||||||
|
while (*vpath != (int) nul_char) {
|
||||||
|
name_p = file_name;
|
||||||
|
while ((*vpath != (int) colon_char) &&
|
||||||
|
(*vpath != (int) nul_char)) {
|
||||||
|
*name_p++ = *vpath++;
|
||||||
|
}
|
||||||
|
*name_p++ = (int) slash_char;
|
||||||
|
(void) wcscpy(name_p, wcb1.get_string());
|
||||||
|
alias = GETNAME(file_name, FIND_LENGTH);
|
||||||
|
if (exists(alias) != file_doesnt_exist) {
|
||||||
|
target->stat.is_file = true;
|
||||||
|
target->stat.mode = alias->stat.mode;
|
||||||
|
target->stat.size = alias->stat.size;
|
||||||
|
target->stat.is_dir = alias->stat.is_dir;
|
||||||
|
target->stat.time = alias->stat.time;
|
||||||
|
maybe_append_prop(target, vpath_alias_prop)->
|
||||||
|
body.vpath_alias.alias = alias;
|
||||||
|
target->has_vpath_alias_prop = true;
|
||||||
|
vpath_defined = true;
|
||||||
|
return alias->stat.time;
|
||||||
|
}
|
||||||
|
while ((*vpath != (int) nul_char) &&
|
||||||
|
((*vpath == (int) colon_char) || iswspace(*vpath))) {
|
||||||
|
vpath++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Restore vpath_defined
|
||||||
|
*/
|
||||||
|
vpath_defined = true;
|
||||||
|
return target->stat.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* read_dir(dir, pattern, line, library)
|
||||||
|
*
|
||||||
|
* Used to enter the contents of directories into makes namespace.
|
||||||
|
* Presence of a file is important when scanning for implicit rules.
|
||||||
|
* read_dir() is also used to expand wildcards in dependency lists.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* Non-0 if we found files to match the pattern
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* dir Path to the directory to read
|
||||||
|
* pattern Pattern for that files should match or NULL
|
||||||
|
* line When we scan using a pattern we enter files
|
||||||
|
* we find as dependencies for this line
|
||||||
|
* library If we scan for "lib.a(<wildcard-member>)"
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* debug_level Should we trace the dir reading?
|
||||||
|
* dot The Name ".", compared against
|
||||||
|
* sccs_dir_path The path to the SCCS dir (from PROJECTDIR)
|
||||||
|
* vpath_defined Was the variable VPATH defined in environment?
|
||||||
|
* vpath_name The Name "VPATH", use to get macro value
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
read_dir(Name dir, wchar_t *pattern, Property line, wchar_t *library)
|
||||||
|
{
|
||||||
|
wchar_t file_name[MAXPATHLEN];
|
||||||
|
wchar_t *file_name_p = file_name;
|
||||||
|
Name file;
|
||||||
|
wchar_t plain_file_name[MAXPATHLEN];
|
||||||
|
wchar_t *plain_file_name_p;
|
||||||
|
Name plain_file;
|
||||||
|
wchar_t tmp_wcs_buffer[MAXPATHLEN];
|
||||||
|
DIR *dir_fd;
|
||||||
|
int m_local_dependency=0;
|
||||||
|
#define d_fileno d_ino
|
||||||
|
register struct dirent *dp;
|
||||||
|
wchar_t *vpath = NULL;
|
||||||
|
wchar_t *p;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if(dir->hash.length >= MAXPATHLEN) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Wstring wcb(dir);
|
||||||
|
Wstring vps;
|
||||||
|
|
||||||
|
/* A directory is only read once unless we need to expand wildcards. */
|
||||||
|
if (pattern == NULL) {
|
||||||
|
if (dir->has_read_dir) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dir->has_read_dir = true;
|
||||||
|
}
|
||||||
|
/* Check if VPATH is active and setup list if it is. */
|
||||||
|
if (vpath_defined && (dir == dot)) {
|
||||||
|
vps.init(getvar(vpath_name));
|
||||||
|
vpath = vps.get_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare the string where we build the full name of the
|
||||||
|
* files in the directory.
|
||||||
|
*/
|
||||||
|
if ((dir->hash.length > 1) || (wcb.get_string()[0] != (int) period_char)) {
|
||||||
|
(void) wcscpy(file_name, wcb.get_string());
|
||||||
|
MBSTOWCS(wcs_buffer, "/");
|
||||||
|
(void) wcscat(file_name, wcs_buffer);
|
||||||
|
file_name_p = file_name + wcslen(file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the directory. */
|
||||||
|
vpath_loop:
|
||||||
|
dir_fd = opendir(dir->string_mb);
|
||||||
|
if (dir_fd == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read all the directory entries. */
|
||||||
|
while ((dp = readdir(dir_fd)) != NULL) {
|
||||||
|
/* We ignore "." and ".." */
|
||||||
|
if ((dp->d_fileno == 0) ||
|
||||||
|
((dp->d_name[0] == (int) period_char) &&
|
||||||
|
((dp->d_name[1] == 0) ||
|
||||||
|
((dp->d_name[1] == (int) period_char) &&
|
||||||
|
(dp->d_name[2] == 0))))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Build the full name of the file using whatever
|
||||||
|
* path supplied to the function.
|
||||||
|
*/
|
||||||
|
MBSTOWCS(tmp_wcs_buffer, dp->d_name);
|
||||||
|
(void) wcscpy(file_name_p, tmp_wcs_buffer);
|
||||||
|
file = enter_file_name(file_name, library);
|
||||||
|
if ((pattern != NULL) && amatch(tmp_wcs_buffer, pattern)) {
|
||||||
|
/*
|
||||||
|
* If we are expanding a wildcard pattern, we
|
||||||
|
* enter the file as a dependency for the target.
|
||||||
|
*/
|
||||||
|
if (debug_level > 0){
|
||||||
|
WCSTOMBS(mbs_buffer, pattern);
|
||||||
|
(void) printf(gettext("'%s: %s' due to %s expansion\n"),
|
||||||
|
line->body.line.target->string_mb,
|
||||||
|
file->string_mb,
|
||||||
|
mbs_buffer);
|
||||||
|
}
|
||||||
|
enter_dependency(line, file, false);
|
||||||
|
result++;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If the file has an SCCS/s. file,
|
||||||
|
* we will detect that later on.
|
||||||
|
*/
|
||||||
|
file->stat.has_sccs = NO_SCCS;
|
||||||
|
/*
|
||||||
|
* If this is an s. file, we also enter it as if it
|
||||||
|
* existed in the plain directory.
|
||||||
|
*/
|
||||||
|
if ((dp->d_name[0] == 's') &&
|
||||||
|
(dp->d_name[1] == (int) period_char)) {
|
||||||
|
|
||||||
|
MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
|
||||||
|
plain_file_name_p = plain_file_name;
|
||||||
|
(void) wcscpy(plain_file_name_p, tmp_wcs_buffer);
|
||||||
|
plain_file = GETNAME(plain_file_name, FIND_LENGTH);
|
||||||
|
plain_file->stat.is_file = true;
|
||||||
|
plain_file->stat.has_sccs = HAS_SCCS;
|
||||||
|
/*
|
||||||
|
* Enter the s. file as a dependency for the
|
||||||
|
* plain file.
|
||||||
|
*/
|
||||||
|
maybe_append_prop(plain_file, sccs_prop)->
|
||||||
|
body.sccs.file = file;
|
||||||
|
MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
|
||||||
|
if ((pattern != NULL) &&
|
||||||
|
amatch(tmp_wcs_buffer, pattern)) {
|
||||||
|
if (debug_level > 0) {
|
||||||
|
WCSTOMBS(mbs_buffer, pattern);
|
||||||
|
(void) printf(gettext("'%s: %s' due to %s expansion\n"),
|
||||||
|
line->body.line.target->
|
||||||
|
string_mb,
|
||||||
|
plain_file->string_mb,
|
||||||
|
mbs_buffer);
|
||||||
|
}
|
||||||
|
enter_dependency(line, plain_file, false);
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) closedir(dir_fd);
|
||||||
|
if ((vpath != NULL) && (*vpath != (int) nul_char)) {
|
||||||
|
while ((*vpath != (int) nul_char) &&
|
||||||
|
(iswspace(*vpath) || (*vpath == (int) colon_char))) {
|
||||||
|
vpath++;
|
||||||
|
}
|
||||||
|
p = vpath;
|
||||||
|
while ((*vpath != (int) colon_char) &&
|
||||||
|
(*vpath != (int) nul_char)) {
|
||||||
|
vpath++;
|
||||||
|
}
|
||||||
|
if (vpath > p) {
|
||||||
|
dir = GETNAME(p, vpath - p);
|
||||||
|
goto vpath_loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* look into SCCS directory only if it's not svr4. For svr4 dont do that.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now read the SCCS directory.
|
||||||
|
* Files in the SCSC directory are considered to be part of the set of
|
||||||
|
* files in the plain directory. They are also entered in their own right.
|
||||||
|
* Prepare the string where we build the true name of the SCCS files.
|
||||||
|
*/
|
||||||
|
(void) wcsncpy(plain_file_name,
|
||||||
|
file_name,
|
||||||
|
file_name_p - file_name);
|
||||||
|
plain_file_name[file_name_p - file_name] = 0;
|
||||||
|
plain_file_name_p = plain_file_name + wcslen(plain_file_name);
|
||||||
|
|
||||||
|
if(!svr4) {
|
||||||
|
|
||||||
|
if (sccs_dir_path != NULL) {
|
||||||
|
wchar_t tmp_wchar;
|
||||||
|
wchar_t path[MAXPATHLEN];
|
||||||
|
char mb_path[MAXPATHLEN];
|
||||||
|
|
||||||
|
if (file_name_p - file_name > 0) {
|
||||||
|
tmp_wchar = *file_name_p;
|
||||||
|
*file_name_p = 0;
|
||||||
|
WCSTOMBS(mbs_buffer, file_name);
|
||||||
|
(void) sprintf(mb_path, "%s/%s/SCCS",
|
||||||
|
sccs_dir_path,
|
||||||
|
mbs_buffer);
|
||||||
|
*file_name_p = tmp_wchar;
|
||||||
|
} else {
|
||||||
|
(void) sprintf(mb_path, "%s/SCCS", sccs_dir_path);
|
||||||
|
}
|
||||||
|
MBSTOWCS(path, mb_path);
|
||||||
|
(void) wcscpy(file_name, path);
|
||||||
|
} else {
|
||||||
|
MBSTOWCS(wcs_buffer, "SCCS");
|
||||||
|
(void) wcscpy(file_name_p, wcs_buffer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MBSTOWCS(wcs_buffer, ".");
|
||||||
|
(void) wcscpy(file_name_p, wcs_buffer);
|
||||||
|
}
|
||||||
|
/* Internalize the constructed SCCS dir name. */
|
||||||
|
(void) exists(dir = GETNAME(file_name, FIND_LENGTH));
|
||||||
|
/* Just give up if the directory file doesnt exist. */
|
||||||
|
if (!dir->stat.is_file) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/* Open the directory. */
|
||||||
|
dir_fd = opendir(dir->string_mb);
|
||||||
|
if (dir_fd == NULL) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
MBSTOWCS(wcs_buffer, "/");
|
||||||
|
(void) wcscat(file_name, wcs_buffer);
|
||||||
|
file_name_p = file_name + wcslen(file_name);
|
||||||
|
|
||||||
|
while ((dp = readdir(dir_fd)) != NULL) {
|
||||||
|
if ((dp->d_fileno == 0) ||
|
||||||
|
((dp->d_name[0] == (int) period_char) &&
|
||||||
|
((dp->d_name[1] == 0) ||
|
||||||
|
((dp->d_name[1] == (int) period_char) &&
|
||||||
|
(dp->d_name[2] == 0))))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Construct and internalize the true name of the SCCS file. */
|
||||||
|
MBSTOWCS(wcs_buffer, dp->d_name);
|
||||||
|
(void) wcscpy(file_name_p, wcs_buffer);
|
||||||
|
file = GETNAME(file_name, FIND_LENGTH);
|
||||||
|
file->stat.is_file = true;
|
||||||
|
file->stat.has_sccs = NO_SCCS;
|
||||||
|
/*
|
||||||
|
* If this is an s. file, we also enter it as if it
|
||||||
|
* existed in the plain directory.
|
||||||
|
*/
|
||||||
|
if ((dp->d_name[0] == 's') &&
|
||||||
|
(dp->d_name[1] == (int) period_char)) {
|
||||||
|
|
||||||
|
MBSTOWCS(wcs_buffer, dp->d_name + 2);
|
||||||
|
(void) wcscpy(plain_file_name_p, wcs_buffer);
|
||||||
|
plain_file = GETNAME(plain_file_name, FIND_LENGTH);
|
||||||
|
plain_file->stat.is_file = true;
|
||||||
|
plain_file->stat.has_sccs = HAS_SCCS;
|
||||||
|
/* if sccs dependency is already set,skip */
|
||||||
|
if(plain_file->prop) {
|
||||||
|
Property sprop = get_prop(plain_file->prop,sccs_prop);
|
||||||
|
if(sprop != NULL) {
|
||||||
|
if (sprop->body.sccs.file) {
|
||||||
|
goto try_pattern;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enter the s. file as a dependency for the
|
||||||
|
* plain file.
|
||||||
|
*/
|
||||||
|
maybe_append_prop(plain_file, sccs_prop)->
|
||||||
|
body.sccs.file = file;
|
||||||
|
try_pattern:
|
||||||
|
MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
|
||||||
|
if ((pattern != NULL) &&
|
||||||
|
amatch(tmp_wcs_buffer, pattern)) {
|
||||||
|
if (debug_level > 0) {
|
||||||
|
WCSTOMBS(mbs_buffer, pattern);
|
||||||
|
(void) printf(gettext("'%s: %s' due to %s expansion\n"),
|
||||||
|
line->body.line.target->
|
||||||
|
string_mb,
|
||||||
|
plain_file->string_mb,
|
||||||
|
mbs_buffer);
|
||||||
|
}
|
||||||
|
enter_dependency(line, plain_file, false);
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) closedir(dir_fd);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* enter_file_name(name_string, library)
|
||||||
|
*
|
||||||
|
* Helper function for read_dir().
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The Name that was entered
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* name_string Name of the file we want to enter
|
||||||
|
* library The library it is a member of, if any
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static Name
|
||||||
|
enter_file_name(wchar_t *name_string, wchar_t *library)
|
||||||
|
{
|
||||||
|
wchar_t buffer[STRING_BUFFER_LENGTH];
|
||||||
|
String_rec lib_name;
|
||||||
|
Name name;
|
||||||
|
Property prop;
|
||||||
|
|
||||||
|
if (library == NULL) {
|
||||||
|
name = GETNAME(name_string, FIND_LENGTH);
|
||||||
|
name->stat.is_file = true;
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_STRING_FROM_STACK(lib_name, buffer);
|
||||||
|
append_string(library, &lib_name, FIND_LENGTH);
|
||||||
|
append_char((int) parenleft_char, &lib_name);
|
||||||
|
append_string(name_string, &lib_name, FIND_LENGTH);
|
||||||
|
append_char((int) parenright_char, &lib_name);
|
||||||
|
|
||||||
|
name = GETNAME(lib_name.buffer.start, FIND_LENGTH);
|
||||||
|
name->stat.is_file = true;
|
||||||
|
name->is_member = true;
|
||||||
|
prop = maybe_append_prop(name, member_prop);
|
||||||
|
prop->body.member.library = GETNAME(library, FIND_LENGTH);
|
||||||
|
prop->body.member.library->stat.is_file = true;
|
||||||
|
prop->body.member.entry = NULL;
|
||||||
|
prop->body.member.member = GETNAME(name_string, FIND_LENGTH);
|
||||||
|
prop->body.member.member->stat.is_file = true;
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* star_match(string, pattern)
|
||||||
|
*
|
||||||
|
* This is a regular shell type wildcard pattern matcher
|
||||||
|
* It is used when xpanding wildcards in dependency lists
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* Indication if the string matched the pattern
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* string String to match
|
||||||
|
* pattern Pattern to match it against
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static Boolean
|
||||||
|
star_match(register wchar_t *string, register wchar_t *pattern)
|
||||||
|
{
|
||||||
|
register int pattern_ch;
|
||||||
|
|
||||||
|
switch (*pattern) {
|
||||||
|
case 0:
|
||||||
|
return succeeded;
|
||||||
|
case bracketleft_char:
|
||||||
|
case question_char:
|
||||||
|
case asterisk_char:
|
||||||
|
while (*string) {
|
||||||
|
if (amatch(string++, pattern)) {
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pattern_ch = (int) *pattern++;
|
||||||
|
while (*string) {
|
||||||
|
if ((*string++ == pattern_ch) &&
|
||||||
|
amatch(string, pattern)) {
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* amatch(string, pattern)
|
||||||
|
*
|
||||||
|
* Helper function for shell pattern matching
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* Indication if the string matched the pattern
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* string String to match
|
||||||
|
* pattern Pattern to match it against
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static Boolean
|
||||||
|
amatch(register wchar_t *string, register wchar_t *pattern)
|
||||||
|
{
|
||||||
|
register long lower_bound;
|
||||||
|
register long string_ch;
|
||||||
|
register long pattern_ch;
|
||||||
|
register int k;
|
||||||
|
|
||||||
|
top:
|
||||||
|
for (; 1; pattern++, string++) {
|
||||||
|
lower_bound = 017777777777;
|
||||||
|
string_ch = *string;
|
||||||
|
switch (pattern_ch = *pattern) {
|
||||||
|
case bracketleft_char:
|
||||||
|
k = 0;
|
||||||
|
while ((pattern_ch = *++pattern) != 0) {
|
||||||
|
switch (pattern_ch) {
|
||||||
|
case bracketright_char:
|
||||||
|
if (!k) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
string++;
|
||||||
|
pattern++;
|
||||||
|
goto top;
|
||||||
|
case hyphen_char:
|
||||||
|
k |= (lower_bound <= string_ch) &&
|
||||||
|
(string_ch <=
|
||||||
|
(pattern_ch = pattern[1]));
|
||||||
|
default:
|
||||||
|
if (string_ch ==
|
||||||
|
(lower_bound = pattern_ch)) {
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return failed;
|
||||||
|
case asterisk_char:
|
||||||
|
return star_match(string, ++pattern);
|
||||||
|
case 0:
|
||||||
|
return BOOLEAN(!string_ch);
|
||||||
|
case question_char:
|
||||||
|
if (string_ch == 0) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (pattern_ch != string_ch) {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
181
bin/globals.cc
Normal file
181
bin/globals.cc
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* globals.cc
|
||||||
|
*
|
||||||
|
* This declares all global variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <nl_types.h>
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global variables used by make only
|
||||||
|
*/
|
||||||
|
FILE *dependency_report_file;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global variables used by make
|
||||||
|
*/
|
||||||
|
Boolean allrules_read=false;
|
||||||
|
Name posix_name;
|
||||||
|
Name svr4_name;
|
||||||
|
Boolean sdot_target; /* used to identify s.m(/M)akefile */
|
||||||
|
Boolean all_parallel;
|
||||||
|
Boolean assign_done;
|
||||||
|
int foo;
|
||||||
|
Boolean build_failed_seen;
|
||||||
|
Name built_last_make_run;
|
||||||
|
Name c_at;
|
||||||
|
Boolean cleanup;
|
||||||
|
Boolean close_report;
|
||||||
|
Boolean command_changed;
|
||||||
|
Boolean commands_done;
|
||||||
|
Chain conditional_targets;
|
||||||
|
Name conditionals;
|
||||||
|
Boolean continue_after_error; /* `-k' */
|
||||||
|
Property current_line;
|
||||||
|
Name current_make_version;
|
||||||
|
Name current_target;
|
||||||
|
short debug_level;
|
||||||
|
Cmd_line default_rule;
|
||||||
|
Name default_rule_name;
|
||||||
|
Name default_target_to_build;
|
||||||
|
Name dmake_group;
|
||||||
|
Name dmake_max_jobs;
|
||||||
|
Name dmake_mode;
|
||||||
|
DMake_mode dmake_mode_type;
|
||||||
|
Name dmake_output_mode;
|
||||||
|
DMake_output_mode output_mode = txt1_mode;
|
||||||
|
Name dmake_odir;
|
||||||
|
Name dmake_rcfile;
|
||||||
|
Name done;
|
||||||
|
Name dot;
|
||||||
|
Name dot_keep_state;
|
||||||
|
Name dot_keep_state_file;
|
||||||
|
Name empty_name;
|
||||||
|
Boolean fatal_in_progress;
|
||||||
|
int file_number;
|
||||||
|
#if 0
|
||||||
|
Boolean filter_stderr; /* `-X' */
|
||||||
|
#endif
|
||||||
|
Name force;
|
||||||
|
Name ignore_name;
|
||||||
|
Boolean ignore_errors; /* `-i' */
|
||||||
|
Boolean ignore_errors_all; /* `-i' */
|
||||||
|
Name init;
|
||||||
|
int job_msg_id;
|
||||||
|
Boolean keep_state;
|
||||||
|
Name make_state;
|
||||||
|
timestruc_t make_state_before;
|
||||||
|
Dependency makefiles_used;
|
||||||
|
Name makeflags;
|
||||||
|
// Boolean make_state_locked; // Moved to lib/mksh
|
||||||
|
Name make_version;
|
||||||
|
char mbs_buffer2[(MAXPATHLEN * MB_LEN_MAX)];
|
||||||
|
char *mbs_ptr;
|
||||||
|
char *mbs_ptr2;
|
||||||
|
Boolean depinfo_already_read = false;
|
||||||
|
Boolean no_action_was_taken = true; /* true if we've not **
|
||||||
|
** run any command */
|
||||||
|
|
||||||
|
Boolean no_parallel = false;
|
||||||
|
Name no_parallel_name;
|
||||||
|
Name not_auto;
|
||||||
|
Boolean only_parallel;
|
||||||
|
Boolean parallel;
|
||||||
|
Name parallel_name;
|
||||||
|
Name localhost_name;
|
||||||
|
int parallel_process_cnt;
|
||||||
|
Percent percent_list;
|
||||||
|
Dyntarget dyntarget_list;
|
||||||
|
Name plus;
|
||||||
|
Name pmake_machinesfile;
|
||||||
|
Name precious;
|
||||||
|
Name primary_makefile;
|
||||||
|
Boolean quest; /* `-q' */
|
||||||
|
short read_trace_level;
|
||||||
|
Boolean reading_dependencies = false;
|
||||||
|
Name recursive_name;
|
||||||
|
int recursion_level;
|
||||||
|
short report_dependencies_level = 0; /* -P */
|
||||||
|
Boolean report_pwd;
|
||||||
|
Boolean rewrite_statefile;
|
||||||
|
Running running_list;
|
||||||
|
char *sccs_dir_path;
|
||||||
|
Name sccs_get_name;
|
||||||
|
Name sccs_get_posix_name;
|
||||||
|
Cmd_line sccs_get_rule;
|
||||||
|
Cmd_line sccs_get_org_rule;
|
||||||
|
Cmd_line sccs_get_posix_rule;
|
||||||
|
Name get_name;
|
||||||
|
Cmd_line get_rule;
|
||||||
|
Name get_posix_name;
|
||||||
|
Cmd_line get_posix_rule;
|
||||||
|
Boolean all_precious;
|
||||||
|
Boolean silent_all; /* `-s' */
|
||||||
|
Boolean report_cwd; /* `-w' */
|
||||||
|
Boolean silent; /* `-s' */
|
||||||
|
Name silent_name;
|
||||||
|
char *stderr_file = NULL;
|
||||||
|
char *stdout_file = NULL;
|
||||||
|
Boolean stdout_stderr_same;
|
||||||
|
Dependency suffixes;
|
||||||
|
Name suffixes_name;
|
||||||
|
Name sunpro_dependencies;
|
||||||
|
Boolean target_variants;
|
||||||
|
const char *tmpdir = "/tmp";
|
||||||
|
const char *temp_file_directory = ".";
|
||||||
|
Name temp_file_name;
|
||||||
|
short temp_file_number;
|
||||||
|
time_t timing_start;
|
||||||
|
wchar_t *top_level_target;
|
||||||
|
Boolean touch; /* `-t' */
|
||||||
|
Boolean trace_reader; /* `-D' */
|
||||||
|
Boolean build_unconditional; /* `-u' */
|
||||||
|
pathpt vroot_path = VROOT_DEFAULT;
|
||||||
|
Name wait_name;
|
||||||
|
wchar_t wcs_buffer2[MAXPATHLEN];
|
||||||
|
wchar_t *wcs_ptr;
|
||||||
|
wchar_t *wcs_ptr2;
|
||||||
|
long int hostid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
|
1462
bin/implicit.cc
Normal file
1462
bin/implicit.cc
Normal file
File diff suppressed because it is too large
Load diff
167
bin/macro.cc
Normal file
167
bin/macro.cc
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* macro.cc
|
||||||
|
*
|
||||||
|
* Handle expansion of make macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <mksh/macro.h> /* getvar(), expand_value() */
|
||||||
|
#include <mksh/misc.h> /* getmem() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
setvar_append(register Name name, register Name value)
|
||||||
|
{
|
||||||
|
register Property macro_apx = get_prop(name->prop, macro_append_prop);
|
||||||
|
register Property macro = get_prop(name->prop, macro_prop);
|
||||||
|
int length;
|
||||||
|
String_rec destination;
|
||||||
|
wchar_t buffer[STRING_BUFFER_LENGTH];
|
||||||
|
register Chain chain;
|
||||||
|
Name val = NULL;
|
||||||
|
|
||||||
|
if(macro_apx == NULL) {
|
||||||
|
macro_apx = append_prop(name, macro_append_prop);
|
||||||
|
if(macro != NULL) {
|
||||||
|
macro_apx->body.macro_appendix.value = macro->body.macro.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val = macro_apx->body.macro_appendix.value_to_append;
|
||||||
|
|
||||||
|
INIT_STRING_FROM_STACK(destination, buffer);
|
||||||
|
buffer[0] = 0;
|
||||||
|
if (val != NULL) {
|
||||||
|
APPEND_NAME(val,
|
||||||
|
&destination,
|
||||||
|
(int) val->hash.length);
|
||||||
|
if (value != NULL) {
|
||||||
|
MBTOWC(wcs_buffer, " ");
|
||||||
|
append_char(wcs_buffer[0], &destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value != NULL) {
|
||||||
|
APPEND_NAME(value,
|
||||||
|
&destination,
|
||||||
|
(int) value->hash.length);
|
||||||
|
}
|
||||||
|
value = GETNAME(destination.buffer.start, FIND_LENGTH);
|
||||||
|
if (destination.free_after_use) {
|
||||||
|
retmem(destination.buffer.start);
|
||||||
|
}
|
||||||
|
macro_apx->body.macro_appendix.value_to_append = value;
|
||||||
|
|
||||||
|
SETVAR(name, empty_name, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setvar_envvar()
|
||||||
|
*
|
||||||
|
* This function scans the list of environment variables that have
|
||||||
|
* dynamic values and sets them.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* envvar A list of environment vars with $ in value
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
setvar_envvar(void)
|
||||||
|
{
|
||||||
|
wchar_t buffer[STRING_BUFFER_LENGTH];
|
||||||
|
int length;
|
||||||
|
register char *mbs, *tmp_mbs_buffer = NULL;
|
||||||
|
register char *env, *tmp_mbs_buffer2 = NULL;
|
||||||
|
Envvar p;
|
||||||
|
String_rec value;
|
||||||
|
|
||||||
|
for (p = envvar; p != NULL; p = p->next) {
|
||||||
|
if (p->already_put
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
INIT_STRING_FROM_STACK(value, buffer);
|
||||||
|
expand_value(p->value, &value, false);
|
||||||
|
if ((length = wcslen(value.buffer.start)) >= MAXPATHLEN) {
|
||||||
|
mbs = tmp_mbs_buffer = getmem((length + 1) * MB_LEN_MAX);
|
||||||
|
(void) wcstombs(mbs,
|
||||||
|
value.buffer.start,
|
||||||
|
(length + 1) * MB_LEN_MAX);
|
||||||
|
} else {
|
||||||
|
mbs = mbs_buffer;
|
||||||
|
WCSTOMBS(mbs, value.buffer.start);
|
||||||
|
}
|
||||||
|
length = 2 + strlen(p->name->string_mb) + strlen(mbs);
|
||||||
|
if (!p->already_put || length > (MAXPATHLEN * MB_LEN_MAX)) {
|
||||||
|
env = tmp_mbs_buffer2 = getmem(length);
|
||||||
|
} else {
|
||||||
|
env = mbs_buffer2;
|
||||||
|
}
|
||||||
|
(void) sprintf(env,
|
||||||
|
"%s=%s",
|
||||||
|
p->name->string_mb,
|
||||||
|
mbs);
|
||||||
|
if (!p->already_put) {
|
||||||
|
(void) putenv(env);
|
||||||
|
p->already_put = true;
|
||||||
|
if (p->env_string) {
|
||||||
|
retmem_mb(p->env_string);
|
||||||
|
}
|
||||||
|
p->env_string = env;
|
||||||
|
tmp_mbs_buffer2 = NULL; // We should not return this memory now
|
||||||
|
}
|
||||||
|
if (tmp_mbs_buffer2) {
|
||||||
|
retmem_mb(tmp_mbs_buffer2);
|
||||||
|
tmp_mbs_buffer2 = NULL;
|
||||||
|
}
|
||||||
|
if (tmp_mbs_buffer) {
|
||||||
|
retmem_mb(tmp_mbs_buffer);
|
||||||
|
tmp_mbs_buffer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
3215
bin/main.cc
Normal file
3215
bin/main.cc
Normal file
File diff suppressed because it is too large
Load diff
498
bin/make.rules.file
Normal file
498
bin/make.rules.file
Normal file
|
@ -0,0 +1,498 @@
|
||||||
|
#
|
||||||
|
# CDDL HEADER START
|
||||||
|
#
|
||||||
|
# The contents of this file are subject to the terms of the
|
||||||
|
# Common Development and Distribution License (the "License").
|
||||||
|
# You may not use this file except in compliance with the License.
|
||||||
|
#
|
||||||
|
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
# or http://www.opensolaris.org/os/licensing.
|
||||||
|
# See the License for the specific language governing permissions
|
||||||
|
# and limitations under the License.
|
||||||
|
#
|
||||||
|
# When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
# If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
#
|
||||||
|
# CDDL HEADER END
|
||||||
|
#
|
||||||
|
# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
# Use is subject to license terms.
|
||||||
|
#
|
||||||
|
|
||||||
|
SUFFIXES = .o .c .c~ .cc .cc~ .y .y~ .l .l~ .s .s~ .sh .sh~ .S .S~ .i .ln \
|
||||||
|
.h .h~ .f .f~ .for .for~ .F .F~ .f90 .f90~ .ftn .ftn~ .mod .mod~ \
|
||||||
|
.sym .def .def~ .p .p~ .r .r~ .cps .cps~ .C .C~ .Y .Y~ .L .L~ \
|
||||||
|
.java .java~ .class
|
||||||
|
|
||||||
|
.SUFFIXES: $(SUFFIXES)
|
||||||
|
|
||||||
|
# OUTPUT_OPTION should be defined to "-o $@" when
|
||||||
|
# the default rules are used for non-local files.
|
||||||
|
OUTPUT_OPTION=
|
||||||
|
|
||||||
|
# C language section.
|
||||||
|
CC=cc
|
||||||
|
CFLAGS=
|
||||||
|
CPPFLAGS=
|
||||||
|
LINT=lint
|
||||||
|
LINTFLAGS=
|
||||||
|
COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -c
|
||||||
|
LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||||
|
LINT.c=$(LINT) $(LINTFLAGS) $(CPPFLAGS)
|
||||||
|
.c:
|
||||||
|
$(LINK.c) -o $@ $< $(LDLIBS)
|
||||||
|
.c~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.c
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $*.c
|
||||||
|
.c.o:
|
||||||
|
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||||
|
.c~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.c
|
||||||
|
$(CC) $(CFLAGS) -c $*.c
|
||||||
|
.c.i:
|
||||||
|
$(CC) $(CFLAGS) $(CPPFLAGS) -P $<
|
||||||
|
.c~.i:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.c
|
||||||
|
$(CC) $(CFLAGS) $(CPPFLAGS) -P $*.c
|
||||||
|
.c.ln:
|
||||||
|
$(LINT.c) $(OUTPUT_OPTION) -c $<
|
||||||
|
.c~.ln:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.c
|
||||||
|
$(LINT.c) $(OUTPUT_OPTION) -c $*.c
|
||||||
|
.c.a:
|
||||||
|
$(COMPILE.c) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.c~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.c
|
||||||
|
$(COMPILE.c) -o $% $*.c
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
|
||||||
|
# C language section. yacc.
|
||||||
|
YACC=yacc
|
||||||
|
YFLAGS=
|
||||||
|
YACC.y=$(YACC) $(YFLAGS)
|
||||||
|
.y:
|
||||||
|
$(YACC.y) $<
|
||||||
|
$(LINK.c) -o $@ y.tab.c $(LDLIBS)
|
||||||
|
$(RM) y.tab.c
|
||||||
|
.y~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.y
|
||||||
|
$(YACC) $(YFLAGS) $*.y
|
||||||
|
$(COMPILE.c) -o $@ y.tab.c
|
||||||
|
$(RM) y.tab.c
|
||||||
|
|
||||||
|
.y.c:
|
||||||
|
$(YACC.y) $<
|
||||||
|
mv y.tab.c $@
|
||||||
|
.y~.c:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.y
|
||||||
|
$(YACC) $(YFLAGS) $*.y
|
||||||
|
mv y.tab.c $@
|
||||||
|
.y.ln:
|
||||||
|
$(YACC.y) $<
|
||||||
|
$(LINT.c) -o $@ -i y.tab.c
|
||||||
|
$(RM) y.tab.c
|
||||||
|
.y~.ln:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.y
|
||||||
|
$(YACC.y) $*.y
|
||||||
|
$(LINT.c) -o $@ -i y.tab.c
|
||||||
|
$(RM) y.tab.c
|
||||||
|
.y.o:
|
||||||
|
$(YACC.y) $<
|
||||||
|
$(COMPILE.c) -o $@ y.tab.c
|
||||||
|
$(RM) y.tab.c
|
||||||
|
.y~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.y
|
||||||
|
$(YACC) $(YFLAGS) $*.y
|
||||||
|
$(CC) $(CFLAGS) -c y.tab.c
|
||||||
|
rm -f y.tab.c
|
||||||
|
mv y.tab.o $@
|
||||||
|
|
||||||
|
# C language section. lex.
|
||||||
|
LEX=lex
|
||||||
|
LFLAGS=
|
||||||
|
LEX.l=$(LEX) $(LFLAGS) -t
|
||||||
|
.l:
|
||||||
|
$(RM) $*.c
|
||||||
|
$(LEX.l) $< > $*.c
|
||||||
|
$(LINK.c) -o $@ $*.c -ll $(LDLIBS)
|
||||||
|
$(RM) $*.c
|
||||||
|
.l~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.l
|
||||||
|
$(LEX) $(LFLAGS) $*.l
|
||||||
|
$(CC) $(CFLAGS) -c lex.yy.c
|
||||||
|
rm -f lex.yy.c
|
||||||
|
mv lex.yy.c $@
|
||||||
|
|
||||||
|
.l.c :
|
||||||
|
$(RM) $@
|
||||||
|
$(LEX.l) $< > $@
|
||||||
|
.l~.c:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.l
|
||||||
|
$(LEX) $(LFLAGS) $*.l
|
||||||
|
mv lex.yy.c $@
|
||||||
|
.l.ln:
|
||||||
|
$(RM) $*.c
|
||||||
|
$(LEX.l) $< > $*.c
|
||||||
|
$(LINT.c) -o $@ -i $*.c
|
||||||
|
$(RM) $*.c
|
||||||
|
.l~.ln:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.l
|
||||||
|
$(RM) $*.c
|
||||||
|
$(LEX.l) $*.l > $*.c
|
||||||
|
$(LINT.c) -o $@ -i $*.c
|
||||||
|
$(RM) $*.c
|
||||||
|
.l.o:
|
||||||
|
$(RM) $*.c
|
||||||
|
$(LEX.l) $< > $*.c
|
||||||
|
$(COMPILE.c) -o $@ $*.c
|
||||||
|
$(RM) $*.c
|
||||||
|
.l~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.l
|
||||||
|
$(LEX) $(LFLAGS) $*.l
|
||||||
|
$(CC) $(CFLAGS) -c lex.yy.c
|
||||||
|
rm -f lex.yy.c
|
||||||
|
mv lex.yy.c $@
|
||||||
|
|
||||||
|
# C++ language section.
|
||||||
|
CCC=CC
|
||||||
|
CCFLAGS=
|
||||||
|
COMPILE.cc=$(CCC) $(CCFLAGS) $(CPPFLAGS) -c
|
||||||
|
LINK.cc=$(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||||
|
COMPILE.C=$(CCC) $(CCFLAGS) $(CPPFLAGS) -c
|
||||||
|
LINK.C=$(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||||
|
.cc:
|
||||||
|
$(LINK.cc) -o $@ $< $(LDLIBS)
|
||||||
|
.cc~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.cc
|
||||||
|
$(LINK.cc) -o $@ $*.cc $(LDLIBS)
|
||||||
|
.cc.o:
|
||||||
|
$(COMPILE.cc) $(OUTPUT_OPTION) $<
|
||||||
|
.cc~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.cc
|
||||||
|
$(COMPILE.cc) $(OUTPUT_OPTION) $*.cc
|
||||||
|
.cc.i:
|
||||||
|
$(CCC) $(CCFLAGS) $(CPPFLAGS) -P $<
|
||||||
|
.cc~.i:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.cc
|
||||||
|
$(CCC) $(CCFLAGS) $(CPPFLAGS) -P $*.cc
|
||||||
|
.cc.a:
|
||||||
|
$(COMPILE.cc) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.cc~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.cc
|
||||||
|
$(COMPILE.cc) -o $% $*.cc
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
|
||||||
|
.C:
|
||||||
|
$(LINK.C) -o $@ $< $(LDLIBS)
|
||||||
|
.C~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.C
|
||||||
|
$(LINK.C) -o $@ $*.C $(LDLIBS)
|
||||||
|
.C.o:
|
||||||
|
$(COMPILE.C) $(OUTPUT_OPTION) $<
|
||||||
|
.C~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.C
|
||||||
|
$(COMPILE.C) $(OUTPUT_OPTION) $*.C
|
||||||
|
.C.i:
|
||||||
|
$(CCC) $(CCFLAGS) $(CPPFLAGS) -P $<
|
||||||
|
.C~.i:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.C
|
||||||
|
$(CCC) $(CCFLAGS) $(CPPFLAGS) -P $*.C
|
||||||
|
.C.a:
|
||||||
|
$(COMPILE.C) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.C~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.C
|
||||||
|
$(COMPILE.C) -o $% $*.C
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
|
||||||
|
# FORTRAN section.
|
||||||
|
FC=f77
|
||||||
|
FFLAGS=
|
||||||
|
COMPILE.f=$(FC) $(FFLAGS) -c
|
||||||
|
LINK.f=$(FC) $(FFLAGS) $(LDFLAGS)
|
||||||
|
COMPILE.F=$(FC) $(FFLAGS) $(CPPFLAGS) -c
|
||||||
|
LINK.F=$(FC) $(FFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||||
|
.f:
|
||||||
|
$(LINK.f) -o $@ $< $(LDLIBS)
|
||||||
|
.f~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.f
|
||||||
|
$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $*.f
|
||||||
|
.f.o:
|
||||||
|
$(COMPILE.f) $(OUTPUT_OPTION) $<
|
||||||
|
.f~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.f
|
||||||
|
$(FC) $(FFLAGS) -c $*.f
|
||||||
|
.f.a:
|
||||||
|
$(COMPILE.f) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.f~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.f
|
||||||
|
$(COMPILE.f) -o $% $*.f
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.for:
|
||||||
|
$(LINK.f) -o $@ $< $(LDLIBS)
|
||||||
|
.for~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.for
|
||||||
|
$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $*.for
|
||||||
|
.for.o:
|
||||||
|
$(COMPILE.f) $(OUTPUT_OPTION) $<
|
||||||
|
.for~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.for
|
||||||
|
$(FC) $(FFLAGS) -c $*.for
|
||||||
|
.for.a:
|
||||||
|
$(COMPILE.f) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.for~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.for
|
||||||
|
$(COMPILE.f) -o $% $*.for
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.F:
|
||||||
|
$(LINK.F) -o $@ $< $(LDLIBS)
|
||||||
|
.F~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.F
|
||||||
|
$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $*.F
|
||||||
|
.F.o:
|
||||||
|
$(COMPILE.F) $(OUTPUT_OPTION) $<
|
||||||
|
.F~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.F
|
||||||
|
$(FC) $(FFLAGS) -c $*.F
|
||||||
|
.F.a:
|
||||||
|
$(COMPILE.F) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.F~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.F
|
||||||
|
$(COMPILE.F) -o $% $*.F
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
|
||||||
|
# FORTRAN section. ratfor.
|
||||||
|
RFLAGS=
|
||||||
|
COMPILE.r=$(FC) $(FFLAGS) $(RFLAGS) -c
|
||||||
|
LINK.r=$(FC) $(FFLAGS) $(RFLAGS) $(LDFLAGS)
|
||||||
|
.r:
|
||||||
|
$(LINK.r) -o $@ $< $(LDLIBS)
|
||||||
|
.r~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.r
|
||||||
|
$(LINK.r) -o $@ $*.r $(LDLIBS)
|
||||||
|
.r.o:
|
||||||
|
$(COMPILE.r) $(OUTPUT_OPTION) $<
|
||||||
|
.r~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.r
|
||||||
|
$(COMPILE.r) $(OUTPUT_OPTION) $*.r
|
||||||
|
.r.a:
|
||||||
|
$(COMPILE.r) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.r~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.r
|
||||||
|
$(COMPILE.r) -o $% $*.r
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
|
||||||
|
# FORTRAN 90 section.
|
||||||
|
F90C=f90
|
||||||
|
F90FLAGS=
|
||||||
|
COMPILE.f90=$(F90C) $(F90FLAGS) -c
|
||||||
|
LINK.f90=$(F90C) $(F90FLAGS) $(LDFLAGS)
|
||||||
|
COMPILE.ftn=$(F90C) $(F90FLAGS) -c
|
||||||
|
LINK.ftn=$(F90C) $(F90FLAGS) $(LDFLAGS)
|
||||||
|
.f90:
|
||||||
|
$(LINK.f90) -o $@ $< $(LDLIBS)
|
||||||
|
.f90~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.f90
|
||||||
|
$(LINK.f90) -o $@ $*.f90 $(LDLIBS)
|
||||||
|
.f90.o:
|
||||||
|
$(COMPILE.f90) $(OUTPUT_OPTION) $<
|
||||||
|
.f90~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.f90
|
||||||
|
$(COMPILE.f90) $(OUTPUT_OPTION) $*.f90
|
||||||
|
.f90.a:
|
||||||
|
$(COMPILE.f90) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.f90~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.f90
|
||||||
|
$(COMPILE.f90) -o $% $*.f90
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.ftn:
|
||||||
|
$(LINK.ftn) -o $@ $< $(LDLIBS)
|
||||||
|
.ftn~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.ftn
|
||||||
|
$(LINK.ftn) -o $@ $*.ftn $(LDLIBS)
|
||||||
|
.ftn.o:
|
||||||
|
$(COMPILE.ftn) $(OUTPUT_OPTION) $<
|
||||||
|
.ftn~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.ftn
|
||||||
|
$(COMPILE.ftn) $(OUTPUT_OPTION) $*.ftn
|
||||||
|
.ftn.a:
|
||||||
|
$(COMPILE.ftn) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.ftn~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.ftn
|
||||||
|
$(COMPILE.ftn) -o $% $*.ftn
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
|
||||||
|
# Modula-2 section.
|
||||||
|
M2C=m2c
|
||||||
|
M2FLAGS=
|
||||||
|
MODFLAGS=
|
||||||
|
DEFFLAGS=
|
||||||
|
COMPILE.def=$(M2C) $(M2FLAGS) $(DEFFLAGS)
|
||||||
|
COMPILE.mod=$(M2C) $(M2FLAGS) $(MODFLAGS)
|
||||||
|
.def.sym:
|
||||||
|
$(COMPILE.def) -o $@ $<
|
||||||
|
.def~.sym:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.def
|
||||||
|
$(COMPILE.def) -o $@ $*.def
|
||||||
|
.mod:
|
||||||
|
$(COMPILE.mod) -o $@ -e $@ $<
|
||||||
|
.mod~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.mod
|
||||||
|
$(COMPILE.mod) -o $@ -e $@ $*.mod
|
||||||
|
.mod.o:
|
||||||
|
$(COMPILE.mod) -o $@ $<
|
||||||
|
.mod~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.mod
|
||||||
|
$(COMPILE.mod) -o $@ $*.mod
|
||||||
|
.mod.a:
|
||||||
|
$(COMPILE.mod) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.mod~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.mod
|
||||||
|
$(COMPILE.mod) -o $% $*.mod
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
|
||||||
|
# Pascal section.
|
||||||
|
PC=pc
|
||||||
|
PFLAGS=
|
||||||
|
COMPILE.p=$(PC) $(PFLAGS) $(CPPFLAGS) -c
|
||||||
|
LINK.p=$(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||||
|
.p:
|
||||||
|
$(LINK.p) -o $@ $< $(LDLIBS)
|
||||||
|
.p~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.p
|
||||||
|
$(LINK.p) -o $@ $*.p $(LDLIBS)
|
||||||
|
.p.o:
|
||||||
|
$(COMPILE.p) $(OUTPUT_OPTION) $<
|
||||||
|
.p~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.p
|
||||||
|
$(COMPILE.p) $(OUTPUT_OPTION) $*.p
|
||||||
|
.p.a:
|
||||||
|
$(COMPILE.p) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.p~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.p
|
||||||
|
$(COMPILE.p) -o $% $*.p
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
|
||||||
|
# Assembly section.
|
||||||
|
AS=as
|
||||||
|
ASFLAGS=
|
||||||
|
COMPILE.s=$(AS) $(ASFLAGS)
|
||||||
|
COMPILE.S=$(CC) $(ASFLAGS) $(CPPFLAGS) -c
|
||||||
|
.s.o:
|
||||||
|
$(COMPILE.s) -o $@ $<
|
||||||
|
.s~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.s
|
||||||
|
$(COMPILE.s) -o $@ $*.s
|
||||||
|
.s.a:
|
||||||
|
$(COMPILE.s) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.s~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.s
|
||||||
|
$(COMPILE.s) -o $% $*.s
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.S.o:
|
||||||
|
$(COMPILE.S) -o $@ $<
|
||||||
|
.S~.o:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.S
|
||||||
|
$(COMPILE.S) -o $@ $*.S
|
||||||
|
.S.a:
|
||||||
|
$(COMPILE.S) -o $% $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
.S~.a:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.S
|
||||||
|
$(COMPILE.S) -o $% $*.S
|
||||||
|
$(AR) $(ARFLAGS) $@ $%
|
||||||
|
$(RM) $%
|
||||||
|
|
||||||
|
# Shell section.
|
||||||
|
.sh:
|
||||||
|
$(RM) $@
|
||||||
|
cat $< > $@
|
||||||
|
chmod +x $@
|
||||||
|
.sh~:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.sh
|
||||||
|
cp $*.sh $@
|
||||||
|
chmod a+x $@
|
||||||
|
|
||||||
|
# NeWS section
|
||||||
|
CPS=cps
|
||||||
|
CPSFLAGS=
|
||||||
|
.cps.h:
|
||||||
|
$(CPS) $(CPSFLAGS) $*.cps
|
||||||
|
.cps~.h:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.cps
|
||||||
|
$(CPS) $(CPSFLAGS) $*.cps
|
||||||
|
|
||||||
|
# JAVA section
|
||||||
|
JAVAC=javac
|
||||||
|
JAVACFLAGS=
|
||||||
|
.java.class:
|
||||||
|
$(JAVAC) $(JAVACFLAGS) $<
|
||||||
|
.java~.class:
|
||||||
|
$(GET) $(GFLAGS) -p $< > $*.java
|
||||||
|
$(JAVAC) $(JAVACFLAGS) $<
|
||||||
|
|
||||||
|
# Miscellaneous section.
|
||||||
|
LD=ld
|
||||||
|
LDFLAGS=
|
||||||
|
LDLIBS=
|
||||||
|
MAKE=make
|
||||||
|
RM=rm -f
|
||||||
|
AR=ar
|
||||||
|
ARFLAGS=rv
|
||||||
|
GET=get
|
||||||
|
GFLAGS=
|
||||||
|
|
||||||
|
markfile.o: markfile
|
||||||
|
echo "static char _sccsid[] = \"`grep @'(#)' markfile`\";" > markfile.c
|
||||||
|
cc -c markfile.c
|
||||||
|
$(RM) markfile.c
|
||||||
|
|
||||||
|
SCCSFLAGS=
|
||||||
|
SCCSGETFLAGS=-s
|
||||||
|
.SCCS_GET:
|
||||||
|
sccs $(SCCSFLAGS) get $(SCCSGETFLAGS) $@ -G$@
|
||||||
|
|
||||||
|
.SCCS_GET_POSIX:
|
||||||
|
sccs $(SCCSFLAGS) get $(SCCSGETFLAGS) $@
|
||||||
|
|
||||||
|
.GET_POSIX:
|
||||||
|
$(GET) $(GFLAGS) s.$@
|
736
bin/misc.cc
Normal file
736
bin/misc.cc
Normal file
|
@ -0,0 +1,736 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* misc.cc
|
||||||
|
*
|
||||||
|
* This file contains various unclassified routines. Some main groups:
|
||||||
|
* getname
|
||||||
|
* Memory allocation
|
||||||
|
* String handling
|
||||||
|
* Property handling
|
||||||
|
* Error message handling
|
||||||
|
* Make internal state dumping
|
||||||
|
* main routine support
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <errno.h>
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <mksh/macro.h> /* SETVAR() */
|
||||||
|
#include <mksh/misc.h> /* enable_interrupt() */
|
||||||
|
#include <stdarg.h> /* va_list, va_start(), va_end() */
|
||||||
|
#include <vroot/report.h> /* SUNPRO_DEPENDENCIES */
|
||||||
|
#include <libintl.h>
|
||||||
|
|
||||||
|
extern void job_adjust_fini();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
static void print_rule(register Name target);
|
||||||
|
static void print_target_n_deps(register Name target);
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
*
|
||||||
|
* getname
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
*
|
||||||
|
* Memory allocation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* free_chain()
|
||||||
|
*
|
||||||
|
* frees a chain of Name_vector's
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* ptr Pointer to the first element in the chain
|
||||||
|
* to be freed.
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
free_chain(Name_vector ptr)
|
||||||
|
{
|
||||||
|
if (ptr != NULL) {
|
||||||
|
if (ptr->next != NULL) {
|
||||||
|
free_chain(ptr->next);
|
||||||
|
}
|
||||||
|
free((char *) ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
*
|
||||||
|
* String manipulation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
*
|
||||||
|
* Nameblock property handling
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
*
|
||||||
|
* Error message handling
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fatal(format, args...)
|
||||||
|
*
|
||||||
|
* Print a message and die
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* format printf type format string
|
||||||
|
* args Arguments to match the format
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* fatal_in_progress Indicates if this is a recursive call
|
||||||
|
* parallel_process_cnt Do we need to wait for anything?
|
||||||
|
* report_pwd Should we report the current path?
|
||||||
|
*/
|
||||||
|
/*VARARGS*/
|
||||||
|
void
|
||||||
|
fatal(const char *message, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, message);
|
||||||
|
(void) fflush(stdout);
|
||||||
|
(void) fprintf(stderr, gettext("%s: Fatal error: "), getprogname());
|
||||||
|
(void) vfprintf(stderr, message, args);
|
||||||
|
(void) fprintf(stderr, "\n");
|
||||||
|
va_end(args);
|
||||||
|
if (report_pwd) {
|
||||||
|
(void) fprintf(stderr,
|
||||||
|
gettext("Current working directory %s\n"),
|
||||||
|
get_current_path());
|
||||||
|
}
|
||||||
|
(void) fflush(stderr);
|
||||||
|
if (fatal_in_progress) {
|
||||||
|
exit_status = 1;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fatal_in_progress = true;
|
||||||
|
/* Let all parallel children finish */
|
||||||
|
if ((dmake_mode_type == parallel_mode) &&
|
||||||
|
(parallel_process_cnt > 0)) {
|
||||||
|
(void) fprintf(stderr,
|
||||||
|
gettext("Waiting for %d %s to finish\n"),
|
||||||
|
parallel_process_cnt,
|
||||||
|
parallel_process_cnt == 1 ?
|
||||||
|
gettext("job") : gettext("jobs"));
|
||||||
|
(void) fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (parallel_process_cnt > 0) {
|
||||||
|
await_parallel(true);
|
||||||
|
finish_children(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
job_adjust_fini();
|
||||||
|
|
||||||
|
exit_status = 1;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* warning(format, args...)
|
||||||
|
*
|
||||||
|
* Print a message and continue.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* format printf type format string
|
||||||
|
* args Arguments to match the format
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* report_pwd Should we report the current path?
|
||||||
|
*/
|
||||||
|
/*VARARGS*/
|
||||||
|
void
|
||||||
|
warning(char * message, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, message);
|
||||||
|
(void) fflush(stdout);
|
||||||
|
(void) fprintf(stderr, gettext("%s: Warning: "), getprogname());
|
||||||
|
(void) vfprintf(stderr, message, args);
|
||||||
|
(void) fprintf(stderr, "\n");
|
||||||
|
va_end(args);
|
||||||
|
if (report_pwd) {
|
||||||
|
(void) fprintf(stderr,
|
||||||
|
gettext("Current working directory %s\n"),
|
||||||
|
get_current_path());
|
||||||
|
}
|
||||||
|
(void) fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* time_to_string(time)
|
||||||
|
*
|
||||||
|
* Take a numeric time value and produce
|
||||||
|
* a proper string representation.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The string representation of the time
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* time The time we need to translate
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
time_to_string(const timestruc_t &time)
|
||||||
|
{
|
||||||
|
struct tm *tm;
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
|
if (time == file_doesnt_exist) {
|
||||||
|
return gettext("File does not exist");
|
||||||
|
}
|
||||||
|
if (time == file_max_time) {
|
||||||
|
return gettext("Younger than any file");
|
||||||
|
}
|
||||||
|
tm = localtime(&time.tv_sec);
|
||||||
|
strftime(buf, sizeof (buf), "%c %Z", tm);
|
||||||
|
buf[127] = (int) nul_char;
|
||||||
|
return strdup(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_current_path()
|
||||||
|
*
|
||||||
|
* Stuff current_path with the current path if it isnt there already.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
get_current_path(void)
|
||||||
|
{
|
||||||
|
char pwd[(MAXPATHLEN * MB_LEN_MAX)];
|
||||||
|
static char *current_path;
|
||||||
|
|
||||||
|
if (current_path == NULL) {
|
||||||
|
getcwd(pwd, sizeof(pwd));
|
||||||
|
if (pwd[0] == (int) nul_char) {
|
||||||
|
pwd[0] = (int) slash_char;
|
||||||
|
pwd[1] = (int) nul_char;
|
||||||
|
}
|
||||||
|
current_path = strdup(pwd);
|
||||||
|
}
|
||||||
|
return current_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
*
|
||||||
|
* Make internal state dumping
|
||||||
|
*
|
||||||
|
* This is a set of routines for dumping the internal make state
|
||||||
|
* Used for the -p option
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dump_make_state()
|
||||||
|
*
|
||||||
|
* Dump make's internal state to stdout
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* svr4 Was ".SVR4" seen in makefile?
|
||||||
|
* svr4_name The Name ".SVR4", printed
|
||||||
|
* posix Was ".POSIX" seen in makefile?
|
||||||
|
* posix_name The Name ".POSIX", printed
|
||||||
|
* default_rule Points to the .DEFAULT rule
|
||||||
|
* default_rule_name The Name ".DEFAULT", printed
|
||||||
|
* default_target_to_build The first target to print
|
||||||
|
* dot_keep_state The Name ".KEEP_STATE", printed
|
||||||
|
* dot_keep_state_file The Name ".KEEP_STATE_FILE", printed
|
||||||
|
* hashtab The make hash table for Name blocks
|
||||||
|
* ignore_errors Was ".IGNORE" seen in makefile?
|
||||||
|
* ignore_name The Name ".IGNORE", printed
|
||||||
|
* keep_state Was ".KEEP_STATE" seen in makefile?
|
||||||
|
* percent_list The list of % rules
|
||||||
|
* precious The Name ".PRECIOUS", printed
|
||||||
|
* sccs_get_name The Name ".SCCS_GET", printed
|
||||||
|
* sccs_get_posix_name The Name ".SCCS_GET_POSIX", printed
|
||||||
|
* get_name The Name ".GET", printed
|
||||||
|
* get_posix_name The Name ".GET_POSIX", printed
|
||||||
|
* sccs_get_rule Points to the ".SCCS_GET" rule
|
||||||
|
* silent Was ".SILENT" seen in makefile?
|
||||||
|
* silent_name The Name ".SILENT", printed
|
||||||
|
* suffixes The suffix list from ".SUFFIXES"
|
||||||
|
* suffixes_name The Name ".SUFFIX", printed
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
dump_make_state(void)
|
||||||
|
{
|
||||||
|
Name_set::iterator p, e;
|
||||||
|
register Property prop;
|
||||||
|
register Dependency dep;
|
||||||
|
register Cmd_line rule;
|
||||||
|
Percent percent, percent_depe;
|
||||||
|
|
||||||
|
/* Default target */
|
||||||
|
if (default_target_to_build != NULL) {
|
||||||
|
print_rule(default_target_to_build);
|
||||||
|
}
|
||||||
|
(void) printf("\n");
|
||||||
|
|
||||||
|
/* .POSIX */
|
||||||
|
if (posix) {
|
||||||
|
(void) printf("%s:\n", posix_name->string_mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .DEFAULT */
|
||||||
|
if (default_rule != NULL) {
|
||||||
|
(void) printf("%s:\n", default_rule_name->string_mb);
|
||||||
|
for (rule = default_rule; rule != NULL; rule = rule->next) {
|
||||||
|
(void) printf("\t%s\n", rule->command_line->string_mb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .IGNORE */
|
||||||
|
if (ignore_errors) {
|
||||||
|
(void) printf("%s:\n", ignore_name->string_mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .KEEP_STATE: */
|
||||||
|
if (keep_state) {
|
||||||
|
(void) printf("%s:\n\n", dot_keep_state->string_mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .PRECIOUS */
|
||||||
|
(void) printf("%s:", precious->string_mb);
|
||||||
|
for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
|
||||||
|
if ((p->stat.is_precious) || (all_precious)) {
|
||||||
|
(void) printf(" %s", p->string_mb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) printf("\n");
|
||||||
|
|
||||||
|
/* .SCCS_GET */
|
||||||
|
if (sccs_get_rule != NULL) {
|
||||||
|
(void) printf("%s:\n", sccs_get_name->string_mb);
|
||||||
|
for (rule = sccs_get_rule; rule != NULL; rule = rule->next) {
|
||||||
|
(void) printf("\t%s\n", rule->command_line->string_mb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .SILENT */
|
||||||
|
if (silent) {
|
||||||
|
(void) printf("%s:\n", silent_name->string_mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .SUFFIXES: */
|
||||||
|
(void) printf("%s:", suffixes_name->string_mb);
|
||||||
|
for (dep = suffixes; dep != NULL; dep = dep->next) {
|
||||||
|
(void) printf(" %s", dep->name->string_mb);
|
||||||
|
build_suffix_list(dep->name);
|
||||||
|
}
|
||||||
|
(void) printf("\n\n");
|
||||||
|
|
||||||
|
/* % rules */
|
||||||
|
for (percent = percent_list;
|
||||||
|
percent != NULL;
|
||||||
|
percent = percent->next) {
|
||||||
|
(void) printf("%s:",
|
||||||
|
percent->name->string_mb);
|
||||||
|
|
||||||
|
for (percent_depe = percent->dependencies;
|
||||||
|
percent_depe != NULL;
|
||||||
|
percent_depe = percent_depe->next) {
|
||||||
|
(void) printf(" %s", percent_depe->name->string_mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) printf("\n");
|
||||||
|
|
||||||
|
for (rule = percent->command_template;
|
||||||
|
rule != NULL;
|
||||||
|
rule = rule->next) {
|
||||||
|
(void) printf("\t%s\n", rule->command_line->string_mb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Suffix rules */
|
||||||
|
for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
|
||||||
|
Wstring wcb(p);
|
||||||
|
if (wcb.get_string()[0] == (int) period_char) {
|
||||||
|
print_rule(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Macro assignments */
|
||||||
|
for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
|
||||||
|
if (((prop = get_prop(p->prop, macro_prop)) != NULL) &&
|
||||||
|
(prop->body.macro.value != NULL)) {
|
||||||
|
(void) printf("%s", p->string_mb);
|
||||||
|
print_value(prop->body.macro.value,
|
||||||
|
(Daemon) prop->body.macro.daemon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) printf("\n");
|
||||||
|
|
||||||
|
/* Conditional macro assignments */
|
||||||
|
for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
|
||||||
|
for (prop = get_prop(p->prop, conditional_prop);
|
||||||
|
prop != NULL;
|
||||||
|
prop = get_prop(prop->next, conditional_prop)) {
|
||||||
|
(void) printf("%s := %s",
|
||||||
|
p->string_mb,
|
||||||
|
prop->body.conditional.name->
|
||||||
|
string_mb);
|
||||||
|
if (prop->body.conditional.append) {
|
||||||
|
printf(" +");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
print_value(prop->body.conditional.value,
|
||||||
|
no_daemon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) printf("\n");
|
||||||
|
|
||||||
|
/* All other dependencies */
|
||||||
|
for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
|
||||||
|
if (p->colons != no_colon) {
|
||||||
|
print_rule(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print_rule(target)
|
||||||
|
*
|
||||||
|
* Print the rule for one target
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target Target we print rule for
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_rule(register Name target)
|
||||||
|
{
|
||||||
|
register Cmd_line rule;
|
||||||
|
register Property line;
|
||||||
|
register Dependency dependency;
|
||||||
|
|
||||||
|
if (target->dependency_printed ||
|
||||||
|
((line = get_prop(target->prop, line_prop)) == NULL) ||
|
||||||
|
((line->body.line.command_template == NULL) &&
|
||||||
|
(line->body.line.dependencies == NULL))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
target->dependency_printed = true;
|
||||||
|
|
||||||
|
(void) printf("%s:", target->string_mb);
|
||||||
|
|
||||||
|
for (dependency = line->body.line.dependencies;
|
||||||
|
dependency != NULL;
|
||||||
|
dependency = dependency->next) {
|
||||||
|
(void) printf(" %s", dependency->name->string_mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) printf("\n");
|
||||||
|
|
||||||
|
for (rule = line->body.line.command_template;
|
||||||
|
rule != NULL;
|
||||||
|
rule = rule->next) {
|
||||||
|
(void) printf("\t%s\n", rule->command_line->string_mb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dump_target_list(void)
|
||||||
|
{
|
||||||
|
Name_set::iterator p, e;
|
||||||
|
Wstring str;
|
||||||
|
|
||||||
|
for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
|
||||||
|
str.init(p);
|
||||||
|
wchar_t * wcb = str.get_string();
|
||||||
|
if ((p->colons != no_colon) &&
|
||||||
|
((wcb[0] != (int) period_char) ||
|
||||||
|
((wcb[0] == (int) period_char) &&
|
||||||
|
(wcschr(wcb, (int) slash_char))))) {
|
||||||
|
print_target_n_deps(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_target_n_deps(register Name target)
|
||||||
|
{
|
||||||
|
register Cmd_line rule;
|
||||||
|
register Property line;
|
||||||
|
register Dependency dependency;
|
||||||
|
|
||||||
|
if (target->dependency_printed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
target->dependency_printed = true;
|
||||||
|
|
||||||
|
(void) printf("%s\n", target->string_mb);
|
||||||
|
|
||||||
|
if ((line = get_prop(target->prop, line_prop)) == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (dependency = line->body.line.dependencies;
|
||||||
|
dependency != NULL;
|
||||||
|
dependency = dependency->next) {
|
||||||
|
if (!dependency->automatic) {
|
||||||
|
print_target_n_deps(dependency->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
*
|
||||||
|
* main() support
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* load_cached_names()
|
||||||
|
*
|
||||||
|
* Load the vector of cached names
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* Many many pointers to Name blocks.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
load_cached_names(void)
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
Name dollar;
|
||||||
|
|
||||||
|
/* Load the cached_names struct */
|
||||||
|
MBSTOWCS(wcs_buffer, ".BUILT_LAST_MAKE_RUN");
|
||||||
|
built_last_make_run = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "@");
|
||||||
|
c_at = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, " *conditionals* ");
|
||||||
|
conditionals = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
/*
|
||||||
|
* A version of make was released with NSE 1.0 that used
|
||||||
|
* VERSION-1.1 but this version is identical to VERSION-1.0.
|
||||||
|
* The version mismatch code makes a special case for this
|
||||||
|
* situation. If the version number is changed from 1.0
|
||||||
|
* it should go to 1.2.
|
||||||
|
*/
|
||||||
|
MBSTOWCS(wcs_buffer, "VERSION-1.0");
|
||||||
|
current_make_version = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".SVR4");
|
||||||
|
svr4_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".POSIX");
|
||||||
|
posix_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".DEFAULT");
|
||||||
|
default_rule_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "$");
|
||||||
|
dollar = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".DONE");
|
||||||
|
done = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".");
|
||||||
|
dot = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".KEEP_STATE");
|
||||||
|
dot_keep_state = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".KEEP_STATE_FILE");
|
||||||
|
dot_keep_state_file = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "");
|
||||||
|
empty_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, " FORCE");
|
||||||
|
force = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "HOST_ARCH");
|
||||||
|
host_arch = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "HOST_MACH");
|
||||||
|
host_mach = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".IGNORE");
|
||||||
|
ignore_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".INIT");
|
||||||
|
init = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".LOCAL");
|
||||||
|
localhost_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".make.state");
|
||||||
|
make_state = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "MAKEFLAGS");
|
||||||
|
makeflags = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".MAKE_VERSION");
|
||||||
|
make_version = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".NO_PARALLEL");
|
||||||
|
no_parallel_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".NOT_AUTO");
|
||||||
|
not_auto = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".PARALLEL");
|
||||||
|
parallel_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "PATH");
|
||||||
|
path_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "+");
|
||||||
|
plus = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".PRECIOUS");
|
||||||
|
precious = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "?");
|
||||||
|
query = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "^");
|
||||||
|
hat = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".RECURSIVE");
|
||||||
|
recursive_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".SCCS_GET");
|
||||||
|
sccs_get_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".SCCS_GET_POSIX");
|
||||||
|
sccs_get_posix_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".GET");
|
||||||
|
get_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".GET_POSIX");
|
||||||
|
get_posix_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "SHELL");
|
||||||
|
shell_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".SILENT");
|
||||||
|
silent_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".SUFFIXES");
|
||||||
|
suffixes_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, SUNPRO_DEPENDENCIES);
|
||||||
|
sunpro_dependencies = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "TARGET_ARCH");
|
||||||
|
target_arch = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "TARGET_MACH");
|
||||||
|
target_mach = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "VIRTUAL_ROOT");
|
||||||
|
virtual_root = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, "VPATH");
|
||||||
|
vpath_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, ".WAIT");
|
||||||
|
wait_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
|
||||||
|
wait_name->state = build_ok;
|
||||||
|
|
||||||
|
/* Mark special targets so that the reader treats them properly */
|
||||||
|
svr4_name->special_reader = svr4_special;
|
||||||
|
posix_name->special_reader = posix_special;
|
||||||
|
built_last_make_run->special_reader = built_last_make_run_special;
|
||||||
|
default_rule_name->special_reader = default_special;
|
||||||
|
dot_keep_state->special_reader = keep_state_special;
|
||||||
|
dot_keep_state_file->special_reader = keep_state_file_special;
|
||||||
|
ignore_name->special_reader = ignore_special;
|
||||||
|
make_version->special_reader = make_version_special;
|
||||||
|
no_parallel_name->special_reader = no_parallel_special;
|
||||||
|
parallel_name->special_reader = parallel_special;
|
||||||
|
localhost_name->special_reader = localhost_special;
|
||||||
|
precious->special_reader = precious_special;
|
||||||
|
sccs_get_name->special_reader = sccs_get_special;
|
||||||
|
sccs_get_posix_name->special_reader = sccs_get_posix_special;
|
||||||
|
get_name->special_reader = get_special;
|
||||||
|
get_posix_name->special_reader = get_posix_special;
|
||||||
|
silent_name->special_reader = silent_special;
|
||||||
|
suffixes_name->special_reader = suffixes_special;
|
||||||
|
|
||||||
|
/* The value of $$ is $ */
|
||||||
|
(void) SETVAR(dollar, dollar, false);
|
||||||
|
dollar->dollar = false;
|
||||||
|
|
||||||
|
/* Set the value of $(SHELL) */
|
||||||
|
if (posix) {
|
||||||
|
MBSTOWCS(wcs_buffer, "/usr/xpg4/bin/sh");
|
||||||
|
} else {
|
||||||
|
MBSTOWCS(wcs_buffer, "/bin/sh");
|
||||||
|
}
|
||||||
|
(void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use " FORCE" to simulate a FRC dependency for :: type
|
||||||
|
* targets with no dependencies.
|
||||||
|
*/
|
||||||
|
(void) append_prop(force, line_prop);
|
||||||
|
force->stat.time = file_max_time;
|
||||||
|
|
||||||
|
/* Make sure VPATH is defined before current dir is read */
|
||||||
|
if ((cp = getenv(vpath_name->string_mb)) != NULL) {
|
||||||
|
MBSTOWCS(wcs_buffer, cp);
|
||||||
|
(void) SETVAR(vpath_name,
|
||||||
|
GETNAME(wcs_buffer, FIND_LENGTH),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there is NO PATH variable. If not we construct one. */
|
||||||
|
if (getenv(path_name->string_mb) == NULL) {
|
||||||
|
vroot_path = NULL;
|
||||||
|
add_dir_to_path(".", &vroot_path, -1);
|
||||||
|
add_dir_to_path("/bin", &vroot_path, -1);
|
||||||
|
add_dir_to_path("/usr/bin", &vroot_path, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* iterate on list of conditional macros in np, and place them in
|
||||||
|
* a String_rec starting with, and separated by the '$' character.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
cond_macros_into_string(Name np, String_rec *buffer)
|
||||||
|
{
|
||||||
|
Macro_list macro_list;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put the version number at the start of the string
|
||||||
|
*/
|
||||||
|
MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION);
|
||||||
|
append_string(wcs_buffer, buffer, FIND_LENGTH);
|
||||||
|
/*
|
||||||
|
* Add the rest of the conditional macros to the buffer
|
||||||
|
*/
|
||||||
|
if (np->depends_on_conditional){
|
||||||
|
for (macro_list = np->conditional_macro_list;
|
||||||
|
macro_list != NULL; macro_list = macro_list->next){
|
||||||
|
append_string(macro_list->macro_name, buffer,
|
||||||
|
FIND_LENGTH);
|
||||||
|
append_char((int) equal_char, buffer);
|
||||||
|
append_string(macro_list->value, buffer, FIND_LENGTH);
|
||||||
|
append_char((int) dollar_char, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
365
bin/nse_printdep.cc
Normal file
365
bin/nse_printdep.cc
Normal file
|
@ -0,0 +1,365 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <mksh/misc.h> /* get_prop() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
void print_dependencies(register Name target, register Property line);
|
||||||
|
static void print_deps(register Name target, register Property line);
|
||||||
|
static void print_more_deps(Name target, Name name);
|
||||||
|
static void print_filename(Name name);
|
||||||
|
static Boolean should_print_dep(Property line);
|
||||||
|
static void print_forest(Name target);
|
||||||
|
static void print_deplist(Dependency head);
|
||||||
|
void print_value(register Name value, Daemon daemon);
|
||||||
|
static void print_rule(register Name target);
|
||||||
|
static void print_rec_info(Name target);
|
||||||
|
static Boolean is_out_of_date(Property line);
|
||||||
|
extern void depvar_print_results (void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print_dependencies(target, line)
|
||||||
|
*
|
||||||
|
* Print all the dependencies of a target. First print all the Makefiles.
|
||||||
|
* Then print all the dependencies. Finally, print all the .INIT
|
||||||
|
* dependencies.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target The target we print dependencies for
|
||||||
|
* line We get the dependency list from here
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* done The Name ".DONE"
|
||||||
|
* init The Name ".INIT"
|
||||||
|
* makefiles_used List of all makefiles read
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
print_dependencies(register Name target, register Property line)
|
||||||
|
{
|
||||||
|
Dependency dp;
|
||||||
|
static Boolean makefiles_printed = false;
|
||||||
|
|
||||||
|
if (target_variants) {
|
||||||
|
depvar_print_results();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!makefiles_printed) {
|
||||||
|
/*
|
||||||
|
* Search the makefile list for the primary makefile,
|
||||||
|
* then print it and its inclusions. After that go back
|
||||||
|
* and print the default.mk file and its inclusions.
|
||||||
|
*/
|
||||||
|
for (dp = makefiles_used; dp != NULL; dp = dp->next) {
|
||||||
|
if (dp->name == primary_makefile) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dp) {
|
||||||
|
print_deplist(dp);
|
||||||
|
for (dp = makefiles_used; dp != NULL; dp = dp->next) {
|
||||||
|
if (dp->name == primary_makefile) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(void)printf(" %s", dp->name->string_mb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) printf("\n");
|
||||||
|
makefiles_printed = true;
|
||||||
|
}
|
||||||
|
print_deps(target, line);
|
||||||
|
/*
|
||||||
|
print_more_deps(target, init);
|
||||||
|
print_more_deps(target, done);
|
||||||
|
*/
|
||||||
|
if (target_variants) {
|
||||||
|
print_forest(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print_more_deps(target, name)
|
||||||
|
*
|
||||||
|
* Print some special dependencies.
|
||||||
|
* These are the dependencies for the .INIT and .DONE targets.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target Target built during make run
|
||||||
|
* name Special target to print dependencies for
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_more_deps(Name target, Name name)
|
||||||
|
{
|
||||||
|
Property line;
|
||||||
|
register Dependency dependencies;
|
||||||
|
|
||||||
|
line = get_prop(name->prop, line_prop);
|
||||||
|
if (line != NULL && line->body.line.dependencies != NULL) {
|
||||||
|
(void) printf("%s:\t", target->string_mb);
|
||||||
|
print_deplist(line->body.line.dependencies);
|
||||||
|
(void) printf("\n");
|
||||||
|
for (dependencies= line->body.line.dependencies;
|
||||||
|
dependencies != NULL;
|
||||||
|
dependencies= dependencies->next) {
|
||||||
|
print_deps(dependencies->name,
|
||||||
|
get_prop(dependencies->name->prop, line_prop));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print_deps(target, line, go_recursive)
|
||||||
|
*
|
||||||
|
* Print a regular dependency list. Append to this information which
|
||||||
|
* indicates whether or not the target is recursive.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target target to print dependencies for
|
||||||
|
* line We get the dependency list from here
|
||||||
|
* go_recursive Should we show all dependencies recursively?
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* recursive_name The Name ".RECURSIVE", printed
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_deps(register Name target, register Property line)
|
||||||
|
{
|
||||||
|
register Dependency dep;
|
||||||
|
|
||||||
|
if ((target->dependency_printed) ||
|
||||||
|
(target == force)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
target->dependency_printed = true;
|
||||||
|
|
||||||
|
/* only print entries that are actually derived and are not leaf
|
||||||
|
* files and are not the result of sccs get.
|
||||||
|
*/
|
||||||
|
if (should_print_dep(line)) {
|
||||||
|
if ((report_dependencies_level == 2) ||
|
||||||
|
(report_dependencies_level == 4)) {
|
||||||
|
if (is_out_of_date(line)) {
|
||||||
|
(void) printf("1 ");
|
||||||
|
} else {
|
||||||
|
(void) printf("0 ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_filename(target);
|
||||||
|
(void) printf(":\t");
|
||||||
|
print_deplist(line->body.line.dependencies);
|
||||||
|
print_rec_info(target);
|
||||||
|
(void) printf("\n");
|
||||||
|
for (dep = line->body.line.dependencies;
|
||||||
|
dep != NULL;
|
||||||
|
dep = dep->next) {
|
||||||
|
print_deps(dep->name,
|
||||||
|
get_prop(dep->name->prop, line_prop));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Boolean
|
||||||
|
is_out_of_date(Property line)
|
||||||
|
{
|
||||||
|
Dependency dep;
|
||||||
|
Property line2;
|
||||||
|
|
||||||
|
if (line == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (line->body.line.is_out_of_date) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (dep = line->body.line.dependencies;
|
||||||
|
dep != NULL;
|
||||||
|
dep = dep->next) {
|
||||||
|
line2 = get_prop(dep->name->prop, line_prop);
|
||||||
|
if (is_out_of_date(line2)) {
|
||||||
|
line->body.line.is_out_of_date = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a dependency print it and all its siblings.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_deplist(Dependency head)
|
||||||
|
{
|
||||||
|
Dependency dp;
|
||||||
|
|
||||||
|
for (dp = head; dp != NULL; dp = dp->next) {
|
||||||
|
if ((report_dependencies_level != 2) ||
|
||||||
|
((!dp->automatic) ||
|
||||||
|
(dp->name->is_double_colon))) {
|
||||||
|
if (dp->name != force) {
|
||||||
|
putwchar(' ');
|
||||||
|
print_filename(dp->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print the name of a file for the -P option.
|
||||||
|
* If the file is a directory put on a trailing slash.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_filename(Name name)
|
||||||
|
{
|
||||||
|
(void) printf("%s", name->string_mb);
|
||||||
|
/*
|
||||||
|
if (name->stat.is_dir) {
|
||||||
|
putwchar('/');
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* should_print_dep(line)
|
||||||
|
*
|
||||||
|
* Test if we should print the dependencies of this target.
|
||||||
|
* The line must exist and either have children dependencies
|
||||||
|
* or have a command that is not an SCCS command.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* true if the dependencies should be printed
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* line We get the dependency list from here
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
static Boolean
|
||||||
|
should_print_dep(Property line)
|
||||||
|
{
|
||||||
|
if (line == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (line->body.line.dependencies != NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (line->body.line.sccs_command) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print out the root nodes of all the dependency trees
|
||||||
|
* in this makefile.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_forest(Name target)
|
||||||
|
{
|
||||||
|
Name_set::iterator np, e;
|
||||||
|
Property line;
|
||||||
|
|
||||||
|
for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) {
|
||||||
|
if (np->is_target && !np->has_parent && np != target) {
|
||||||
|
(void) doname_check(np, true, false, false);
|
||||||
|
line = get_prop(np->prop, line_prop);
|
||||||
|
printf("-\n");
|
||||||
|
print_deps(np, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a set of routines for dumping the internal make state
|
||||||
|
* Used for the -p option
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
print_value(register Name value, Daemon daemon)
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Chain cp;
|
||||||
|
|
||||||
|
if (value == NULL)
|
||||||
|
(void)printf("=\n");
|
||||||
|
else
|
||||||
|
switch (daemon) {
|
||||||
|
case no_daemon:
|
||||||
|
(void)printf("= %s\n", value->string_mb);
|
||||||
|
break;
|
||||||
|
case chain_daemon:
|
||||||
|
for (cp= (Chain) value; cp != NULL; cp= cp->next)
|
||||||
|
(void)printf(cp->next == NULL ? "%s" : "%s ",
|
||||||
|
cp->name->string_mb);
|
||||||
|
(void)printf("\n");
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_rule(register Name target)
|
||||||
|
{
|
||||||
|
register Cmd_line rule;
|
||||||
|
register Property line;
|
||||||
|
|
||||||
|
if (((line= get_prop(target->prop, line_prop)) == NULL) ||
|
||||||
|
((line->body.line.command_template == NULL) &&
|
||||||
|
(line->body.line.dependencies == NULL)))
|
||||||
|
return;
|
||||||
|
print_dependencies(target, line);
|
||||||
|
for (rule= line->body.line.command_template; rule != NULL; rule= rule->next)
|
||||||
|
(void)printf("\t%s\n", rule->command_line->string_mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If target is recursive, print the following to standard out:
|
||||||
|
* .RECURSIVE subdir targ Makefile
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_rec_info(Name target)
|
||||||
|
{
|
||||||
|
Recursive_make rp;
|
||||||
|
wchar_t *colon;
|
||||||
|
|
||||||
|
report_recursive_init();
|
||||||
|
|
||||||
|
rp = find_recursive_target(target);
|
||||||
|
|
||||||
|
if (rp) {
|
||||||
|
/*
|
||||||
|
* if found, print starting with the space after the ':'
|
||||||
|
*/
|
||||||
|
colon = (wchar_t *) wcschr(rp->oldline, (int) colon_char);
|
||||||
|
(void) printf("%s", colon + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1892
bin/parallel.cc
Normal file
1892
bin/parallel.cc
Normal file
File diff suppressed because it is too large
Load diff
420
bin/pmake.cc
Normal file
420
bin/pmake.cc
Normal file
|
@ -0,0 +1,420 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <mksh/misc.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <rpc/rpc.h> /* host2netname(), netname2host() */
|
||||||
|
#include <libintl.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
static int get_max(wchar_t **ms_address, wchar_t *hostname);
|
||||||
|
static Boolean pskip_comment(wchar_t **cp_address);
|
||||||
|
static void pskip_till_next_word(wchar_t **cp);
|
||||||
|
static Boolean pskip_white_space(wchar_t **cp_address);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* read_make_machines(Name make_machines_name)
|
||||||
|
*
|
||||||
|
* For backwards compatibility w/ PMake 1.x, when DMake 2.x is
|
||||||
|
* being run in parallel mode, DMake should parse the PMake startup
|
||||||
|
* file $(HOME)/.make.machines to get the PMake max jobs.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* int of PMake max jobs
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* make_machines_name Name of .make.machines file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
read_make_machines(Name make_machines_name)
|
||||||
|
{
|
||||||
|
wchar_t c;
|
||||||
|
Boolean default_make_machines;
|
||||||
|
struct hostent *hp;
|
||||||
|
wchar_t local_host[MAX_HOSTNAMELEN + 1];
|
||||||
|
char local_host_mb[MAX_HOSTNAMELEN + 1] = "";
|
||||||
|
int local_host_wslen;
|
||||||
|
wchar_t full_host[MAXNETNAMELEN + 1];
|
||||||
|
int full_host_wslen = 0;
|
||||||
|
char *homedir;
|
||||||
|
Name MAKE_MACHINES;
|
||||||
|
struct stat make_machines_buf;
|
||||||
|
FILE *make_machines_file;
|
||||||
|
wchar_t *make_machines_list = NULL;
|
||||||
|
char *make_machines_list_mb = NULL;
|
||||||
|
wchar_t make_machines_path[MAXPATHLEN];
|
||||||
|
char mb_make_machines_path[MAXPATHLEN];
|
||||||
|
wchar_t *mp;
|
||||||
|
wchar_t *ms;
|
||||||
|
int pmake_max_jobs = 0;
|
||||||
|
struct utsname uts_info;
|
||||||
|
|
||||||
|
|
||||||
|
MBSTOWCS(wcs_buffer, "MAKE_MACHINES");
|
||||||
|
MAKE_MACHINES = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
/* Did the user specify a .make.machines file on the command line? */
|
||||||
|
default_make_machines = false;
|
||||||
|
if (make_machines_name == NULL) {
|
||||||
|
/* Try reading the default .make.machines file, in $(HOME). */
|
||||||
|
homedir = getenv("HOME");
|
||||||
|
if ((homedir != NULL) && (strlen(homedir) < (sizeof(mb_make_machines_path) - 16))) {
|
||||||
|
sprintf(mb_make_machines_path,
|
||||||
|
"%s/.make.machines", homedir);
|
||||||
|
MBSTOWCS(make_machines_path, mb_make_machines_path);
|
||||||
|
make_machines_name = GETNAME(make_machines_path, FIND_LENGTH);
|
||||||
|
default_make_machines = true;
|
||||||
|
}
|
||||||
|
if (make_machines_name == NULL) {
|
||||||
|
/*
|
||||||
|
* No $(HOME)/.make.machines file.
|
||||||
|
* Return 0 for PMake max jobs.
|
||||||
|
*/
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
make_machines_list_mb = getenv(MAKE_MACHINES->string_mb);
|
||||||
|
*/
|
||||||
|
/* Open the .make.machines file. */
|
||||||
|
if ((make_machines_file = fopen(make_machines_name->string_mb, "r")) == NULL) {
|
||||||
|
if (!default_make_machines) {
|
||||||
|
/* Error opening .make.machines file. */
|
||||||
|
fatal(gettext("Open of %s failed: %s"),
|
||||||
|
make_machines_name->string_mb,
|
||||||
|
errmsg(errno));
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* No $(HOME)/.make.machines file.
|
||||||
|
* Return 0 for PMake max jobs.
|
||||||
|
*/
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
/* Stat the .make.machines file to get the size of the file. */
|
||||||
|
} else if (fstat(fileno(make_machines_file), &make_machines_buf) < 0) {
|
||||||
|
/* Error stat'ing .make.machines file. */
|
||||||
|
fatal(gettext("Stat of %s failed: %s"),
|
||||||
|
make_machines_name->string_mb,
|
||||||
|
errmsg(errno));
|
||||||
|
} else {
|
||||||
|
/* Allocate memory for "MAKE_MACHINES=<contents of .m.m>" */
|
||||||
|
make_machines_list_mb =
|
||||||
|
(char *) getmem((int) (strlen(MAKE_MACHINES->string_mb) +
|
||||||
|
2 +
|
||||||
|
make_machines_buf.st_size));
|
||||||
|
sprintf(make_machines_list_mb,
|
||||||
|
"%s=",
|
||||||
|
MAKE_MACHINES->string_mb);
|
||||||
|
/* Read in the .make.machines file. */
|
||||||
|
if (fread(make_machines_list_mb + strlen(MAKE_MACHINES->string_mb) + 1,
|
||||||
|
sizeof(char),
|
||||||
|
(int) make_machines_buf.st_size,
|
||||||
|
make_machines_file) != make_machines_buf.st_size) {
|
||||||
|
/*
|
||||||
|
* Error reading .make.machines file.
|
||||||
|
* Return 0 for PMake max jobs.
|
||||||
|
*/
|
||||||
|
warning(gettext("Unable to read %s"),
|
||||||
|
make_machines_name->string_mb);
|
||||||
|
(void) fclose(make_machines_file);
|
||||||
|
retmem_mb((caddr_t) make_machines_list_mb);
|
||||||
|
return(0);
|
||||||
|
} else {
|
||||||
|
(void) fclose(make_machines_file);
|
||||||
|
/* putenv "MAKE_MACHINES=<contents of .m.m>" */
|
||||||
|
*(make_machines_list_mb +
|
||||||
|
strlen(MAKE_MACHINES->string_mb) +
|
||||||
|
1 +
|
||||||
|
make_machines_buf.st_size) = (int) nul_char;
|
||||||
|
if (putenv(make_machines_list_mb) != 0) {
|
||||||
|
warning(gettext("Couldn't put contents of %s in environment"),
|
||||||
|
make_machines_name->string_mb);
|
||||||
|
} else {
|
||||||
|
make_machines_list_mb += strlen(MAKE_MACHINES->string_mb) + 1;
|
||||||
|
make_machines_list = ALLOC_WC(strlen(make_machines_list_mb) + 1);
|
||||||
|
(void) mbstowcs(make_machines_list,
|
||||||
|
make_machines_list_mb,
|
||||||
|
(strlen(make_machines_list_mb) + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uname(&uts_info);
|
||||||
|
strcpy(local_host_mb, &uts_info.nodename[0]);
|
||||||
|
MBSTOWCS(local_host, local_host_mb);
|
||||||
|
local_host_wslen = wcslen(local_host);
|
||||||
|
|
||||||
|
// There is no getdomainname() function on Solaris.
|
||||||
|
// And netname2host() function does not work on Linux.
|
||||||
|
// So we have to use different APIs.
|
||||||
|
if (host2netname(mbs_buffer, NULL, NULL) &&
|
||||||
|
netname2host(mbs_buffer, mbs_buffer2, MAXNETNAMELEN+1)) {
|
||||||
|
MBSTOWCS(full_host, mbs_buffer2);
|
||||||
|
full_host_wslen = wcslen(full_host);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ms = make_machines_list;
|
||||||
|
(ms) && (*ms );
|
||||||
|
) {
|
||||||
|
/*
|
||||||
|
* Skip white space and comments till you reach
|
||||||
|
* a machine name.
|
||||||
|
*/
|
||||||
|
pskip_till_next_word(&ms);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we haven't reached the end of file, process the
|
||||||
|
* machine name.
|
||||||
|
*/
|
||||||
|
if (*ms) {
|
||||||
|
/*
|
||||||
|
* If invalid machine name decrement counter
|
||||||
|
* and skip line.
|
||||||
|
*/
|
||||||
|
mp = ms;
|
||||||
|
SKIPWORD(ms);
|
||||||
|
c = *ms;
|
||||||
|
*ms++ = '\0'; /* Append null to machine name. */
|
||||||
|
/*
|
||||||
|
* If this was the beginning of a comment
|
||||||
|
* (we overwrote a # sign) and it's not
|
||||||
|
* end of line yet, shift the # sign.
|
||||||
|
*/
|
||||||
|
if ((c == '#') && (*ms != '\n') && (*ms)) {
|
||||||
|
*ms = '#';
|
||||||
|
}
|
||||||
|
WCSTOMBS(mbs_buffer, mp);
|
||||||
|
/*
|
||||||
|
* Print "Ignoring unknown host" if:
|
||||||
|
* 1) hostname is longer than MAX_HOSTNAMELEN, or
|
||||||
|
* 2) hostname is unknown
|
||||||
|
*/
|
||||||
|
if ((wcslen(mp) > MAX_HOSTNAMELEN) ||
|
||||||
|
((hp = gethostbyname(mbs_buffer)) == NULL)) {
|
||||||
|
warning(gettext("Ignoring unknown host %s"),
|
||||||
|
mbs_buffer);
|
||||||
|
SKIPTOEND(ms);
|
||||||
|
/* Increment ptr if not end of file. */
|
||||||
|
if (*ms) {
|
||||||
|
ms++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Compare current hostname with local_host. */
|
||||||
|
if (wcslen(mp) == local_host_wslen &&
|
||||||
|
IS_WEQUALN(mp, local_host, local_host_wslen)) {
|
||||||
|
/*
|
||||||
|
* Bingo, local_host is in .make.machines.
|
||||||
|
* Continue reading.
|
||||||
|
*/
|
||||||
|
pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
|
||||||
|
/* Compare current hostname with full_host. */
|
||||||
|
} else if (wcslen(mp) == full_host_wslen &&
|
||||||
|
IS_WEQUALN(mp, full_host, full_host_wslen)) {
|
||||||
|
/*
|
||||||
|
* Bingo, full_host is in .make.machines.
|
||||||
|
* Continue reading.
|
||||||
|
*/
|
||||||
|
pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
|
||||||
|
} else {
|
||||||
|
if (c != '\n') {
|
||||||
|
SKIPTOEND(ms);
|
||||||
|
if (*ms) {
|
||||||
|
ms++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* If we get here, local_host is in .make.machines. */
|
||||||
|
if (c != '\n') {
|
||||||
|
/* Now look for keyword 'max'. */
|
||||||
|
MBSTOWCS(wcs_buffer, "max");
|
||||||
|
SKIPSPACE(ms);
|
||||||
|
while ((*ms != '\n') && (*ms)) {
|
||||||
|
if (*ms == '#') {
|
||||||
|
pskip_comment(&ms);
|
||||||
|
} else if (IS_WEQUALN(ms, wcs_buffer, 3)) {
|
||||||
|
/* Skip "max". */
|
||||||
|
ms += 3;
|
||||||
|
pmake_max_jobs = get_max(&ms, mp);
|
||||||
|
SKIPSPACE(ms);
|
||||||
|
} else {
|
||||||
|
warning(gettext("unknown option for host %s"), mbs_buffer);
|
||||||
|
SKIPTOEND(ms);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; /* out of outermost for() loop. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retmem(make_machines_list);
|
||||||
|
return(pmake_max_jobs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pskip_till_next_word(cp)
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* cp the address of the string pointer.
|
||||||
|
*
|
||||||
|
* On return:
|
||||||
|
* cp points to beginning of machine name.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
pskip_till_next_word(wchar_t **cp)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Keep recursing until all combinations of white spaces
|
||||||
|
* and comments have been skipped.
|
||||||
|
*/
|
||||||
|
if (pskip_white_space(cp) || pskip_comment(cp)) {
|
||||||
|
pskip_till_next_word(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pskip_white_space(cp_address)
|
||||||
|
*
|
||||||
|
* Advances the string pointer so that it points to the first
|
||||||
|
* non white character (space/tab/linefeed).
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* cp_address the address of the string pointer.
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* True if the pointer was changed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static Boolean
|
||||||
|
pskip_white_space(wchar_t **cp_address)
|
||||||
|
{
|
||||||
|
wchar_t *cp = *cp_address;
|
||||||
|
|
||||||
|
while (*cp && iswspace(*cp)) {
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
/* Have we skipped any characters? */
|
||||||
|
if (cp != *cp_address) {
|
||||||
|
*cp_address = cp;
|
||||||
|
return(true);
|
||||||
|
} else {
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pskip_comment(cp_address)
|
||||||
|
*
|
||||||
|
* If cp_address is pointing to '#' (the beginning of a comment),
|
||||||
|
* increment the pointer till you reach end of line.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* cp_address the address of the string pointer.
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* True if the pointer was changed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static Boolean
|
||||||
|
pskip_comment(wchar_t **cp_address)
|
||||||
|
{
|
||||||
|
wchar_t *cp = *cp_address;
|
||||||
|
|
||||||
|
/* Is this the beginning of a comment? Skip till end of line. */
|
||||||
|
if (*cp == '#') {
|
||||||
|
SKIPTOEND(cp);
|
||||||
|
}
|
||||||
|
/* Have we skipped a comment line? */
|
||||||
|
if (cp != *cp_address) {
|
||||||
|
*cp_address = cp;
|
||||||
|
return(true);
|
||||||
|
} else {
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_max(wchar_t **ms_address, wchar_t *hostname)
|
||||||
|
{
|
||||||
|
wchar_t *ms = *ms_address;
|
||||||
|
int limit = PMAKE_DEF_MAX_JOBS; /* Default setting. */
|
||||||
|
|
||||||
|
WCSTOMBS(mbs_buffer, hostname);
|
||||||
|
/* Look for `='. */
|
||||||
|
SKIPSPACE(ms);
|
||||||
|
if ((!*ms) || (*ms == '\n') || (*ms != '=')) {
|
||||||
|
SKIPTOEND(ms);
|
||||||
|
warning(gettext("expected `=' after max, ignoring rest of line for host %s"),
|
||||||
|
mbs_buffer);
|
||||||
|
*ms_address = ms;
|
||||||
|
return((int) limit);
|
||||||
|
} else {
|
||||||
|
ms++;
|
||||||
|
SKIPSPACE(ms);
|
||||||
|
if ((*ms != '\n') && (*ms != '\0')) {
|
||||||
|
/* We've found, hopefully, a valid "max" value. */
|
||||||
|
limit = (int) wcstol(ms, &ms, 10);
|
||||||
|
if (limit < 1) {
|
||||||
|
limit = PMAKE_DEF_MAX_JOBS;
|
||||||
|
warning(gettext("max value cannot be less than or equal to zero for host %s"), mbs_buffer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* No "max" value after "max=". */
|
||||||
|
warning(gettext("no max value specified for host %s"), mbs_buffer);
|
||||||
|
}
|
||||||
|
*ms_address = ms;
|
||||||
|
return(limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
2148
bin/read.cc
Normal file
2148
bin/read.cc
Normal file
File diff suppressed because it is too large
Load diff
1898
bin/read2.cc
Normal file
1898
bin/read2.cc
Normal file
File diff suppressed because it is too large
Load diff
394
bin/rep.cc
Normal file
394
bin/rep.cc
Normal file
|
@ -0,0 +1,394 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rep.c
|
||||||
|
*
|
||||||
|
* This file handles the .nse_depinfo file
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <mksh/misc.h> /* retmem() */
|
||||||
|
#include <vroot/report.h> /* NSE_DEPINFO */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static variables
|
||||||
|
*/
|
||||||
|
static Recursive_make recursive_list;
|
||||||
|
static Recursive_make *bpatch = &recursive_list;
|
||||||
|
static Boolean changed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* report_recursive_init()
|
||||||
|
*
|
||||||
|
* Read the .nse_depinfo file and make a list of all the
|
||||||
|
* .RECURSIVE entries.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* Static variables used:
|
||||||
|
* bpatch Points to slot where next cell should be added
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* recursive_name The Name ".RECURSIVE", compared against
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
report_recursive_init(void)
|
||||||
|
{
|
||||||
|
char *search_dir;
|
||||||
|
char nse_depinfo[MAXPATHLEN];
|
||||||
|
FILE *fp;
|
||||||
|
int line_size, line_index;
|
||||||
|
wchar_t *line;
|
||||||
|
wchar_t *bigger_line;
|
||||||
|
wchar_t *colon;
|
||||||
|
wchar_t *dollar;
|
||||||
|
Recursive_make rp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine can be called more than once, don't do
|
||||||
|
* anything after the first time.
|
||||||
|
*/
|
||||||
|
if (depinfo_already_read) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
depinfo_already_read = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
search_dir = getenv("NSE_DEP");
|
||||||
|
if (search_dir == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(void) sprintf(nse_depinfo, "%s/%s", search_dir, NSE_DEPINFO);
|
||||||
|
fp = fopen(nse_depinfo, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
line_size = MAXPATHLEN;
|
||||||
|
line_index = line_size - 1;
|
||||||
|
line = ALLOC_WC(line_size);
|
||||||
|
Wstring rns(recursive_name);
|
||||||
|
wchar_t * wcb = rns.get_string();
|
||||||
|
while (fgetws(line, line_size, fp) != NULL) {
|
||||||
|
while (wcslen(line) == line_index) {
|
||||||
|
if (line[wcslen(line) - 1] == '\n') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bigger_line = ALLOC_WC(2 * line_size);
|
||||||
|
wcscpy(bigger_line, line);
|
||||||
|
retmem(line);
|
||||||
|
line = bigger_line;
|
||||||
|
if (fgetws(&line[line_index], line_size, fp) == NULL)
|
||||||
|
continue;
|
||||||
|
line_index = 2 * line_index;
|
||||||
|
line_size = 2 * line_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
colon = (wchar_t *) wcschr(line, (int) colon_char);
|
||||||
|
if (colon == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dollar = (wchar_t *) wcschr(line, (int) dollar_char);
|
||||||
|
line[wcslen(line) - 1] = (int) nul_char;
|
||||||
|
if (IS_WEQUALN(&colon[2], wcb,
|
||||||
|
(int) recursive_name->hash.length)) {
|
||||||
|
/*
|
||||||
|
* If this entry is an old entry, ignore it
|
||||||
|
*/
|
||||||
|
MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION);
|
||||||
|
if (dollar == NULL ||
|
||||||
|
!IS_WEQUALN(wcs_buffer, (dollar+1) - VER_LEN, VER_LEN)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rp = ALLOC(Recursive_make);
|
||||||
|
(void) memset((char *) rp, 0, sizeof (Recursive_make_rec));
|
||||||
|
/*
|
||||||
|
* set conditional_macro_string if string is present
|
||||||
|
*/
|
||||||
|
rp->oldline = (wchar_t *) wcsdup(line);
|
||||||
|
if ( dollar != NULL ){
|
||||||
|
rp->cond_macrostring =
|
||||||
|
(wchar_t *) wcsdup(dollar - VER_LEN + 1);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* get target name into recursive struct
|
||||||
|
*/
|
||||||
|
*colon = (int) nul_char;
|
||||||
|
rp->target = (wchar_t *) wcsdup(line);
|
||||||
|
*bpatch = rp;
|
||||||
|
bpatch = &rp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* report_recursive_dep(target, line)
|
||||||
|
*
|
||||||
|
* Report a target as recursive.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* line Dependency line reported
|
||||||
|
*
|
||||||
|
* Static variables used:
|
||||||
|
* bpatch Points to slot where next cell should be added
|
||||||
|
* changed Written if report set changed
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
report_recursive_dep(Name target, wchar_t *line)
|
||||||
|
{
|
||||||
|
Recursive_make rp;
|
||||||
|
wchar_t rec_buf[STRING_BUFFER_LENGTH];
|
||||||
|
String_rec string;
|
||||||
|
|
||||||
|
INIT_STRING_FROM_STACK(string, rec_buf);
|
||||||
|
cond_macros_into_string(target, &string);
|
||||||
|
/*
|
||||||
|
* find an applicable recursive entry, if there isn't one, create it
|
||||||
|
*/
|
||||||
|
rp = find_recursive_target(target);
|
||||||
|
if (rp == NULL) {
|
||||||
|
rp = ALLOC(Recursive_make);
|
||||||
|
(void) memset((char *) rp, 0, sizeof (Recursive_make_rec));
|
||||||
|
wchar_t * wcb = get_wstring(target->string_mb); // XXX Tolik: needs retmem
|
||||||
|
rp->target = wcb;
|
||||||
|
rp->newline = (wchar_t *) wcsdup(line);
|
||||||
|
rp->cond_macrostring = (wchar_t *) wcsdup(rec_buf);
|
||||||
|
*bpatch = rp;
|
||||||
|
bpatch = &rp->next;
|
||||||
|
changed = true;
|
||||||
|
} else {
|
||||||
|
if ((rp->oldline != NULL) && !IS_WEQUAL(rp->oldline, line)) {
|
||||||
|
rp->newline = (wchar_t *) wcsdup(line);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
rp->removed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_recursive_target(target)
|
||||||
|
*
|
||||||
|
* Search the list for a given target.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The target cell
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target The target we need
|
||||||
|
* top_level_target more info used to determinde the
|
||||||
|
* target we need
|
||||||
|
*
|
||||||
|
* Static variables used:
|
||||||
|
* recursive_list The list of targets
|
||||||
|
*/
|
||||||
|
Recursive_make
|
||||||
|
find_recursive_target(Name target)
|
||||||
|
{
|
||||||
|
Recursive_make rp;
|
||||||
|
String_rec string;
|
||||||
|
wchar_t rec_buf[STRING_BUFFER_LENGTH];
|
||||||
|
|
||||||
|
INIT_STRING_FROM_STACK(string, rec_buf);
|
||||||
|
cond_macros_into_string(target, &string);
|
||||||
|
|
||||||
|
Wstring tstr(target);
|
||||||
|
wchar_t * wcb = tstr.get_string();
|
||||||
|
for (rp = recursive_list; rp != NULL; rp = rp->next) {
|
||||||
|
/*
|
||||||
|
* If this entry has already been removed, ignore it.
|
||||||
|
*/
|
||||||
|
if (rp->removed)
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
* If this target, and the target on the list are the same
|
||||||
|
* and if one of them contains conditional macro info, while
|
||||||
|
* the other doesn't, remove this entry from the list of
|
||||||
|
* recursive entries. This can only happen if the Makefile
|
||||||
|
* has changed to no longer contain conditional macros.
|
||||||
|
*/
|
||||||
|
if (IS_WEQUAL(rp->target, wcb)) {
|
||||||
|
if (rp->cond_macrostring[VER_LEN] == '\0' &&
|
||||||
|
string.buffer.start[VER_LEN] != '\0'){
|
||||||
|
rp->removed = true;
|
||||||
|
continue;
|
||||||
|
} else if (rp->cond_macrostring[VER_LEN] != '\0' &&
|
||||||
|
string.buffer.start[VER_LEN] == '\0'){
|
||||||
|
rp->removed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If this is not a VERS2 entry, only need to match
|
||||||
|
* the target name. toptarg information from VERS1 entries
|
||||||
|
* are ignored.
|
||||||
|
*/
|
||||||
|
MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION);
|
||||||
|
if (IS_WEQUALN(wcs_buffer, string.buffer.start, VER_LEN)) {
|
||||||
|
if (IS_WEQUAL(rp->cond_macrostring,
|
||||||
|
string.buffer.start) &&
|
||||||
|
IS_WEQUAL(rp->target, wcb)) {
|
||||||
|
return rp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (IS_WEQUAL(rp->target, wcb)) {
|
||||||
|
return rp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* remove_recursive_dep(target, top_level_target)
|
||||||
|
*
|
||||||
|
* Mark a target as no longer recursive.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target The target we want to remove
|
||||||
|
* top_level_target target we want to remove must be built from
|
||||||
|
* the same top level target
|
||||||
|
*
|
||||||
|
* Static variables used:
|
||||||
|
* changed Written if report set changed
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
remove_recursive_dep(Name target)
|
||||||
|
{
|
||||||
|
Recursive_make rp;
|
||||||
|
|
||||||
|
rp = find_recursive_target(target);
|
||||||
|
|
||||||
|
if ( rp != NULL ) {
|
||||||
|
rp->removed = true;
|
||||||
|
changed = true;
|
||||||
|
if(rp->target) {
|
||||||
|
retmem(rp->target);
|
||||||
|
rp->target = NULL;
|
||||||
|
}
|
||||||
|
if(rp->newline) {
|
||||||
|
retmem(rp->newline);
|
||||||
|
rp->newline = NULL;
|
||||||
|
}
|
||||||
|
if(rp->oldline) {
|
||||||
|
retmem(rp->oldline);
|
||||||
|
rp->oldline = NULL;
|
||||||
|
}
|
||||||
|
if(rp->cond_macrostring) {
|
||||||
|
retmem(rp->cond_macrostring);
|
||||||
|
rp->cond_macrostring = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* gather_recursive_deps()
|
||||||
|
*
|
||||||
|
* Create or update list of recursive targets.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gather_recursive_deps(void)
|
||||||
|
{
|
||||||
|
Name_set::iterator np, e;
|
||||||
|
String_rec rec;
|
||||||
|
wchar_t rec_buf[STRING_BUFFER_LENGTH];
|
||||||
|
register Property lines;
|
||||||
|
Boolean has_recursive;
|
||||||
|
Dependency dp;
|
||||||
|
|
||||||
|
report_recursive_init();
|
||||||
|
|
||||||
|
/* Go thru all targets and dump recursive dependencies */
|
||||||
|
for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) {
|
||||||
|
if (np->has_recursive_dependency){
|
||||||
|
has_recursive = false;
|
||||||
|
/*
|
||||||
|
* start .RECURSIVE line with target:
|
||||||
|
*/
|
||||||
|
INIT_STRING_FROM_STACK(rec, rec_buf);
|
||||||
|
APPEND_NAME(np, &rec, FIND_LENGTH);
|
||||||
|
append_char((int) colon_char, &rec);
|
||||||
|
append_char((int) space_char, &rec);
|
||||||
|
|
||||||
|
for (lines = get_prop(np->prop,recursive_prop);
|
||||||
|
lines != NULL;
|
||||||
|
lines = get_prop(lines->next, recursive_prop)) {
|
||||||
|
/*
|
||||||
|
* if entry is already in depinfo
|
||||||
|
* file or entry was not built, ignore it
|
||||||
|
*/
|
||||||
|
if (lines->body.recursive.in_depinfo)
|
||||||
|
continue;
|
||||||
|
if (!lines->body.recursive.has_built)
|
||||||
|
continue;
|
||||||
|
has_recursive = true;
|
||||||
|
lines->body.recursive.in_depinfo=true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the remainder of the
|
||||||
|
* .RECURSIVE line
|
||||||
|
*/
|
||||||
|
APPEND_NAME(recursive_name, &rec,
|
||||||
|
FIND_LENGTH);
|
||||||
|
append_char((int) space_char, &rec);
|
||||||
|
APPEND_NAME(lines->body.recursive.directory,
|
||||||
|
&rec, FIND_LENGTH);
|
||||||
|
append_char((int) space_char, &rec);
|
||||||
|
APPEND_NAME(lines->body.recursive.target,
|
||||||
|
&rec, FIND_LENGTH);
|
||||||
|
append_char((int) space_char, &rec);
|
||||||
|
|
||||||
|
/* Complete list of makefiles used */
|
||||||
|
for (dp = lines->body.recursive.makefiles;
|
||||||
|
dp != NULL;
|
||||||
|
dp = dp->next) {
|
||||||
|
APPEND_NAME(dp->name, &rec, FIND_LENGTH);
|
||||||
|
append_char((int) space_char, &rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* dump list of conditional targets,
|
||||||
|
* and report recursive entry, if needed
|
||||||
|
*/
|
||||||
|
cond_macros_into_string(np, &rec);
|
||||||
|
if (has_recursive){
|
||||||
|
report_recursive_dep(np, rec.buffer.start);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if ( np->has_built ) {
|
||||||
|
remove_recursive_dep(np);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
444
bin/state.cc
Normal file
444
bin/state.cc
Normal file
|
@ -0,0 +1,444 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* state.c
|
||||||
|
*
|
||||||
|
* This file contains the routines that write the .make.state file
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <mk/defs.h>
|
||||||
|
#include <mksh/misc.h> /* errmsg() */
|
||||||
|
#include <setjmp.h> /* setjmp() */
|
||||||
|
#include <unistd.h> /* getpid() */
|
||||||
|
#include <errno.h> /* errno */
|
||||||
|
#include <locale.h> /* MB_CUR_MAX */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined macros
|
||||||
|
*/
|
||||||
|
#define LONGJUMP_VALUE 17
|
||||||
|
#define XFWRITE(string, length, fd) {if (fwrite(string, 1, length, fd) == 0) \
|
||||||
|
longjmp(long_jump, LONGJUMP_VALUE);}
|
||||||
|
#define XPUTC(ch, fd) { \
|
||||||
|
if (putc((int) ch, fd) == EOF) \
|
||||||
|
longjmp(long_jump, LONGJUMP_VALUE); \
|
||||||
|
}
|
||||||
|
#define XFPUTS(string, fd) fputs(string, fd)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
static char * escape_target_name(Name np)
|
||||||
|
{
|
||||||
|
if(np->dollar) {
|
||||||
|
int len = strlen(np->string_mb);
|
||||||
|
char * buff = (char*)malloc(2 * len);
|
||||||
|
int pos = 0;
|
||||||
|
wchar_t wc;
|
||||||
|
int pp = 0;
|
||||||
|
while(pos < len) {
|
||||||
|
int n = mbtowc(&wc, np->string_mb + pos, MB_CUR_MAX);
|
||||||
|
if(n < 0) { // error - this shouldn't happen
|
||||||
|
(void)free(buff);
|
||||||
|
return strdup(np->string_mb);
|
||||||
|
}
|
||||||
|
if(wc == dollar_char) {
|
||||||
|
buff[pp] = '\\'; pp++;
|
||||||
|
buff[pp] = '$'; pp++;
|
||||||
|
} else {
|
||||||
|
for(int j=0;j<n;j++) {
|
||||||
|
buff[pp] = np->string_mb[pos+j]; pp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos += n;
|
||||||
|
}
|
||||||
|
buff[pp] = '\0';
|
||||||
|
return buff;
|
||||||
|
} else {
|
||||||
|
return strdup(np->string_mb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_auto_depes(register Dependency dependency, register FILE *fd, register Boolean built_this_run, register int *line_length, register char *target_name, jmp_buf long_jump);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* write_state_file(report_recursive, exiting)
|
||||||
|
*
|
||||||
|
* Write a new version of .make.state
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* report_recursive Should only be done at end of run
|
||||||
|
* exiting true if called from the exit handler
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* built_last_make_run The Name ".BUILT_LAST_MAKE_RUN", written
|
||||||
|
* command_changed If no command changed we do not need to write
|
||||||
|
* current_make_version The Name "<current version>", written
|
||||||
|
* do_not_exec_rule If -n is on we do not write statefile
|
||||||
|
* hashtab The hashtable that contains all names
|
||||||
|
* keep_state If .KEEP_STATE is no on we do not write file
|
||||||
|
* make_state The Name ".make.state", used for opening file
|
||||||
|
* make_version The Name ".MAKE_VERSION", written
|
||||||
|
* recursive_name The Name ".RECURSIVE", written
|
||||||
|
* rewrite_statefile Indicates that something changed
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
write_state_file(int, Boolean exiting)
|
||||||
|
{
|
||||||
|
register FILE *fd;
|
||||||
|
int lock_err;
|
||||||
|
char buffer[MAXPATHLEN];
|
||||||
|
char make_state_tempfile[MAXPATHLEN];
|
||||||
|
jmp_buf long_jump;
|
||||||
|
register int attempts = 0;
|
||||||
|
Name_set::iterator np, e;
|
||||||
|
register Property lines;
|
||||||
|
register int m;
|
||||||
|
Dependency dependency;
|
||||||
|
register Boolean name_printed;
|
||||||
|
Boolean built_this_run = false;
|
||||||
|
char *target_name;
|
||||||
|
int line_length;
|
||||||
|
register Cmd_line cp;
|
||||||
|
|
||||||
|
|
||||||
|
if (!rewrite_statefile ||
|
||||||
|
!command_changed ||
|
||||||
|
!keep_state ||
|
||||||
|
do_not_exec_rule ||
|
||||||
|
(report_dependencies_level > 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Lock the file for writing. */
|
||||||
|
make_state_lockfile = getmem(strlen(make_state->string_mb) + strlen(".lock") + 1);
|
||||||
|
(void) sprintf(make_state_lockfile,
|
||||||
|
"%s.lock",
|
||||||
|
make_state->string_mb);
|
||||||
|
if (lock_err = file_lock(make_state->string_mb,
|
||||||
|
make_state_lockfile,
|
||||||
|
(int *) &make_state_locked, 0)) {
|
||||||
|
retmem_mb(make_state_lockfile);
|
||||||
|
make_state_lockfile = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to make sure that we are not being
|
||||||
|
* called by the exit handler so we don't call
|
||||||
|
* it again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (exiting) {
|
||||||
|
(void) sprintf(buffer, "%s/.make.state.%d.XXXXXX", tmpdir, getpid());
|
||||||
|
report_pwd = true;
|
||||||
|
warning(gettext("Writing to %s"), buffer);
|
||||||
|
int fdes = mkstemp(buffer);
|
||||||
|
if ((fdes < 0) || (fd = fdopen(fdes, "w")) == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
gettext("Could not open statefile `%s': %s"),
|
||||||
|
buffer,
|
||||||
|
errmsg(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
report_pwd = true;
|
||||||
|
fatal(gettext("Can't lock .make.state"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) sprintf(make_state_tempfile,
|
||||||
|
"%s.tmp",
|
||||||
|
make_state->string_mb);
|
||||||
|
/* Delete old temporary statefile (in case it exists) */
|
||||||
|
(void) unlink(make_state_tempfile);
|
||||||
|
if ((fd = fopen(make_state_tempfile, "w")) == NULL) {
|
||||||
|
lock_err = errno; /* Save it! unlink() can change errno */
|
||||||
|
(void) unlink(make_state_lockfile);
|
||||||
|
retmem_mb(make_state_lockfile);
|
||||||
|
make_state_lockfile = NULL;
|
||||||
|
make_state_locked = false;
|
||||||
|
fatal(gettext("Could not open temporary statefile `%s': %s"),
|
||||||
|
make_state_tempfile,
|
||||||
|
errmsg(lock_err));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Set a trap for failed writes. If a write fails, the routine
|
||||||
|
* will try saving the .make.state file under another name in /tmp.
|
||||||
|
*/
|
||||||
|
if (setjmp(long_jump)) {
|
||||||
|
(void) fclose(fd);
|
||||||
|
if (attempts++ > 5) {
|
||||||
|
if ((make_state_lockfile != NULL) &&
|
||||||
|
make_state_locked) {
|
||||||
|
(void) unlink(make_state_lockfile);
|
||||||
|
retmem_mb(make_state_lockfile);
|
||||||
|
make_state_lockfile = NULL;
|
||||||
|
make_state_locked = false;
|
||||||
|
}
|
||||||
|
fatal(gettext("Giving up on writing statefile"));
|
||||||
|
}
|
||||||
|
sleep(10);
|
||||||
|
(void) sprintf(buffer, "%s/.make.state.%d.XXXXXX", tmpdir, getpid());
|
||||||
|
int fdes = mkstemp(buffer);
|
||||||
|
if ((fdes < 0) || (fd = fdopen(fdes, "w")) == NULL) {
|
||||||
|
fatal(gettext("Could not open statefile `%s': %s"),
|
||||||
|
buffer,
|
||||||
|
errmsg(errno));
|
||||||
|
}
|
||||||
|
warning(gettext("Initial write of statefile failed. Trying again on %s"),
|
||||||
|
buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the version stamp. */
|
||||||
|
XFWRITE(make_version->string_mb,
|
||||||
|
strlen(make_version->string_mb),
|
||||||
|
fd);
|
||||||
|
XPUTC(colon_char, fd);
|
||||||
|
XPUTC(tab_char, fd);
|
||||||
|
XFWRITE(current_make_version->string_mb,
|
||||||
|
strlen(current_make_version->string_mb),
|
||||||
|
fd);
|
||||||
|
XPUTC(newline_char, fd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go through all the targets, dump their dependencies and
|
||||||
|
* command used.
|
||||||
|
*/
|
||||||
|
for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) {
|
||||||
|
/*
|
||||||
|
* If the target has no command used nor dependencies,
|
||||||
|
* we can go to the next one.
|
||||||
|
*/
|
||||||
|
if ((lines = get_prop(np->prop, line_prop)) == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* If this target is a special target, don't print. */
|
||||||
|
if (np->special_reader != no_special) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Find out if any of the targets dependencies should
|
||||||
|
* be written to .make.state.
|
||||||
|
*/
|
||||||
|
for (m = 0, dependency = lines->body.line.dependencies;
|
||||||
|
dependency != NULL;
|
||||||
|
dependency = dependency->next) {
|
||||||
|
if (m = !dependency->stale
|
||||||
|
&& (dependency->name != force)
|
||||||
|
#ifndef PRINT_EXPLICIT_DEPEN
|
||||||
|
&& dependency->automatic
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Only print if dependencies listed. */
|
||||||
|
if (m || (lines->body.line.command_used != NULL)) {
|
||||||
|
name_printed = false;
|
||||||
|
/*
|
||||||
|
* If this target was built during this make run,
|
||||||
|
* we mark it.
|
||||||
|
*/
|
||||||
|
built_this_run = false;
|
||||||
|
if (np->has_built) {
|
||||||
|
built_this_run = true;
|
||||||
|
XFWRITE(built_last_make_run->string_mb,
|
||||||
|
strlen(built_last_make_run->string_mb),
|
||||||
|
fd);
|
||||||
|
XPUTC(colon_char, fd);
|
||||||
|
XPUTC(newline_char, fd);
|
||||||
|
}
|
||||||
|
/* If the target has dependencies, we dump them. */
|
||||||
|
target_name = escape_target_name(np);
|
||||||
|
if (np->has_long_member_name) {
|
||||||
|
target_name =
|
||||||
|
get_prop(np->prop, long_member_name_prop)
|
||||||
|
->body.long_member_name.member_name->
|
||||||
|
string_mb;
|
||||||
|
}
|
||||||
|
if (m) {
|
||||||
|
XFPUTS(target_name, fd);
|
||||||
|
XPUTC(colon_char, fd);
|
||||||
|
XFPUTS("\t", fd);
|
||||||
|
name_printed = true;
|
||||||
|
line_length = 0;
|
||||||
|
for (dependency =
|
||||||
|
lines->body.line.dependencies;
|
||||||
|
dependency != NULL;
|
||||||
|
dependency = dependency->next) {
|
||||||
|
print_auto_depes(dependency,
|
||||||
|
fd,
|
||||||
|
built_this_run,
|
||||||
|
&line_length,
|
||||||
|
target_name,
|
||||||
|
long_jump);
|
||||||
|
}
|
||||||
|
XFPUTS("\n", fd);
|
||||||
|
}
|
||||||
|
/* If there is a command used, we dump it. */
|
||||||
|
if (lines->body.line.command_used != NULL) {
|
||||||
|
/*
|
||||||
|
* Only write the target name if it
|
||||||
|
* wasn't done for the dependencies.
|
||||||
|
*/
|
||||||
|
if (!name_printed) {
|
||||||
|
XFPUTS(target_name, fd);
|
||||||
|
XPUTC(colon_char, fd);
|
||||||
|
XPUTC(newline_char, fd);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Write the command lines.
|
||||||
|
* Prefix each textual line with a tab.
|
||||||
|
*/
|
||||||
|
for (cp = lines->body.line.command_used;
|
||||||
|
cp != NULL;
|
||||||
|
cp = cp->next) {
|
||||||
|
char *csp;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
XPUTC(tab_char, fd);
|
||||||
|
if (cp->command_line != NULL) {
|
||||||
|
for (csp = cp->
|
||||||
|
command_line->
|
||||||
|
string_mb,
|
||||||
|
n = strlen(cp->
|
||||||
|
command_line->
|
||||||
|
string_mb);
|
||||||
|
n > 0;
|
||||||
|
n--, csp++) {
|
||||||
|
XPUTC(*csp, fd);
|
||||||
|
if (*csp ==
|
||||||
|
(int) newline_char) {
|
||||||
|
XPUTC(tab_char,
|
||||||
|
fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XPUTC(newline_char, fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void)free(target_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fclose(fd) == EOF) {
|
||||||
|
longjmp(long_jump, LONGJUMP_VALUE);
|
||||||
|
}
|
||||||
|
if (attempts == 0) {
|
||||||
|
if (unlink(make_state->string_mb) != 0 && errno != ENOENT) {
|
||||||
|
lock_err = errno; /* Save it! unlink() can change errno */
|
||||||
|
/* Delete temporary statefile */
|
||||||
|
(void) unlink(make_state_tempfile);
|
||||||
|
(void) unlink(make_state_lockfile);
|
||||||
|
retmem_mb(make_state_lockfile);
|
||||||
|
make_state_lockfile = NULL;
|
||||||
|
make_state_locked = false;
|
||||||
|
fatal(gettext("Could not delete old statefile `%s': %s"),
|
||||||
|
make_state->string_mb,
|
||||||
|
errmsg(lock_err));
|
||||||
|
}
|
||||||
|
if (rename(make_state_tempfile, make_state->string_mb) != 0) {
|
||||||
|
lock_err = errno; /* Save it! unlink() can change errno */
|
||||||
|
/* Delete temporary statefile */
|
||||||
|
(void) unlink(make_state_tempfile);
|
||||||
|
(void) unlink(make_state_lockfile);
|
||||||
|
retmem_mb(make_state_lockfile);
|
||||||
|
make_state_lockfile = NULL;
|
||||||
|
make_state_locked = false;
|
||||||
|
fatal(gettext("Could not rename `%s' to `%s': %s"),
|
||||||
|
make_state_tempfile,
|
||||||
|
make_state->string_mb,
|
||||||
|
errmsg(lock_err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((make_state_lockfile != NULL) && make_state_locked) {
|
||||||
|
(void) unlink(make_state_lockfile);
|
||||||
|
retmem_mb(make_state_lockfile);
|
||||||
|
make_state_lockfile = NULL;
|
||||||
|
make_state_locked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print_auto_depes(dependency, fd, built_this_run,
|
||||||
|
* line_length, target_name, long_jump)
|
||||||
|
*
|
||||||
|
* Will print a dependency list for automatic entries.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* dependency The dependency to print
|
||||||
|
* fd The file to print it to
|
||||||
|
* built_this_run If on we prefix each line with .BUILT_THIS...
|
||||||
|
* line_length Pointer to line length var that we update
|
||||||
|
* target_name We need this when we restart line
|
||||||
|
* long_jump setjmp/longjmp buffer used for IO error action
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* built_last_make_run The Name ".BUILT_LAST_MAKE_RUN", written
|
||||||
|
* force The Name " FORCE", compared against
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_auto_depes(register Dependency dependency, register FILE *fd, register Boolean built_this_run, register int *line_length, register char *target_name, jmp_buf long_jump)
|
||||||
|
{
|
||||||
|
if (!dependency->automatic ||
|
||||||
|
dependency->stale ||
|
||||||
|
(dependency->name == force)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
XFWRITE(dependency->name->string_mb,
|
||||||
|
strlen(dependency->name->string_mb),
|
||||||
|
fd);
|
||||||
|
/*
|
||||||
|
* Check if the dependency line is too long.
|
||||||
|
* If so, break it and start a new one.
|
||||||
|
*/
|
||||||
|
if ((*line_length += (int) strlen(dependency->name->string_mb) + 1) > 450) {
|
||||||
|
*line_length = 0;
|
||||||
|
XPUTC(newline_char, fd);
|
||||||
|
if (built_this_run) {
|
||||||
|
XFPUTS(built_last_make_run->string_mb, fd);
|
||||||
|
XPUTC(colon_char, fd);
|
||||||
|
XPUTC(newline_char, fd);
|
||||||
|
}
|
||||||
|
XFPUTS(target_name, fd);
|
||||||
|
XPUTC(colon_char, fd);
|
||||||
|
XPUTC(tab_char, fd);
|
||||||
|
} else {
|
||||||
|
XFPUTS(" ", fd);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
241
bin/svr4.make.rules.file
Normal file
241
bin/svr4.make.rules.file
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
#
|
||||||
|
# CDDL HEADER START
|
||||||
|
#
|
||||||
|
# The contents of this file are subject to the terms of the
|
||||||
|
# Common Development and Distribution License (the "License").
|
||||||
|
# You may not use this file except in compliance with the License.
|
||||||
|
#
|
||||||
|
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
# or http://www.opensolaris.org/os/licensing.
|
||||||
|
# See the License for the specific language governing permissions
|
||||||
|
# and limitations under the License.
|
||||||
|
#
|
||||||
|
# When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
# If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
#
|
||||||
|
# CDDL HEADER END
|
||||||
|
#
|
||||||
|
# Copyright 1994 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
# Use is subject to license terms.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
.SUFFIXES: .o .c .c~ .y .y~ .l .l~ .s .s~ .sh .sh~ .h .h~ .f .f~ \
|
||||||
|
.C .C~ .Y .Y~ .L .L~
|
||||||
|
|
||||||
|
MAKE=make
|
||||||
|
BUILD=build
|
||||||
|
AR=ar
|
||||||
|
ARFLAGS=rv
|
||||||
|
AS=as
|
||||||
|
ASFLAGS=
|
||||||
|
CC=cc
|
||||||
|
CFLAGS=-O
|
||||||
|
F77=f77
|
||||||
|
FFLAGS=-O
|
||||||
|
GET=get
|
||||||
|
GFLAGS=
|
||||||
|
LD=ld
|
||||||
|
LDFLAGS=
|
||||||
|
LEX=lex
|
||||||
|
LFLAGS=
|
||||||
|
YACC=yacc
|
||||||
|
YFLAGS=
|
||||||
|
C++C=CC
|
||||||
|
C++FLAGS=-O
|
||||||
|
|
||||||
|
|
||||||
|
.c:
|
||||||
|
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
||||||
|
.c~:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(CC) $(CFLAGS) $*.c -o $@ $(LDFLAGS)
|
||||||
|
-rm -f $*.c
|
||||||
|
.f:
|
||||||
|
$(F77) $(FFLAGS) $< -o $@ $(LDFLAGS)
|
||||||
|
.f~:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(F77) $(FFLAGS) $*.f -o $@ $(LDFLAGS)
|
||||||
|
-rm -f $*.f
|
||||||
|
.s:
|
||||||
|
$(AS) $(ASFLAGS) $< -o $@ $(LDFLAGS)
|
||||||
|
.s~:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(AS) $(ASFLAGS) $*.s -o $* $(LDFLAGS)
|
||||||
|
-rm -f $*.s
|
||||||
|
.sh:
|
||||||
|
cp $< $@; chmod 0777 $@
|
||||||
|
.sh~:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
cp $*.sh $*; chmod 0777 $@
|
||||||
|
-rm -f $*.sh
|
||||||
|
.C:
|
||||||
|
$(C++C) $(C++FLAGS) $< -o $@ $(LDFLAGS)
|
||||||
|
.C~:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(C++C) $(C++FLAGS) $*.C -o $@ $(LDFLAGS)
|
||||||
|
-rm -f $*.C
|
||||||
|
|
||||||
|
.c.a:
|
||||||
|
$(CC) $(CFLAGS) -c $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $*.o
|
||||||
|
-rm -f $*.o
|
||||||
|
.c.o:
|
||||||
|
$(CC) $(CFLAGS) -c $<
|
||||||
|
.c~.a:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(CC) $(CFLAGS) -c $*.c
|
||||||
|
$(AR) $(ARFLAGS) $@ $*.o
|
||||||
|
-rm -f $*.[co]
|
||||||
|
.c~.c:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
.c~.o:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(CC) $(CFLAGS) -c $*.c
|
||||||
|
-rm -f $*.c
|
||||||
|
.f.a:
|
||||||
|
$(F77) $(FFLAGS) -c $*.f
|
||||||
|
$(AR) $(ARFLAGS) $@ $*.o
|
||||||
|
-rm -f $*.o
|
||||||
|
.f.o:
|
||||||
|
$(F77) $(FFLAGS) -c $*.f
|
||||||
|
.f~.a:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(F77) $(FFLAGS) -c $*.f
|
||||||
|
$(AR) $(ARFLAGS) $@ $*.o
|
||||||
|
-rm -f $*.[fo]
|
||||||
|
.f~.f:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
.f~.o:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(F77) $(FFLAGS) -c $*.f
|
||||||
|
-rm -f $*.f
|
||||||
|
.h~.h:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
.l.c:
|
||||||
|
$(LEX) $(LFLAGS) $<
|
||||||
|
mv lex.yy.c $@
|
||||||
|
.l.o:
|
||||||
|
$(LEX) $(LFLAGS) $<
|
||||||
|
$(CC) $(CFLAGS) -c lex.yy.c
|
||||||
|
-rm lex.yy.c; mv lex.yy.o $@
|
||||||
|
.l~.c:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(LEX) $(LFLAGS) $*.l
|
||||||
|
mv lex.yy.c $@
|
||||||
|
-rm -f $*.l
|
||||||
|
.l~.l:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
.l~.o:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(LEX) $(LFLAGS) $*.l
|
||||||
|
$(CC) $(CFLAGS) -c lex.yy.c
|
||||||
|
-rm -f lex.yy.c $*.l
|
||||||
|
mv lex.yy.o $@
|
||||||
|
.s.a:
|
||||||
|
$(AS) $(ASFLAGS) -o $*.o $*.s
|
||||||
|
$(AR) $(ARFLAGS) $@ $*.o
|
||||||
|
.s.o:
|
||||||
|
$(AS) $(ASFLAGS) -o $@ $<
|
||||||
|
.s~.a:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(AS) $(ASFLAGS) -o $*.o $*.s
|
||||||
|
$(AR) $(ARFLAGS) $@ $*.o
|
||||||
|
-rm -f $*.[so]
|
||||||
|
.s~.o:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(AS) $(ASFLAGS) -o $*.o $*.s
|
||||||
|
-rm -f $*.s
|
||||||
|
.s~.s:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
.sh~.sh:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
.y.c:
|
||||||
|
$(YACC) $(YFLAGS) $<
|
||||||
|
mv y.tab.c $@
|
||||||
|
.y.o:
|
||||||
|
$(YACC) $(YFLAGS) $<
|
||||||
|
$(CC) $(CFLAGS) -c y.tab.c
|
||||||
|
-rm y.tab.c
|
||||||
|
mv y.tab.o $@
|
||||||
|
.y~.c:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(YACC) $(YFLAGS) $*.y
|
||||||
|
mv y.tab.c $*.c
|
||||||
|
-rm -f $*.y
|
||||||
|
.y~.o:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(YACC) $(YFLAGS) $*.y
|
||||||
|
$(CC) $(CFLAGS) -c y.tab.c
|
||||||
|
-rm -f y.tab.c $*.y
|
||||||
|
mv y.tab.o $*.o
|
||||||
|
.y~.y :
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
.C.a:
|
||||||
|
$(C++C) $(C++FLAGS) -c $<
|
||||||
|
$(AR) $(ARFLAGS) $@ $*.o
|
||||||
|
-rm -f $*.o
|
||||||
|
.C.o:
|
||||||
|
$(C++C) $(C++FLAGS) -c $<
|
||||||
|
.C~.a:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(C++C) $(C++FLAGS) -c $*.C
|
||||||
|
$(AR) $(ARFLAGS) $@ $*.o
|
||||||
|
-rm -f $*.[Co]
|
||||||
|
.C~.C:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
.C~.o:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(C++C) $(C++FLAGS) -c $*.C
|
||||||
|
-rm -f $*.C
|
||||||
|
.L.C:
|
||||||
|
$(LEX) $(LFLAGS) $<
|
||||||
|
mv lex.yy.c $@
|
||||||
|
.L.o:
|
||||||
|
$(LEX) $(LFLAGS) $<
|
||||||
|
$(C++C) $(C++FLAGS) -c lex.yy.c
|
||||||
|
-rm lex.yy.c; mv lex.yy.o $@
|
||||||
|
.L~.C:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(LEX) $(LFLAGS) $*.L
|
||||||
|
mv lex.yy.c $@
|
||||||
|
-rm -f $*.L
|
||||||
|
.L~.L:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
.L~.o:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(LEX) $(LFLAGS) $*.L
|
||||||
|
$(C++C) $(C++FLAGS) -c lex.yy.c
|
||||||
|
-rm -f lex.yy.c $*.L
|
||||||
|
mv lex.yy.c $@
|
||||||
|
.Y.C:
|
||||||
|
$(YACC) $(YFLAGS) $<
|
||||||
|
mv y.tab.c $@
|
||||||
|
.Y.o:
|
||||||
|
$(YACC) $(YFLAGS) $<
|
||||||
|
$(C++C) $(C++FLAGS) -c y.tab.c
|
||||||
|
-rm y.tab.c
|
||||||
|
mv y.tab.o $@
|
||||||
|
.Y~.C:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(YACC) $(YFLAGS) $*.Y
|
||||||
|
mv y.tab.c $*.C
|
||||||
|
-rm -f $*.Y
|
||||||
|
.Y~.o:
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
$(YACC) $(YFLAGS) $*.Y
|
||||||
|
$(C++C) $(C++FLAGS) -c y.tab.c
|
||||||
|
-rm -f y.tab.c $*.Y
|
||||||
|
mv y.tab.o $*.o
|
||||||
|
.Y~.Y :
|
||||||
|
$(GET) $(GFLAGS) $<
|
||||||
|
|
||||||
|
markfile.o: markfile
|
||||||
|
echo "static char _sccsid[] = \"`grep @'(#)' markfile`\";" > markfile.c
|
||||||
|
$(CC) -c markfile.c
|
||||||
|
-rm -f markfile.c
|
||||||
|
|
||||||
|
.SCCS_GET:
|
||||||
|
$(GET) $(GFLAGS) s.$@
|
47
include/bsd/bsd.h
Normal file
47
include/bsd/bsd.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bsd/bsd.h: Interface definitions to BSD compatibility functions for SVR4.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BSD_BSD_H
|
||||||
|
#define _BSD_BSD_H
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
typedef void (*SIG_PF) (int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" SIG_PF bsd_signal(int a, SIG_PF b);
|
||||||
|
#else
|
||||||
|
extern void (*bsd_signal(int, void (*) (int))) (int);
|
||||||
|
#endif
|
||||||
|
extern void bsd_signals(void);
|
||||||
|
|
||||||
|
#endif
|
396
include/mk/defs.h
Normal file
396
include/mk/defs.h
Normal file
|
@ -0,0 +1,396 @@
|
||||||
|
#ifndef _MK_DEFS_H
|
||||||
|
#define _MK_DEFS_H
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mksh/defs.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SKIPSPACE(x) while (*x && \
|
||||||
|
((*x == (int) space_char) || \
|
||||||
|
(*x == (int) tab_char) || \
|
||||||
|
(*x == (int) comma_char))) { \
|
||||||
|
x++; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SKIPWORD(x) while (*x && \
|
||||||
|
(*x != (int) space_char) && \
|
||||||
|
(*x != (int) tab_char) && \
|
||||||
|
(*x != (int) newline_char) && \
|
||||||
|
(*x != (int) comma_char) && \
|
||||||
|
(*x != (int) equal_char)) { \
|
||||||
|
x++; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SKIPTOEND(x) while (*x && \
|
||||||
|
(*x != (int) newline_char)) { \
|
||||||
|
x++; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PMAKE_DEF_MAX_JOBS 2 /* Default number of parallel jobs. */
|
||||||
|
|
||||||
|
#define OUT_OF_DATE(a,b) \
|
||||||
|
(((a) < (b)) || (((a) == file_doesnt_exist) && ((b) == file_doesnt_exist)))
|
||||||
|
|
||||||
|
#define OUT_OF_DATE_SEC(a,b) \
|
||||||
|
(((a).tv_sec < (b).tv_sec) || (((a).tv_sec == file_doesnt_exist.tv_sec) && ((b).tv_sec == file_doesnt_exist.tv_sec)))
|
||||||
|
|
||||||
|
#define SETVAR(name, value, append) \
|
||||||
|
setvar_daemon(name, value, append, no_daemon, \
|
||||||
|
true, debug_level)
|
||||||
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||||
|
/*
|
||||||
|
* New feature added to SUN5_0 make, invoke the vanilla svr4 make when
|
||||||
|
* the USE_SVR4_MAKE environment variable is set.
|
||||||
|
*/
|
||||||
|
#define SVR4_MAKE "/usr/ccs/lib/svr4.make"
|
||||||
|
#define USE_SVR4_MAKE "USE_SVR4_MAKE"
|
||||||
|
/*
|
||||||
|
* The standard MAXHOSTNAMELEN is 64. We want 32.
|
||||||
|
*/
|
||||||
|
#define MAX_HOSTNAMELEN 32
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
no_state,
|
||||||
|
scan_name_state,
|
||||||
|
scan_command_state,
|
||||||
|
enter_dependencies_state,
|
||||||
|
enter_conditional_state,
|
||||||
|
enter_equal_state,
|
||||||
|
illegal_bytes_state,
|
||||||
|
illegal_eoln_state,
|
||||||
|
poorly_formed_macro_state,
|
||||||
|
exit_state
|
||||||
|
} Reader_state;
|
||||||
|
|
||||||
|
struct _Name_vector {
|
||||||
|
struct _Name *names[64];
|
||||||
|
struct _Chain *target_group[64];
|
||||||
|
short used;
|
||||||
|
struct _Name_vector *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Running {
|
||||||
|
struct _Running *next;
|
||||||
|
Doname state;
|
||||||
|
struct _Name *target;
|
||||||
|
struct _Name *true_target;
|
||||||
|
struct _Property *command;
|
||||||
|
struct _Name *sprodep_value;
|
||||||
|
char *sprodep_env;
|
||||||
|
int recursion_level;
|
||||||
|
Boolean do_get;
|
||||||
|
Boolean implicit;
|
||||||
|
Boolean redo;
|
||||||
|
int auto_count;
|
||||||
|
struct _Name **automatics;
|
||||||
|
pid_t pid;
|
||||||
|
int job_msg_id;
|
||||||
|
char *stdout_file;
|
||||||
|
char *stderr_file;
|
||||||
|
struct _Name *temp_file;
|
||||||
|
int conditional_cnt;
|
||||||
|
struct _Name **conditional_targets;
|
||||||
|
Boolean make_refd;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
serial_mode,
|
||||||
|
parallel_mode
|
||||||
|
} DMake_mode;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
txt1_mode,
|
||||||
|
txt2_mode,
|
||||||
|
html1_mode
|
||||||
|
} DMake_output_mode;
|
||||||
|
|
||||||
|
struct _Recursive_make {
|
||||||
|
struct _Recursive_make *next; /* Linked list */
|
||||||
|
wchar_t *target;/* Name of target */
|
||||||
|
wchar_t *oldline;/* Original line in .nse_depinfo */
|
||||||
|
wchar_t *newline;/* New line in .nse_depinfo */
|
||||||
|
wchar_t *cond_macrostring;
|
||||||
|
/* string built from value of
|
||||||
|
* conditional macros used by
|
||||||
|
* this target
|
||||||
|
*/
|
||||||
|
Boolean removed;/* This target is no longer recursive*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Dyntarget {
|
||||||
|
struct _Dyntarget *next;
|
||||||
|
struct _Name *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Typedefs for all structs
|
||||||
|
*/
|
||||||
|
typedef struct _Cmd_line *Cmd_line, Cmd_line_rec;
|
||||||
|
typedef struct _Dependency *Dependency, Dependency_rec;
|
||||||
|
typedef struct _Macro *Macro, Macro_rec;
|
||||||
|
typedef struct _Name_vector *Name_vector, Name_vector_rec;
|
||||||
|
typedef struct _Percent *Percent, Percent_rec;
|
||||||
|
typedef struct _Dyntarget *Dyntarget;
|
||||||
|
typedef struct _Recursive_make *Recursive_make, Recursive_make_rec;
|
||||||
|
typedef struct _Running *Running, Running_rec;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* extern declarations for all global variables.
|
||||||
|
* The actual declarations are in globals.cc
|
||||||
|
*/
|
||||||
|
extern Boolean allrules_read;
|
||||||
|
extern Name posix_name;
|
||||||
|
extern Name svr4_name;
|
||||||
|
extern Boolean sdot_target;
|
||||||
|
extern Boolean all_parallel;
|
||||||
|
extern Boolean assign_done;
|
||||||
|
extern Boolean build_failed_seen;
|
||||||
|
extern Name built_last_make_run;
|
||||||
|
extern Name c_at;
|
||||||
|
extern Boolean command_changed;
|
||||||
|
extern Boolean commands_done;
|
||||||
|
extern Chain conditional_targets;
|
||||||
|
extern Name conditionals;
|
||||||
|
extern Boolean continue_after_error;
|
||||||
|
extern Property current_line;
|
||||||
|
extern Name current_make_version;
|
||||||
|
extern Name current_target;
|
||||||
|
extern short debug_level;
|
||||||
|
extern Cmd_line default_rule;
|
||||||
|
extern Name default_rule_name;
|
||||||
|
extern Name default_target_to_build;
|
||||||
|
extern Boolean depinfo_already_read;
|
||||||
|
extern Name dmake_group;
|
||||||
|
extern Name dmake_max_jobs;
|
||||||
|
extern Name dmake_mode;
|
||||||
|
extern DMake_mode dmake_mode_type;
|
||||||
|
extern Name dmake_output_mode;
|
||||||
|
extern DMake_output_mode output_mode;
|
||||||
|
extern Name dmake_odir;
|
||||||
|
extern Name dmake_rcfile;
|
||||||
|
extern Name done;
|
||||||
|
extern Name dot;
|
||||||
|
extern Name dot_keep_state;
|
||||||
|
extern Name dot_keep_state_file;
|
||||||
|
extern Name empty_name;
|
||||||
|
extern Boolean fatal_in_progress;
|
||||||
|
extern int file_number;
|
||||||
|
extern Name force;
|
||||||
|
extern Name ignore_name;
|
||||||
|
extern Boolean ignore_errors;
|
||||||
|
extern Boolean ignore_errors_all;
|
||||||
|
extern Name init;
|
||||||
|
extern int job_msg_id;
|
||||||
|
extern Boolean keep_state;
|
||||||
|
extern Name make_state;
|
||||||
|
extern timestruc_t make_state_before;
|
||||||
|
extern Boolean make_state_locked;
|
||||||
|
extern Dependency makefiles_used;
|
||||||
|
extern Name makeflags;
|
||||||
|
extern Name make_version;
|
||||||
|
extern char mbs_buffer2[];
|
||||||
|
extern char *mbs_ptr;
|
||||||
|
extern char *mbs_ptr2;
|
||||||
|
extern Boolean no_action_was_taken;
|
||||||
|
extern Boolean no_parallel;
|
||||||
|
extern Name no_parallel_name;
|
||||||
|
extern Name not_auto;
|
||||||
|
extern Boolean only_parallel;
|
||||||
|
extern Boolean parallel;
|
||||||
|
extern Name parallel_name;
|
||||||
|
extern Name localhost_name;
|
||||||
|
extern int parallel_process_cnt;
|
||||||
|
extern Percent percent_list;
|
||||||
|
extern Dyntarget dyntarget_list;
|
||||||
|
extern Name plus;
|
||||||
|
extern Name pmake_machinesfile;
|
||||||
|
extern Name precious;
|
||||||
|
extern Name primary_makefile;
|
||||||
|
extern Boolean quest;
|
||||||
|
extern short read_trace_level;
|
||||||
|
extern Boolean reading_dependencies;
|
||||||
|
extern int recursion_level;
|
||||||
|
extern Name recursive_name;
|
||||||
|
extern short report_dependencies_level;
|
||||||
|
extern Boolean report_pwd;
|
||||||
|
extern Boolean rewrite_statefile;
|
||||||
|
extern Running running_list;
|
||||||
|
extern char *sccs_dir_path;
|
||||||
|
extern Name sccs_get_name;
|
||||||
|
extern Name sccs_get_posix_name;
|
||||||
|
extern Cmd_line sccs_get_rule;
|
||||||
|
extern Cmd_line sccs_get_org_rule;
|
||||||
|
extern Cmd_line sccs_get_posix_rule;
|
||||||
|
extern Name get_name;
|
||||||
|
extern Name get_posix_name;
|
||||||
|
extern Cmd_line get_rule;
|
||||||
|
extern Cmd_line get_posix_rule;
|
||||||
|
extern Boolean all_precious;
|
||||||
|
extern Boolean report_cwd;
|
||||||
|
extern Boolean silent_all;
|
||||||
|
extern Boolean silent;
|
||||||
|
extern Name silent_name;
|
||||||
|
extern char *stderr_file;
|
||||||
|
extern char *stdout_file;
|
||||||
|
extern Boolean stdout_stderr_same;
|
||||||
|
extern Dependency suffixes;
|
||||||
|
extern Name suffixes_name;
|
||||||
|
extern Name sunpro_dependencies;
|
||||||
|
extern Boolean target_variants;
|
||||||
|
extern const char *tmpdir;
|
||||||
|
extern const char *temp_file_directory;
|
||||||
|
extern Name temp_file_name;
|
||||||
|
extern short temp_file_number;
|
||||||
|
extern wchar_t *top_level_target;
|
||||||
|
extern Boolean touch;
|
||||||
|
extern Boolean trace_reader;
|
||||||
|
extern Boolean build_unconditional;
|
||||||
|
extern pathpt vroot_path;
|
||||||
|
extern Name wait_name;
|
||||||
|
extern wchar_t wcs_buffer2[];
|
||||||
|
extern wchar_t *wcs_ptr;
|
||||||
|
extern wchar_t *wcs_ptr2;
|
||||||
|
extern long int hostid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Declarations of system defined variables
|
||||||
|
*/
|
||||||
|
/* On linux this variable is defined in 'signal.h' */
|
||||||
|
extern char *sys_siglist[];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Declarations of system supplied functions
|
||||||
|
*/
|
||||||
|
extern int file_lock(char *, char *, int *, int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Declarations of functions declared and used by make
|
||||||
|
*/
|
||||||
|
extern void add_pending(Name target, int recursion_level, Boolean do_get, Boolean implicit, Boolean redo);
|
||||||
|
extern void add_running(Name target, Name true_target, Property command, int recursion_level, int auto_count, Name *automatics, Boolean do_get, Boolean implicit);
|
||||||
|
extern void add_serial(Name target, int recursion_level, Boolean do_get, Boolean implicit);
|
||||||
|
extern void add_subtree(Name target, int recursion_level, Boolean do_get, Boolean implicit);
|
||||||
|
extern void append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro);
|
||||||
|
extern void await_parallel(Boolean waitflg);
|
||||||
|
extern void build_suffix_list(Name target_suffix);
|
||||||
|
extern Boolean check_auto_dependencies(Name target, int auto_count, Name *automatics);
|
||||||
|
extern void check_state(Name temp_file_name);
|
||||||
|
extern void cond_macros_into_string(Name np, String_rec *buffer);
|
||||||
|
extern void construct_target_string();
|
||||||
|
extern void create_xdrs_ptr(void);
|
||||||
|
extern void depvar_add_to_list (Name name, Boolean cmdline);
|
||||||
|
extern Doname doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic = false);
|
||||||
|
extern Doname doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
|
||||||
|
extern Doname doname_parallel(Name target, Boolean do_get, Boolean implicit);
|
||||||
|
extern Doname dosys(register Name command, register Boolean ignore_error, register Boolean call_make, Boolean silent_error, Boolean always_exec, Name target);
|
||||||
|
extern void dump_make_state(void);
|
||||||
|
extern void dump_target_list(void);
|
||||||
|
extern void enter_conditional(register Name target, Name name, Name value, register Boolean append);
|
||||||
|
extern void enter_dependencies(register Name target, Chain target_group, register Name_vector depes, register Cmd_line command, register Separator separator);
|
||||||
|
extern void enter_dependency(Property line, register Name depe, Boolean automatic);
|
||||||
|
extern void enter_equal(Name name, Name value, register Boolean append);
|
||||||
|
extern Percent enter_percent(register Name target, Chain target_group, register Name_vector depes, Cmd_line command);
|
||||||
|
extern Dyntarget enter_dyntarget(register Name target);
|
||||||
|
extern Name_vector enter_name(String string, Boolean tail_present, register wchar_t *string_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names, Boolean *target_group_seen);
|
||||||
|
extern Boolean exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error);
|
||||||
|
extern Doname execute_parallel(Property line, Boolean waitflg, Boolean local = false);
|
||||||
|
extern Doname execute_serial(Property line);
|
||||||
|
extern timestruc_t& exists(register Name target);
|
||||||
|
extern void fatal(const char *, ...);
|
||||||
|
extern void fatal_reader(char *, ...);
|
||||||
|
extern Doname find_ar_suffix_rule(register Name target, Name true_target, Property *command, Boolean rechecking);
|
||||||
|
extern Doname find_double_suffix_rule(register Name target, Property *command, Boolean rechecking);
|
||||||
|
extern Doname find_percent_rule(register Name target, Property *command, Boolean rechecking);
|
||||||
|
extern int find_run_directory (char *cmd, char *cwd, char *dir, char **pgm, char **run, char *path);
|
||||||
|
extern Doname find_suffix_rule(Name target, Name target_body, Name target_suffix, Property *command, Boolean rechecking);
|
||||||
|
extern Chain find_target_groups(register Name_vector target_list, register int i, Boolean reset);
|
||||||
|
extern void finish_children(Boolean docheck);
|
||||||
|
extern void finish_running(void);
|
||||||
|
extern void free_chain(Name_vector ptr);
|
||||||
|
extern void gather_recursive_deps(void);
|
||||||
|
extern char *get_current_path(void);
|
||||||
|
extern int get_job_msg_id(void);
|
||||||
|
extern wchar_t *getmem_wc(register int size);
|
||||||
|
/* On linux getwd(char *) is defined in 'unistd.h' */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
extern char *getwd(char *);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
extern void handle_interrupt(int);
|
||||||
|
extern Boolean is_running(Name target);
|
||||||
|
extern void load_cached_names(void);
|
||||||
|
extern Boolean parallel_ok(Name target, Boolean line_prop_must_exists);
|
||||||
|
extern void print_dependencies(register Name target, register Property line);
|
||||||
|
extern void send_job_start_msg(Property line);
|
||||||
|
extern void send_rsrc_info_msg(int max_jobs, char *hostname, char *username);
|
||||||
|
extern void print_value(register Name value, Daemon daemon);
|
||||||
|
extern timestruc_t& read_archive(register Name target);
|
||||||
|
extern int read_dir(Name dir, wchar_t *pattern, Property line, wchar_t *library);
|
||||||
|
extern void read_directory_of_file(register Name file);
|
||||||
|
extern int read_make_machines(Name make_machines_name);
|
||||||
|
extern Boolean read_simple_file(register Name makefile_name, register Boolean chase_path, register Boolean doname_it, Boolean complain, Boolean must_exist, Boolean report_file, Boolean lock_makefile);
|
||||||
|
extern void remove_recursive_dep(Name target);
|
||||||
|
extern void report_recursive_dep(Name target, char *line);
|
||||||
|
extern void report_recursive_done(void);
|
||||||
|
extern void report_recursive_init(void);
|
||||||
|
extern Recursive_make find_recursive_target(Name target);
|
||||||
|
extern void reset_locals(register Name target, register Property old_locals, register Property conditional, register int index);
|
||||||
|
extern void set_locals(register Name target, register Property old_locals);
|
||||||
|
extern void setvar_append(register Name name, register Name value);
|
||||||
|
extern void setvar_envvar(void);
|
||||||
|
extern void special_reader(Name target, register Name_vector depes, Cmd_line command);
|
||||||
|
extern void startup_rxm();
|
||||||
|
extern Doname target_can_be_built(register Name target);
|
||||||
|
extern char *time_to_string(const timestruc_t &time);
|
||||||
|
extern void update_target(Property line, Doname result);
|
||||||
|
extern void warning(char *, ...);
|
||||||
|
extern void write_state_file(int report_recursive, Boolean exiting);
|
||||||
|
extern Name vpath_translation(register Name cmd);
|
||||||
|
extern char *make_install_prefix(void);
|
||||||
|
|
||||||
|
#define DEPINFO_FMT_VERSION "VERS2$"
|
||||||
|
#define VER_LEN strlen(DEPINFO_FMT_VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
945
include/mksh/defs.h
Normal file
945
include/mksh/defs.h
Normal file
|
@ -0,0 +1,945 @@
|
||||||
|
#ifndef _MKSH_DEFS_H
|
||||||
|
#define _MKSH_DEFS_H
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limits.h> /* MB_LEN_MAX */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h> /* wchar_t */
|
||||||
|
#include <string.h> /* strcmp() */
|
||||||
|
#include <sys/param.h> /* MAXPATHLEN */
|
||||||
|
#include <sys/types.h> /* time_t, caddr_t */
|
||||||
|
#include <vroot/vroot.h> /* pathpt */
|
||||||
|
#include <sys/time.h> /* timestruc_t */
|
||||||
|
#include <errno.h> /* errno */
|
||||||
|
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A type and some utilities for boolean values
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define false BOOLEAN_false
|
||||||
|
#define true BOOLEAN_true
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
false = 0,
|
||||||
|
true = 1,
|
||||||
|
failed = 0,
|
||||||
|
succeeded = 1
|
||||||
|
} Boolean;
|
||||||
|
#define BOOLEAN(expr) ((expr) ? true : false)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some random constants (in an enum so dbx knows their values)
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
update_delay = 30, /* time between rstat checks */
|
||||||
|
ar_member_name_len = 1024,
|
||||||
|
hashsize = 2048 /* size of hash table */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbols that defines all the different char constants make uses
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
ampersand_char = '&',
|
||||||
|
asterisk_char = '*',
|
||||||
|
at_char = '@',
|
||||||
|
backquote_char = '`',
|
||||||
|
backslash_char = '\\',
|
||||||
|
bar_char = '|',
|
||||||
|
braceleft_char = '{',
|
||||||
|
braceright_char = '}',
|
||||||
|
bracketleft_char = '[',
|
||||||
|
bracketright_char = ']',
|
||||||
|
colon_char = ':',
|
||||||
|
comma_char = ',',
|
||||||
|
dollar_char = '$',
|
||||||
|
doublequote_char = '"',
|
||||||
|
equal_char = '=',
|
||||||
|
exclam_char = '!',
|
||||||
|
greater_char = '>',
|
||||||
|
hat_char = '^',
|
||||||
|
hyphen_char = '-',
|
||||||
|
less_char = '<',
|
||||||
|
newline_char = '\n',
|
||||||
|
nul_char = '\0',
|
||||||
|
numbersign_char = '#',
|
||||||
|
parenleft_char = '(',
|
||||||
|
parenright_char = ')',
|
||||||
|
percent_char = '%',
|
||||||
|
period_char = '.',
|
||||||
|
plus_char = '+',
|
||||||
|
question_char = '?',
|
||||||
|
quote_char = '\'',
|
||||||
|
semicolon_char = ';',
|
||||||
|
slash_char = '/',
|
||||||
|
space_char = ' ',
|
||||||
|
tab_char = '\t',
|
||||||
|
tilde_char = '~'
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For make i18n. Codeset independent.
|
||||||
|
* Setup character semantics by identifying all the special characters
|
||||||
|
* of make, and assigning each an entry in the char_semantics[] vector.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
ampersand_char_entry = 0, /* 0 */
|
||||||
|
asterisk_char_entry, /* 1 */
|
||||||
|
at_char_entry, /* 2 */
|
||||||
|
backquote_char_entry, /* 3 */
|
||||||
|
backslash_char_entry, /* 4 */
|
||||||
|
bar_char_entry, /* 5 */
|
||||||
|
bracketleft_char_entry, /* 6 */
|
||||||
|
bracketright_char_entry, /* 7 */
|
||||||
|
colon_char_entry, /* 8 */
|
||||||
|
dollar_char_entry, /* 9 */
|
||||||
|
doublequote_char_entry, /* 10 */
|
||||||
|
equal_char_entry, /* 11 */
|
||||||
|
exclam_char_entry, /* 12 */
|
||||||
|
greater_char_entry, /* 13 */
|
||||||
|
hat_char_entry, /* 14 */
|
||||||
|
hyphen_char_entry, /* 15 */
|
||||||
|
less_char_entry, /* 16 */
|
||||||
|
newline_char_entry, /* 17 */
|
||||||
|
numbersign_char_entry, /* 18 */
|
||||||
|
parenleft_char_entry, /* 19 */
|
||||||
|
parenright_char_entry, /* 20 */
|
||||||
|
percent_char_entry, /* 21 */
|
||||||
|
plus_char_entry, /* 22 */
|
||||||
|
question_char_entry, /* 23 */
|
||||||
|
quote_char_entry, /* 24 */
|
||||||
|
semicolon_char_entry, /* 25 */
|
||||||
|
no_semantics_entry /* 26 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CHAR_SEMANTICS_ENTRIES should be the number of entries above.
|
||||||
|
* The last entry in char_semantics[] should be blank.
|
||||||
|
*/
|
||||||
|
#define CHAR_SEMANTICS_ENTRIES 27
|
||||||
|
/*
|
||||||
|
#define CHAR_SEMANTICS_STRING "&*@`\\|[]:$=!>-\n#()%+?;^<'\""
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some utility macros
|
||||||
|
*/
|
||||||
|
#define ALLOC(x) ((struct _##x *)getmem(sizeof (struct _##x)))
|
||||||
|
#define ALLOC_WC(x) ((wchar_t *)getmem((x) * SIZEOFWCHAR_T))
|
||||||
|
#define FIND_LENGTH -1
|
||||||
|
#define GETNAME(a,b) getname_fn((a), (b), false)
|
||||||
|
#define IS_EQUAL(a,b) (!strcmp((a), (b)))
|
||||||
|
#define IS_EQUALN(a,b,n) (!strncmp((a), (b), (n)))
|
||||||
|
#define IS_WEQUAL(a,b) (!wcscmp((a), (b)))
|
||||||
|
#define IS_WEQUALN(a,b,n) (!wcsncmp((a), (b), (n)))
|
||||||
|
#define MBLEN(a) mblen((a), MB_LEN_MAX)
|
||||||
|
#define MBSTOWCS(a,b) (void) mbstowcs_with_check((a), (b), MAXPATHLEN)
|
||||||
|
#define MBTOWC(a,b) mbtowc((a), (b), MB_LEN_MAX)
|
||||||
|
#define SIZEOFWCHAR_T (sizeof (wchar_t))
|
||||||
|
#define VSIZEOF(v) (sizeof (v) / sizeof ((v)[0]))
|
||||||
|
#define WCSTOMBS(a,b) (void) wcstombs((a), (b), (MAXPATHLEN * MB_LEN_MAX))
|
||||||
|
#define WCTOMB(a,b) (void) wctomb((a), (b))
|
||||||
|
#define HASH(v, c) (v = (v)*31 + (unsigned int)(c))
|
||||||
|
|
||||||
|
extern void mbstowcs_with_check(wchar_t *pwcs, const char *s, size_t n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bits stored in funny vector to classify chars
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
dollar_sem = 0001,
|
||||||
|
meta_sem = 0002,
|
||||||
|
percent_sem = 0004,
|
||||||
|
wildcard_sem = 0010,
|
||||||
|
command_prefix_sem = 0020,
|
||||||
|
special_macro_sem = 0040,
|
||||||
|
colon_sem = 0100,
|
||||||
|
parenleft_sem = 0200
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type returned from doname class functions
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
build_dont_know = 0,
|
||||||
|
build_failed,
|
||||||
|
build_ok,
|
||||||
|
build_in_progress,
|
||||||
|
build_running, /* PARALLEL & DISTRIBUTED */
|
||||||
|
build_pending, /* PARALLEL & DISTRIBUTED */
|
||||||
|
build_serial, /* PARALLEL & DISTRIBUTED */
|
||||||
|
build_subtree /* PARALLEL & DISTRIBUTED */
|
||||||
|
} Doname;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The String struct defines a string with the following layout
|
||||||
|
* "xxxxxxxxxxxxxxxCxxxxxxxxxxxxxxx________"
|
||||||
|
* ^ ^ ^ ^
|
||||||
|
* | | | |
|
||||||
|
* buffer.start text.p text.end buffer.end
|
||||||
|
* text.p points to the next char to read/write.
|
||||||
|
*/
|
||||||
|
struct _String {
|
||||||
|
struct Text {
|
||||||
|
wchar_t *p; /* Read/Write pointer */
|
||||||
|
wchar_t *end; /* Read limit pointer */
|
||||||
|
} text;
|
||||||
|
struct Physical_buffer {
|
||||||
|
wchar_t *start; /* Points to start of buffer */
|
||||||
|
wchar_t *end; /* End of physical buffer */
|
||||||
|
} buffer;
|
||||||
|
Boolean free_after_use:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define STRING_BUFFER_LENGTH 1024
|
||||||
|
#define INIT_STRING_FROM_STACK(str, buf) { \
|
||||||
|
str.buffer.start = (buf); \
|
||||||
|
str.text.p = (buf); \
|
||||||
|
str.text.end = NULL; \
|
||||||
|
str.buffer.end = (buf) \
|
||||||
|
+ (sizeof (buf)/SIZEOFWCHAR_T); \
|
||||||
|
str.free_after_use = false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define APPEND_NAME(np, dest, len) append_string((np)->string_mb, (dest), (len));
|
||||||
|
|
||||||
|
class Wstring {
|
||||||
|
public:
|
||||||
|
struct _String string;
|
||||||
|
wchar_t string_buf[STRING_BUFFER_LENGTH];
|
||||||
|
|
||||||
|
public:
|
||||||
|
Wstring();
|
||||||
|
Wstring(struct _Name * name);
|
||||||
|
~Wstring();
|
||||||
|
|
||||||
|
void init(struct _Name * name);
|
||||||
|
void init(wchar_t * name, unsigned length);
|
||||||
|
unsigned length() {
|
||||||
|
return wcslen(string.buffer.start);
|
||||||
|
};
|
||||||
|
void append_to_str(struct _String * str, unsigned off, unsigned length);
|
||||||
|
|
||||||
|
wchar_t * get_string() {
|
||||||
|
return string.buffer.start;
|
||||||
|
};
|
||||||
|
|
||||||
|
wchar_t * get_string(unsigned off) {
|
||||||
|
return string.buffer.start + off;
|
||||||
|
};
|
||||||
|
|
||||||
|
Boolean equaln(wchar_t * str, unsigned length);
|
||||||
|
Boolean equal(wchar_t * str);
|
||||||
|
Boolean equal(wchar_t * str, unsigned off);
|
||||||
|
Boolean equal(wchar_t * str, unsigned off, unsigned length);
|
||||||
|
|
||||||
|
Boolean equaln(Wstring * str, unsigned length);
|
||||||
|
Boolean equal(Wstring * str);
|
||||||
|
Boolean equal(Wstring * str, unsigned off);
|
||||||
|
Boolean equal(Wstring * str, unsigned off, unsigned length);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used for storing the $? list and also for the "target + target:"
|
||||||
|
* construct.
|
||||||
|
*/
|
||||||
|
struct _Chain {
|
||||||
|
struct _Chain *next;
|
||||||
|
struct _Name *name;
|
||||||
|
struct _Percent *percent_member;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stores one command line for a rule
|
||||||
|
*/
|
||||||
|
struct _Cmd_line {
|
||||||
|
struct _Cmd_line *next;
|
||||||
|
struct _Name *command_line;
|
||||||
|
Boolean make_refd:1; /* $(MAKE) referenced? */
|
||||||
|
/*
|
||||||
|
* Remember any command line prefixes given
|
||||||
|
*/
|
||||||
|
Boolean ignore_command_dependency:1; /* `?' */
|
||||||
|
Boolean assign:1; /* `=' */
|
||||||
|
Boolean ignore_error:1; /* `-' */
|
||||||
|
Boolean silent:1; /* `@' */
|
||||||
|
Boolean always_exec:1; /* `+' */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linked list of targets/files
|
||||||
|
*/
|
||||||
|
struct _Dependency {
|
||||||
|
struct _Dependency *next;
|
||||||
|
struct _Name *name;
|
||||||
|
Boolean automatic:1;
|
||||||
|
Boolean stale:1;
|
||||||
|
Boolean built:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The specials are markers for targets that the reader should special case
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
no_special,
|
||||||
|
built_last_make_run_special,
|
||||||
|
default_special,
|
||||||
|
get_posix_special,
|
||||||
|
get_special,
|
||||||
|
ignore_special,
|
||||||
|
keep_state_file_special,
|
||||||
|
keep_state_special,
|
||||||
|
make_version_special,
|
||||||
|
no_parallel_special,
|
||||||
|
parallel_special,
|
||||||
|
posix_special,
|
||||||
|
precious_special,
|
||||||
|
sccs_get_posix_special,
|
||||||
|
sccs_get_special,
|
||||||
|
silent_special,
|
||||||
|
suffixes_special,
|
||||||
|
svr4_special,
|
||||||
|
localhost_special
|
||||||
|
} Special;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
no_colon,
|
||||||
|
one_colon,
|
||||||
|
two_colon,
|
||||||
|
equal_seen,
|
||||||
|
conditional_seen,
|
||||||
|
none_seen
|
||||||
|
} Separator;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Magic values for the timestamp stored with each name object
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
extern const timestruc_t file_no_time;
|
||||||
|
extern const timestruc_t file_doesnt_exist;
|
||||||
|
extern const timestruc_t file_is_dir;
|
||||||
|
extern const timestruc_t file_min_time;
|
||||||
|
extern const timestruc_t file_max_time;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each Name has a list of properties
|
||||||
|
* The properties are used to store information that only
|
||||||
|
* a subset of the Names need
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
no_prop,
|
||||||
|
conditional_prop,
|
||||||
|
line_prop,
|
||||||
|
macro_prop,
|
||||||
|
makefile_prop,
|
||||||
|
member_prop,
|
||||||
|
recursive_prop,
|
||||||
|
sccs_prop,
|
||||||
|
suffix_prop,
|
||||||
|
target_prop,
|
||||||
|
time_prop,
|
||||||
|
vpath_alias_prop,
|
||||||
|
long_member_name_prop,
|
||||||
|
macro_append_prop,
|
||||||
|
env_mem_prop
|
||||||
|
} Property_id;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
no_daemon = 0,
|
||||||
|
chain_daemon
|
||||||
|
} Daemon;
|
||||||
|
|
||||||
|
struct _Env_mem {
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Macro_appendix {
|
||||||
|
struct _Name *value;
|
||||||
|
struct _Name *value_to_append;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Macro {
|
||||||
|
/*
|
||||||
|
* For "ABC = xyz" constructs
|
||||||
|
* Name "ABC" get one macro prop
|
||||||
|
*/
|
||||||
|
struct _Name *value;
|
||||||
|
Boolean exported:1;
|
||||||
|
Boolean read_only:1;
|
||||||
|
/*
|
||||||
|
* This macro is defined conditionally
|
||||||
|
*/
|
||||||
|
Boolean is_conditional:1;
|
||||||
|
/*
|
||||||
|
* The list for $? is stored as a structured list that
|
||||||
|
* is translated into a string iff it is referenced.
|
||||||
|
* This is why some macro values need a daemon.
|
||||||
|
*/
|
||||||
|
Daemon daemon:2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Macro_list {
|
||||||
|
struct _Macro_list *next;
|
||||||
|
char *macro_name;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sccs_stat {
|
||||||
|
DONT_KNOW_SCCS = 0,
|
||||||
|
NO_SCCS,
|
||||||
|
HAS_SCCS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Name {
|
||||||
|
struct _Property *prop; /* List of properties */
|
||||||
|
char *string_mb; /* Multi-byte name string */
|
||||||
|
struct {
|
||||||
|
unsigned int length;
|
||||||
|
} hash;
|
||||||
|
struct {
|
||||||
|
timestruc_t time; /* Modification */
|
||||||
|
int stat_errno; /* error from "stat" */
|
||||||
|
off_t size; /* Of file */
|
||||||
|
mode_t mode; /* Of file */
|
||||||
|
Boolean is_file:1;
|
||||||
|
Boolean is_dir:1;
|
||||||
|
Boolean is_sym_link:1;
|
||||||
|
Boolean is_precious:1;
|
||||||
|
enum sccs_stat has_sccs:2;
|
||||||
|
} stat;
|
||||||
|
/*
|
||||||
|
* Count instances of :: definitions for this target
|
||||||
|
*/
|
||||||
|
short colon_splits;
|
||||||
|
/*
|
||||||
|
* We only clear the automatic depes once per target per report
|
||||||
|
*/
|
||||||
|
short temp_file_number;
|
||||||
|
/*
|
||||||
|
* Count how many conditional macros this target has defined
|
||||||
|
*/
|
||||||
|
short conditional_cnt;
|
||||||
|
/*
|
||||||
|
* A conditional macro was used when building this target
|
||||||
|
*/
|
||||||
|
Boolean depends_on_conditional:1;
|
||||||
|
/*
|
||||||
|
* Pointer to list of conditional macros which were used to build
|
||||||
|
* this target
|
||||||
|
*/
|
||||||
|
struct _Macro_list *conditional_macro_list;
|
||||||
|
Boolean has_member_depe:1;
|
||||||
|
Boolean is_member:1;
|
||||||
|
/*
|
||||||
|
* This target is a directory that has been read
|
||||||
|
*/
|
||||||
|
Boolean has_read_dir:1;
|
||||||
|
/*
|
||||||
|
* This name is a macro that is now being expanded
|
||||||
|
*/
|
||||||
|
Boolean being_expanded:1;
|
||||||
|
/*
|
||||||
|
* This name is a magic name that the reader must know about
|
||||||
|
*/
|
||||||
|
Special special_reader:5;
|
||||||
|
Doname state:3;
|
||||||
|
Separator colons:3;
|
||||||
|
Boolean has_depe_list_expanded:1;
|
||||||
|
Boolean suffix_scan_done:1;
|
||||||
|
Boolean has_complained:1; /* For sccs */
|
||||||
|
/*
|
||||||
|
* This target has been built during this make run
|
||||||
|
*/
|
||||||
|
Boolean ran_command:1;
|
||||||
|
Boolean with_squiggle:1; /* for .SUFFIXES */
|
||||||
|
Boolean without_squiggle:1; /* for .SUFFIXES */
|
||||||
|
Boolean has_read_suffixes:1; /* Suffix list cached*/
|
||||||
|
Boolean has_suffixes:1;
|
||||||
|
Boolean has_target_prop:1;
|
||||||
|
Boolean has_vpath_alias_prop:1;
|
||||||
|
Boolean dependency_printed:1; /* For dump_make_state() */
|
||||||
|
Boolean dollar:1; /* In namestring */
|
||||||
|
Boolean meta:1; /* In namestring */
|
||||||
|
Boolean percent:1; /* In namestring */
|
||||||
|
Boolean wildcard:1; /* In namestring */
|
||||||
|
Boolean has_parent:1;
|
||||||
|
Boolean is_target:1;
|
||||||
|
Boolean has_built:1;
|
||||||
|
Boolean colon:1; /* In namestring */
|
||||||
|
Boolean parenleft:1; /* In namestring */
|
||||||
|
Boolean has_recursive_dependency:1;
|
||||||
|
Boolean has_regular_dependency:1;
|
||||||
|
Boolean is_double_colon:1;
|
||||||
|
Boolean is_double_colon_parent:1;
|
||||||
|
Boolean has_long_member_name:1;
|
||||||
|
/*
|
||||||
|
* allowed to run in parallel
|
||||||
|
*/
|
||||||
|
Boolean parallel:1;
|
||||||
|
/*
|
||||||
|
* not allowed to run in parallel
|
||||||
|
*/
|
||||||
|
Boolean no_parallel:1;
|
||||||
|
/*
|
||||||
|
* used in dependency_conflict
|
||||||
|
*/
|
||||||
|
Boolean checking_subtree:1;
|
||||||
|
Boolean added_pattern_conditionals:1;
|
||||||
|
/*
|
||||||
|
* rechecking target for possible rebuild
|
||||||
|
*/
|
||||||
|
Boolean rechecking_target:1;
|
||||||
|
/*
|
||||||
|
* build this target in silent mode
|
||||||
|
*/
|
||||||
|
Boolean silent_mode:1;
|
||||||
|
/*
|
||||||
|
* build this target in ignore error mode
|
||||||
|
*/
|
||||||
|
Boolean ignore_error_mode:1;
|
||||||
|
Boolean dont_activate_cond_values:1;
|
||||||
|
/*
|
||||||
|
* allowed to run serially on local host
|
||||||
|
*/
|
||||||
|
Boolean localhost:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stores the % matched default rules
|
||||||
|
*/
|
||||||
|
struct _Percent {
|
||||||
|
struct _Percent *next;
|
||||||
|
struct _Name **patterns;
|
||||||
|
struct _Name *name;
|
||||||
|
struct _Percent *dependencies;
|
||||||
|
struct _Cmd_line *command_template;
|
||||||
|
struct _Chain *target_group;
|
||||||
|
int patterns_total;
|
||||||
|
Boolean being_expanded;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Conditional {
|
||||||
|
/*
|
||||||
|
* For "foo := ABC [+]= xyz" constructs
|
||||||
|
* Name "foo" gets one conditional prop
|
||||||
|
*/
|
||||||
|
struct _Name *target;
|
||||||
|
struct _Name *name;
|
||||||
|
struct _Name *value;
|
||||||
|
int sequence;
|
||||||
|
Boolean append:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Line {
|
||||||
|
/*
|
||||||
|
* For "target : dependencies" constructs
|
||||||
|
* Name "target" gets one line prop
|
||||||
|
*/
|
||||||
|
struct _Cmd_line *command_template;
|
||||||
|
struct _Cmd_line *command_used;
|
||||||
|
struct _Dependency *dependencies;
|
||||||
|
timestruc_t dependency_time;
|
||||||
|
struct _Chain *target_group;
|
||||||
|
Boolean is_out_of_date:1;
|
||||||
|
Boolean sccs_command:1;
|
||||||
|
Boolean command_template_redefined:1;
|
||||||
|
Boolean dont_rebuild_command_used:1;
|
||||||
|
/*
|
||||||
|
* Values for the dynamic macros
|
||||||
|
*/
|
||||||
|
struct _Name *target;
|
||||||
|
struct _Name *star;
|
||||||
|
struct _Name *less;
|
||||||
|
struct _Name *percent;
|
||||||
|
struct _Chain *query;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Makefile {
|
||||||
|
/*
|
||||||
|
* Names that reference makefiles gets one prop
|
||||||
|
*/
|
||||||
|
wchar_t *contents;
|
||||||
|
off_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Member {
|
||||||
|
/*
|
||||||
|
* For "lib(member)" and "lib((entry))" constructs
|
||||||
|
* Name "lib(member)" gets one member prop
|
||||||
|
* Name "lib((entry))" gets one member prop
|
||||||
|
* The member field is filled in when the prop is refd
|
||||||
|
*/
|
||||||
|
struct _Name *library;
|
||||||
|
struct _Name *entry;
|
||||||
|
struct _Name *member;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Recursive {
|
||||||
|
/*
|
||||||
|
* For "target: .RECURSIVE dir makefiles" constructs
|
||||||
|
* Used to keep track of recursive calls to make
|
||||||
|
* Name "target" gets one recursive prop
|
||||||
|
*/
|
||||||
|
struct _Name *directory;
|
||||||
|
struct _Name *target;
|
||||||
|
struct _Dependency *makefiles;
|
||||||
|
Boolean has_built;
|
||||||
|
Boolean in_depinfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sccs {
|
||||||
|
/*
|
||||||
|
* Each file that has a SCCS s. file gets one prop
|
||||||
|
*/
|
||||||
|
struct _Name *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Suffix {
|
||||||
|
/*
|
||||||
|
* Cached list of suffixes that can build this target
|
||||||
|
* suffix is built from .SUFFIXES
|
||||||
|
*/
|
||||||
|
struct _Name *suffix;
|
||||||
|
struct _Cmd_line *command_template;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Target {
|
||||||
|
/*
|
||||||
|
* For "target:: dependencies" constructs
|
||||||
|
* The "::" construct is handled by converting it to
|
||||||
|
* "foo: 1@foo" + "1@foo: dependecies"
|
||||||
|
* "1@foo" gets one target prop
|
||||||
|
* This target prop cause $@ to be bound to "foo"
|
||||||
|
* not "1@foo" when the rule is evaluated
|
||||||
|
*/
|
||||||
|
struct _Name *target;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct STime {
|
||||||
|
/*
|
||||||
|
* Save the original time for :: targets
|
||||||
|
*/
|
||||||
|
timestruc_t time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Vpath_alias {
|
||||||
|
/*
|
||||||
|
* If a file was found using the VPATH it gets
|
||||||
|
* a vpath_alias prop
|
||||||
|
*/
|
||||||
|
struct _Name *alias;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Long_member_name {
|
||||||
|
/*
|
||||||
|
* Targets with a truncated member name carries
|
||||||
|
* the full lib(member) name for the state file
|
||||||
|
*/
|
||||||
|
struct _Name *member_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
union Body {
|
||||||
|
struct _Macro macro;
|
||||||
|
struct Conditional conditional;
|
||||||
|
struct Line line;
|
||||||
|
struct Makefile makefile;
|
||||||
|
struct Member member;
|
||||||
|
struct Recursive recursive;
|
||||||
|
struct Sccs sccs;
|
||||||
|
struct Suffix suffix;
|
||||||
|
struct Target target;
|
||||||
|
struct STime time;
|
||||||
|
struct Vpath_alias vpath_alias;
|
||||||
|
struct Long_member_name long_member_name;
|
||||||
|
struct _Macro_appendix macro_appendix;
|
||||||
|
struct _Env_mem env_mem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PROPERTY_HEAD_SIZE (sizeof (struct _Property)-sizeof (union Body))
|
||||||
|
struct _Property {
|
||||||
|
struct _Property *next;
|
||||||
|
Property_id type:4;
|
||||||
|
union Body body;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Structure for dynamic "ascii" arrays */
|
||||||
|
struct ASCII_Dyn_Array {
|
||||||
|
char *start;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Envvar {
|
||||||
|
struct _Name *name;
|
||||||
|
struct _Name *value;
|
||||||
|
struct _Envvar *next;
|
||||||
|
char *env_string;
|
||||||
|
Boolean already_put:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for the reader
|
||||||
|
*/
|
||||||
|
#define GOTO_STATE(new_state) { \
|
||||||
|
SET_STATE(new_state); \
|
||||||
|
goto enter_state; \
|
||||||
|
}
|
||||||
|
#define SET_STATE(new_state) state = (new_state)
|
||||||
|
|
||||||
|
#define UNCACHE_SOURCE() if (source != NULL) { \
|
||||||
|
source->string.text.p = source_p; \
|
||||||
|
}
|
||||||
|
#define CACHE_SOURCE(comp) if (source != NULL) { \
|
||||||
|
source_p = source->string.text.p - \
|
||||||
|
(comp); \
|
||||||
|
source_end = source->string.text.end; \
|
||||||
|
}
|
||||||
|
#define GET_NEXT_BLOCK_NOCHK(source) { UNCACHE_SOURCE(); \
|
||||||
|
source = get_next_block_fn(source); \
|
||||||
|
CACHE_SOURCE(0) \
|
||||||
|
}
|
||||||
|
#define GET_NEXT_BLOCK(source) { GET_NEXT_BLOCK_NOCHK(source); \
|
||||||
|
if (source != NULL && source->error_converting) { \
|
||||||
|
GOTO_STATE(illegal_bytes_state); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define GET_CHAR() ((source == NULL) || \
|
||||||
|
(source_p >= source_end) ? 0 : *source_p)
|
||||||
|
|
||||||
|
struct _Source {
|
||||||
|
struct _String string;
|
||||||
|
struct _Source *previous;
|
||||||
|
off_t bytes_left_in_file;
|
||||||
|
short fd;
|
||||||
|
Boolean already_expanded:1;
|
||||||
|
Boolean error_converting:1;
|
||||||
|
char *inp_buf;
|
||||||
|
char *inp_buf_end;
|
||||||
|
char *inp_buf_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
reading_nothing,
|
||||||
|
reading_makefile,
|
||||||
|
reading_statefile,
|
||||||
|
rereading_statefile,
|
||||||
|
reading_cpp_file
|
||||||
|
} Makefile_type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Typedefs for all structs
|
||||||
|
*/
|
||||||
|
typedef struct _Chain *Chain, Chain_rec;
|
||||||
|
typedef struct _Envvar *Envvar, Envvar_rec;
|
||||||
|
typedef struct _Macro_list *Macro_list, Macro_list_rec;
|
||||||
|
typedef struct _Name *Name, Name_rec;
|
||||||
|
typedef struct _Property *Property, Property_rec;
|
||||||
|
typedef struct _Source *Source, Source_rec;
|
||||||
|
typedef struct _String *String, String_rec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* name records hash table.
|
||||||
|
*/
|
||||||
|
struct Name_set {
|
||||||
|
private:
|
||||||
|
// single node in a tree
|
||||||
|
struct entry {
|
||||||
|
entry(Name name_, entry *parent_) :
|
||||||
|
name(name_),
|
||||||
|
parent(parent_),
|
||||||
|
left(0),
|
||||||
|
right(0),
|
||||||
|
depth(1)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Name name;
|
||||||
|
|
||||||
|
entry *parent;
|
||||||
|
entry *left;
|
||||||
|
entry *right;
|
||||||
|
unsigned depth;
|
||||||
|
|
||||||
|
void setup_depth() {
|
||||||
|
unsigned rdepth = (right != 0) ? right->depth : 0;
|
||||||
|
unsigned ldepth = (left != 0) ? left->depth : 0;
|
||||||
|
depth = 1 + ((ldepth > rdepth) ? ldepth : rdepth);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
// make iterator a friend of Name_set to have access to struct entry
|
||||||
|
struct iterator;
|
||||||
|
friend struct Name_set::iterator;
|
||||||
|
|
||||||
|
// iterator over tree nodes
|
||||||
|
struct iterator {
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
iterator() : node(0) {}
|
||||||
|
iterator(entry *node_) : node(node_) {}
|
||||||
|
|
||||||
|
// dereference operator
|
||||||
|
Name operator->() const { return node->name; }
|
||||||
|
|
||||||
|
// conversion operator
|
||||||
|
operator Name() { return node->name; }
|
||||||
|
|
||||||
|
// assignment operator
|
||||||
|
iterator& operator=(const iterator &o) { node = o.node; return *this; }
|
||||||
|
|
||||||
|
// equality/inequality operators
|
||||||
|
int operator==(const iterator &o) const { return (node == o.node); }
|
||||||
|
int operator!=(const iterator &o) const { return (node != o.node); }
|
||||||
|
|
||||||
|
// pre/post increment operators
|
||||||
|
iterator& operator++();
|
||||||
|
iterator operator++(int) { iterator it = *this; ++*this; return it; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// the node iterator points to
|
||||||
|
entry *node;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
Name_set() : root(0) {}
|
||||||
|
|
||||||
|
// lookup, insert and remove operations
|
||||||
|
Name lookup(const char *key);
|
||||||
|
Name insert(const char *key, Boolean &found);
|
||||||
|
void insert(Name name);
|
||||||
|
|
||||||
|
// begin/end iterators
|
||||||
|
iterator begin() const;
|
||||||
|
iterator end() const { return iterator(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// rebalance given node
|
||||||
|
void rebalance(entry *node);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// tree root
|
||||||
|
entry *root;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* extern declarations for all global variables.
|
||||||
|
* The actual declarations are in globals.cc
|
||||||
|
*/
|
||||||
|
extern char char_semantics[];
|
||||||
|
extern wchar_t char_semantics_char[];
|
||||||
|
extern Macro_list cond_macro_list;
|
||||||
|
extern Boolean conditional_macro_used;
|
||||||
|
extern Boolean do_not_exec_rule; /* `-n' */
|
||||||
|
extern Boolean dollarget_seen;
|
||||||
|
extern Boolean dollarless_flag;
|
||||||
|
extern Name dollarless_value;
|
||||||
|
extern char **environ;
|
||||||
|
extern Envvar envvar;
|
||||||
|
extern int exit_status;
|
||||||
|
extern wchar_t *file_being_read;
|
||||||
|
/* Variable gnu_style=true if env. var. SUN_MAKE_COMPAT_MODE=GNU (RFE 4866328) */
|
||||||
|
extern Boolean gnu_style;
|
||||||
|
extern Name_set hashtab;
|
||||||
|
extern Name host_arch;
|
||||||
|
extern Name host_mach;
|
||||||
|
extern int line_number;
|
||||||
|
extern char *make_state_lockfile;
|
||||||
|
extern Boolean make_word_mentioned;
|
||||||
|
extern Makefile_type makefile_type;
|
||||||
|
extern char mbs_buffer[];
|
||||||
|
extern Name path_name;
|
||||||
|
extern Boolean posix;
|
||||||
|
extern Name query;
|
||||||
|
extern Boolean query_mentioned;
|
||||||
|
extern Name hat;
|
||||||
|
extern Boolean reading_environment;
|
||||||
|
extern Name shell_name;
|
||||||
|
extern Boolean svr4;
|
||||||
|
extern Name target_arch;
|
||||||
|
extern Name target_mach;
|
||||||
|
extern Boolean tilde_rule;
|
||||||
|
extern wchar_t wcs_buffer[];
|
||||||
|
extern Boolean working_on_targets;
|
||||||
|
extern Name virtual_root;
|
||||||
|
extern Boolean vpath_defined;
|
||||||
|
extern Name vpath_name;
|
||||||
|
extern Boolean make_state_locked;
|
||||||
|
extern Boolean out_err_same;
|
||||||
|
extern pid_t childPid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RFE 1257407: make does not use fine granularity time info available from stat.
|
||||||
|
* High resolution time comparison.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline int
|
||||||
|
operator==(const timestruc_t &t1, const timestruc_t &t2) {
|
||||||
|
return ((t1.tv_sec == t2.tv_sec) && (t1.tv_nsec == t2.tv_nsec));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int
|
||||||
|
operator!=(const timestruc_t &t1, const timestruc_t &t2) {
|
||||||
|
return ((t1.tv_sec != t2.tv_sec) || (t1.tv_nsec != t2.tv_nsec));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int
|
||||||
|
operator>(const timestruc_t &t1, const timestruc_t &t2) {
|
||||||
|
if (t1.tv_sec == t2.tv_sec) {
|
||||||
|
return (t1.tv_nsec > t2.tv_nsec);
|
||||||
|
}
|
||||||
|
return (t1.tv_sec > t2.tv_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int
|
||||||
|
operator>=(const timestruc_t &t1, const timestruc_t &t2) {
|
||||||
|
if (t1.tv_sec == t2.tv_sec) {
|
||||||
|
return (t1.tv_nsec >= t2.tv_nsec);
|
||||||
|
}
|
||||||
|
return (t1.tv_sec > t2.tv_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int
|
||||||
|
operator<(const timestruc_t &t1, const timestruc_t &t2) {
|
||||||
|
if (t1.tv_sec == t2.tv_sec) {
|
||||||
|
return (t1.tv_nsec < t2.tv_nsec);
|
||||||
|
}
|
||||||
|
return (t1.tv_sec < t2.tv_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int
|
||||||
|
operator<=(const timestruc_t &t1, const timestruc_t &t2) {
|
||||||
|
if (t1.tv_sec == t2.tv_sec) {
|
||||||
|
return (t1.tv_nsec <= t2.tv_nsec);
|
||||||
|
}
|
||||||
|
return (t1.tv_sec < t2.tv_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
37
include/mksh/dosys.h
Normal file
37
include/mksh/dosys.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef _MKSH_DOSYS_H
|
||||||
|
#define _MKSH_DOSYS_H
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mksh/defs.h>
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
|
||||||
|
extern Boolean await(register Boolean ignore_error, register Boolean silent_error, Name target, wchar_t *command, pid_t running_pid, void *xdrs, int job_msg_id);
|
||||||
|
extern int doexec(register wchar_t *command, register Boolean ignore_error, char *stdout_file, char *stderr_file, pathpt vroot_path, int nice_prio);
|
||||||
|
extern int doshell(wchar_t *command, register Boolean ignore_error, char *stdout_file, char *stderr_file, int nice_prio);
|
||||||
|
extern void redirect_io(char *stdout_file, char *stderr_file);
|
||||||
|
extern void sh_command2string(register String command, register String destination);
|
||||||
|
|
||||||
|
#endif
|
30
include/mksh/globals.h
Normal file
30
include/mksh/globals.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef _MKSH_GLOBALS_H
|
||||||
|
#define _MKSH_GLOBALS_H
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1994 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mksh/defs.h>
|
||||||
|
|
||||||
|
#endif
|
33
include/mksh/i18n.h
Normal file
33
include/mksh/i18n.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef _MKSH_I18N_H
|
||||||
|
#define _MKSH_I18N_H
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1994 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mksh/defs.h>
|
||||||
|
|
||||||
|
extern int get_char_semantics_entry(wchar_t ch);
|
||||||
|
extern char get_char_semantics_value(wchar_t ch);
|
||||||
|
|
||||||
|
#endif
|
31
include/mksh/libmksh_init.h
Normal file
31
include/mksh/libmksh_init.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef _MKSH_INIT_H
|
||||||
|
#define _MKSH_INIT_H
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1995 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int libmksh_init()
|
||||||
|
void libmksh_fini();
|
||||||
|
|
||||||
|
#endif
|
36
include/mksh/macro.h
Normal file
36
include/mksh/macro.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef _MKSH_MACRO_H
|
||||||
|
#define _MKSH_MACRO_H
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mksh/defs.h>
|
||||||
|
|
||||||
|
extern void expand_macro(register Source source, register String destination, wchar_t *current_string, Boolean cmd);
|
||||||
|
extern void expand_value(Name value, register String destination, Boolean cmd);
|
||||||
|
extern Name getvar(register Name name);
|
||||||
|
|
||||||
|
extern Property setvar_daemon(register Name name, register Name value, Boolean append, Daemon daemon, Boolean strip_trailing_spaces, short debug_level);
|
||||||
|
|
||||||
|
#endif
|
55
include/mksh/misc.h
Normal file
55
include/mksh/misc.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#ifndef _MKSH_MISC_H
|
||||||
|
#define _MKSH_MISC_H
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mksh/defs.h>
|
||||||
|
|
||||||
|
extern void append_char(wchar_t from, register String to);
|
||||||
|
extern Property append_prop(register Name target, register Property_id type);
|
||||||
|
extern void append_string(register wchar_t *from, register String to, register int length);
|
||||||
|
extern void enable_interrupt(register void (*handler) (int));
|
||||||
|
extern char *errmsg(int errnum);
|
||||||
|
extern void fatal_mksh(const char *message, ...);
|
||||||
|
extern void fatal_reader_mksh(const char *pattern, ...);
|
||||||
|
extern char *get_current_path_mksh(void);
|
||||||
|
extern Property get_prop(register Property start, register Property_id type);
|
||||||
|
extern char *getmem(register int size);
|
||||||
|
extern Name getname_fn(wchar_t *name, register int len, register Boolean dont_enter, register Boolean * foundp = NULL);
|
||||||
|
extern void store_name(Name name);
|
||||||
|
extern void free_name(Name name);
|
||||||
|
extern void handle_interrupt_mksh(int);
|
||||||
|
extern Property maybe_append_prop(register Name target, register Property_id type);
|
||||||
|
extern void retmem(wchar_t *p);
|
||||||
|
extern void retmem_mb(caddr_t p);
|
||||||
|
extern void setup_char_semantics(void);
|
||||||
|
extern void setup_interrupt(register void (*handler) (int));
|
||||||
|
extern void warning_mksh(char * message, ...);
|
||||||
|
|
||||||
|
extern void append_string(register char *from, register String to, register int length);
|
||||||
|
extern wchar_t *get_wstring(char * from);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
37
include/mksh/mksh.h
Normal file
37
include/mksh/mksh.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef _MKSH_MKSH_H
|
||||||
|
#define _MKSH_MKSH_H
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mksh/defs.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
33
include/mksh/read.h
Normal file
33
include/mksh/read.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef _MKSH_READ_H
|
||||||
|
#define _MKSH_READ_H
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1994 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <mksh/defs.h>
|
||||||
|
|
||||||
|
extern Source get_next_block_fn(register Source source);
|
||||||
|
|
||||||
|
#endif
|
63
include/vroot/args.h
Normal file
63
include/vroot/args.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1999 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _ARGS_H_
|
||||||
|
#define _ARGS_H_
|
||||||
|
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
|
||||||
|
typedef enum { rw_read, rw_write} rwt, *rwpt;
|
||||||
|
|
||||||
|
extern void translate_with_thunk(register char *filename, int (*thunk) (char *), pathpt path_vector, pathpt vroot_vector, rwt rw);
|
||||||
|
|
||||||
|
union Args {
|
||||||
|
struct { int mode;} access;
|
||||||
|
struct { int mode;} chmod;
|
||||||
|
struct { int user; int group;} chown;
|
||||||
|
struct { int mode;} creat;
|
||||||
|
struct { char **argv; char **environ;} execve;
|
||||||
|
struct { struct stat *buffer;} lstat;
|
||||||
|
struct { int mode;} mkdir;
|
||||||
|
struct { char *name; int mode;} mount;
|
||||||
|
struct { int flags; int mode;} open;
|
||||||
|
struct { char *buffer; int buffer_size;} readlink;
|
||||||
|
struct { struct stat *buffer;} stat;
|
||||||
|
struct { int length;} truncate;
|
||||||
|
struct { struct timeval *time;} utimes;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern union Args vroot_args;
|
||||||
|
extern int vroot_result;
|
||||||
|
|
||||||
|
#endif
|
48
include/vroot/report.h
Normal file
48
include/vroot/report.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1994 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _REPORT_H_
|
||||||
|
#define _REPORT_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern FILE *get_report_file(void);
|
||||||
|
extern char *get_target_being_reported_for(void);
|
||||||
|
extern void report_dependency(const char *name);
|
||||||
|
extern int file_lock(char *name, char *lockname, int *file_locked, int timeout);
|
||||||
|
|
||||||
|
#define SUNPRO_DEPENDENCIES "SUNPRO_DEPENDENCIES"
|
||||||
|
#define LD "LD"
|
||||||
|
#define COMP "COMP"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These relate to Sun's ancient source control system that predated TeamWare,
|
||||||
|
* named NSE. They appear to be used regardless of its presence, however, and
|
||||||
|
* so linger.
|
||||||
|
*/
|
||||||
|
#define NSE_DEPINFO ".nse_depinfo"
|
||||||
|
#define NSE_DEPINFO_LOCK ".nse_depinfo.lock"
|
||||||
|
|
||||||
|
#endif
|
61
include/vroot/vroot.h
Normal file
61
include/vroot/vroot.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _VROOT_H_
|
||||||
|
#define _VROOT_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <nl_types.h>
|
||||||
|
|
||||||
|
#define VROOT_DEFAULT ((pathpt)-1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *path;
|
||||||
|
short length;
|
||||||
|
} pathcellt, *pathcellpt, patht;
|
||||||
|
typedef patht *pathpt;
|
||||||
|
|
||||||
|
extern void add_dir_to_path(const char *path, register pathpt *pointer, register int position);
|
||||||
|
extern void flush_path_cache(void);
|
||||||
|
extern void flush_vroot_cache(void);
|
||||||
|
extern const char *get_path_name(void);
|
||||||
|
extern char *get_vroot_path(register char **vroot, register char **path, register char **filename);
|
||||||
|
extern const char *get_vroot_name(void);
|
||||||
|
extern int open_vroot(char *path, int flags, int mode, pathpt vroot_path, pathpt vroot_vroot);
|
||||||
|
extern pathpt parse_path_string(register char *string, register int remove_slash);
|
||||||
|
extern void scan_path_first(void);
|
||||||
|
extern void scan_vroot_first(void);
|
||||||
|
extern void set_path_style(int style);
|
||||||
|
|
||||||
|
extern int access_vroot(char *path, int mode, pathpt vroot_path, pathpt vroot_vroot);
|
||||||
|
|
||||||
|
extern int execve_vroot(char *path, char **argv, char **environ, pathpt vroot_path, pathpt vroot_vroot);
|
||||||
|
|
||||||
|
extern int lstat_vroot(char *path, struct stat *buffer, pathpt vroot_path, pathpt vroot_vroot);
|
||||||
|
extern int stat_vroot(char *path, struct stat *buffer, pathpt vroot_path, pathpt vroot_vroot);
|
||||||
|
extern int readlink_vroot(char *path, char *buffer, int buffer_size, pathpt vroot_path, pathpt vroot_vroot);
|
||||||
|
|
||||||
|
#endif
|
73
lib/bsd/bsd.cc
Normal file
73
lib/bsd/bsd.cc
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <bsd/bsd.h>
|
||||||
|
|
||||||
|
/* External references.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Forward references.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Static data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern SIG_PF
|
||||||
|
bsd_signal (int Signal, SIG_PF Handler)
|
||||||
|
{
|
||||||
|
auto SIG_PF previous_handler;
|
||||||
|
#ifdef sun
|
||||||
|
previous_handler = sigset (Signal, Handler);
|
||||||
|
#else
|
||||||
|
auto struct sigaction new_action;
|
||||||
|
auto struct sigaction old_action;
|
||||||
|
|
||||||
|
new_action.sa_flags = SA_SIGINFO;
|
||||||
|
new_action.sa_handler = (void (*) ()) Handler;
|
||||||
|
(void) sigemptyset (&new_action.sa_mask);
|
||||||
|
(void) sigaddset (&new_action.sa_mask, Signal);
|
||||||
|
|
||||||
|
(void) sigaction (Signal, &new_action, &old_action);
|
||||||
|
|
||||||
|
previous_handler = (SIG_PF) old_action.sa_handler;
|
||||||
|
#endif
|
||||||
|
return previous_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void
|
||||||
|
bsd_signals (void)
|
||||||
|
{
|
||||||
|
static int initialized = 0;
|
||||||
|
|
||||||
|
if (initialized == 0)
|
||||||
|
{
|
||||||
|
initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
188
lib/makestate/ld_file.c
Normal file
188
lib/makestate/ld_file.c
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1998 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma init(ld_support_init)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libelf.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <link.h>
|
||||||
|
|
||||||
|
#define SUNPRO_DEPENDENCIES "SUNPRO_DEPENDENCIES"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linked list of strings - used to keep lists of names
|
||||||
|
* of directories or files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Stritem {
|
||||||
|
char * str;
|
||||||
|
void * next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Stritem Stritem;
|
||||||
|
|
||||||
|
static char * depend_file = NULL;
|
||||||
|
static Stritem * list = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void mk_state_init()
|
||||||
|
{
|
||||||
|
depend_file = getenv(SUNPRO_DEPENDENCIES);
|
||||||
|
} /* mk_state_init() */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
prepend_str(Stritem **list, const char * str)
|
||||||
|
{
|
||||||
|
Stritem * new;
|
||||||
|
char * newstr;
|
||||||
|
|
||||||
|
if (!(new = calloc(1, sizeof (Stritem)))) {
|
||||||
|
perror("libmakestate.so");
|
||||||
|
return;
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
if (!(newstr = malloc(strlen(str) + 1))) {
|
||||||
|
perror("libmakestate.so");
|
||||||
|
return;
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
new->str = strcpy(newstr, str);
|
||||||
|
new->next = *list;
|
||||||
|
*list = new;
|
||||||
|
|
||||||
|
} /* prepend_str() */
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mk_state_collect_dep(const char * file)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* SUNPRO_DEPENDENCIES wasn't set, we don't collect .make.state
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
if (!depend_file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
prepend_str(&list, file);
|
||||||
|
|
||||||
|
} /* mk_state_collect_dep() */
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mk_state_update_exit()
|
||||||
|
{
|
||||||
|
Stritem * cur;
|
||||||
|
char lockfile[MAXPATHLEN], * err, * space, * target;
|
||||||
|
FILE * ofp;
|
||||||
|
extern char * file_lock(char *, char *, int);
|
||||||
|
|
||||||
|
if (!depend_file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((space = strchr(depend_file, ' ')) == NULL)
|
||||||
|
return;
|
||||||
|
*space = '\0';
|
||||||
|
target = &space[1];
|
||||||
|
|
||||||
|
(void) sprintf(lockfile, "%s.lock", depend_file);
|
||||||
|
if ((err = file_lock(depend_file, lockfile, 0))) {
|
||||||
|
(void) fprintf(stderr, "%s\n", err);
|
||||||
|
return;
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
if (!(ofp = fopen(depend_file, "a")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (list)
|
||||||
|
(void) fprintf(ofp, "%s: ", target);
|
||||||
|
|
||||||
|
for (cur = list; cur; cur = cur->next)
|
||||||
|
(void) fprintf(ofp, " %s", cur->str);
|
||||||
|
|
||||||
|
(void) fputc('\n', ofp);
|
||||||
|
|
||||||
|
(void) fclose(ofp);
|
||||||
|
(void) unlink(lockfile);
|
||||||
|
*space = ' ';
|
||||||
|
|
||||||
|
} /* mk_state_update_exit() */
|
||||||
|
|
||||||
|
static void
|
||||||
|
/* LINTED static unused */
|
||||||
|
ld_support_init()
|
||||||
|
{
|
||||||
|
mk_state_init();
|
||||||
|
|
||||||
|
} /* ld_support_init() */
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
|
void
|
||||||
|
ld_file(const char * file, const Elf_Kind ekind, int flags, Elf *elf)
|
||||||
|
{
|
||||||
|
if(! ((flags & LD_SUP_DERIVED) && !(flags & LD_SUP_EXTRACTED)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mk_state_collect_dep(file);
|
||||||
|
|
||||||
|
} /* ld_file */
|
||||||
|
|
||||||
|
void
|
||||||
|
ld_atexit(int exit_code)
|
||||||
|
{
|
||||||
|
if (exit_code)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mk_state_update_exit();
|
||||||
|
|
||||||
|
} /* ld_atexit() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supporting 64-bit objects
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ld_file64(const char * file, const Elf_Kind ekind, int flags, Elf *elf)
|
||||||
|
{
|
||||||
|
if(! ((flags & LD_SUP_DERIVED) && !(flags & LD_SUP_EXTRACTED)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mk_state_collect_dep(file);
|
||||||
|
|
||||||
|
} /* ld_file64 */
|
||||||
|
|
||||||
|
void
|
||||||
|
ld_atexit64(int exit_code)
|
||||||
|
{
|
||||||
|
if (exit_code)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mk_state_update_exit();
|
||||||
|
|
||||||
|
} /* ld_atexit64() */
|
172
lib/makestate/lock.c
Normal file
172
lib/makestate/lock.c
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <errno.h> /* errno */
|
||||||
|
|
||||||
|
#if defined(_LP64)
|
||||||
|
/*
|
||||||
|
* The symbols _sys_errlist and _sys_nerr are not visible in the
|
||||||
|
* LP64 libc. Use strerror(3C) instead.
|
||||||
|
*/
|
||||||
|
#else /* #_LP64 */
|
||||||
|
extern char * sys_errlist[];
|
||||||
|
extern int sys_nerr;
|
||||||
|
#endif /* #_LP64 */
|
||||||
|
|
||||||
|
static void file_lock_error();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This code stolen from the NSE library and changed to not depend
|
||||||
|
* upon any NSE routines or header files.
|
||||||
|
*
|
||||||
|
* Simple file locking.
|
||||||
|
* Create a symlink to a file. The "test and set" will be
|
||||||
|
* atomic as creating the symlink provides both functions.
|
||||||
|
*
|
||||||
|
* The timeout value specifies how long to wait for stale locks
|
||||||
|
* to disappear. If the lock is more than 'timeout' seconds old
|
||||||
|
* then it is ok to blow it away. This part has a small window
|
||||||
|
* of vunerability as the operations of testing the time,
|
||||||
|
* removing the lock and creating a new one are not atomic.
|
||||||
|
* It would be possible for two processes to both decide to blow
|
||||||
|
* away the lock and then have process A remove the lock and establish
|
||||||
|
* its own, and then then have process B remove the lock which accidentily
|
||||||
|
* removes A's lock rather than the stale one.
|
||||||
|
*
|
||||||
|
* A further complication is with the NFS. If the file in question is
|
||||||
|
* being served by an NFS server, then its time is set by that server.
|
||||||
|
* We can not use the time on the client machine to check for a stale
|
||||||
|
* lock. Therefore, a temp file on the server is created to get
|
||||||
|
* the servers current time.
|
||||||
|
*
|
||||||
|
* Returns an error message. NULL return means the lock was obtained.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
file_lock(char * name, char * lockname, int timeout)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int fd;
|
||||||
|
struct stat statb;
|
||||||
|
struct stat fs_statb;
|
||||||
|
char tmpname[MAXPATHLEN];
|
||||||
|
static char msg[MAXPATHLEN];
|
||||||
|
|
||||||
|
if (timeout <= 0) {
|
||||||
|
timeout = 15;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
r = symlink(name, lockname);
|
||||||
|
if (r == 0) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
if (errno != EEXIST) {
|
||||||
|
file_lock_error(msg, name,
|
||||||
|
(const char *)"symlink(%s, %s)", name, lockname);
|
||||||
|
return (msg);
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
(void) sleep(1);
|
||||||
|
r = lstat(lockname, &statb);
|
||||||
|
if (r == -1) {
|
||||||
|
/*
|
||||||
|
* The lock must have just gone away - try
|
||||||
|
* again.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* With the NFS the time given a file is the time on
|
||||||
|
* the file server. This time may vary from the
|
||||||
|
* client's time. Therefore, we create a tmpfile in
|
||||||
|
* the same directory to establish the time on the
|
||||||
|
* server and use this time to see if the lock has
|
||||||
|
* expired.
|
||||||
|
*/
|
||||||
|
(void) sprintf(tmpname, "%s.XXXXXX", lockname);
|
||||||
|
(void) mktemp(tmpname);
|
||||||
|
fd = creat(tmpname, 0666);
|
||||||
|
if (fd != -1) {
|
||||||
|
(void) close(fd);
|
||||||
|
} else {
|
||||||
|
file_lock_error(msg, name,
|
||||||
|
(const char *)"creat(%s)", tmpname);
|
||||||
|
return (msg);
|
||||||
|
}
|
||||||
|
if (stat(tmpname, &fs_statb) == -1) {
|
||||||
|
file_lock_error(msg, name,
|
||||||
|
(const char *)"stat(%s)", tmpname);
|
||||||
|
return (msg);
|
||||||
|
}
|
||||||
|
(void) unlink(tmpname);
|
||||||
|
if (statb.st_mtime + timeout < fs_statb.st_mtime) {
|
||||||
|
/*
|
||||||
|
* The lock has expired - blow it away.
|
||||||
|
*/
|
||||||
|
(void) unlink(lockname);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Format a message telling why the lock could not be created.
|
||||||
|
*/
|
||||||
|
/* VARARGS4 */
|
||||||
|
static void
|
||||||
|
file_lock_error(char * msg, char * file, const char * str, char * arg1,
|
||||||
|
char * arg2)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
(void) sprintf(msg, "Could not lock file `%s'; ", file);
|
||||||
|
len = strlen(msg);
|
||||||
|
(void) sprintf(&msg[len], str, arg1, arg2);
|
||||||
|
(void) strcat(msg, " failed - ");
|
||||||
|
#if defined(_LP64)
|
||||||
|
/* Needs to be changed to use strerror(3C) instead. */
|
||||||
|
len = strlen(msg);
|
||||||
|
(void) sprintf(&msg[len], "errno %d", errno);
|
||||||
|
#else /* #_LP64 */
|
||||||
|
if (errno < sys_nerr) {
|
||||||
|
(void) strcat(msg, sys_errlist[errno]);
|
||||||
|
} else {
|
||||||
|
len = strlen(msg);
|
||||||
|
(void) sprintf(&msg[len], "errno %d", errno);
|
||||||
|
}
|
||||||
|
#endif /* #_LP64 */
|
||||||
|
}
|
577
lib/mksh/dosys.cc
Normal file
577
lib/mksh/dosys.cc
Normal file
|
@ -0,0 +1,577 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2015, Joyent, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dosys.cc
|
||||||
|
*
|
||||||
|
* Execute one commandline
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <sys/wait.h> /* WIFEXITED(status) */
|
||||||
|
#include <alloca.h> /* alloca() */
|
||||||
|
|
||||||
|
#include <stdio.h> /* errno */
|
||||||
|
#include <errno.h> /* errno */
|
||||||
|
#include <fcntl.h> /* open() */
|
||||||
|
#include <mksh/dosys.h>
|
||||||
|
#include <mksh/macro.h> /* getvar() */
|
||||||
|
#include <mksh/misc.h> /* getmem(), fatal_mksh(), errmsg() */
|
||||||
|
#include <sys/signal.h> /* SIG_DFL */
|
||||||
|
#include <sys/stat.h> /* open() */
|
||||||
|
#include <sys/wait.h> /* wait() */
|
||||||
|
#include <ulimit.h> /* ulimit() */
|
||||||
|
#include <unistd.h> /* close(), dup2() */
|
||||||
|
#include <stdlib.h> /* closefrom() */
|
||||||
|
#include <libintl.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Static variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
static Boolean exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error, pathpt vroot_path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for NFS bug. Sometimes, when running 'open' on a remote
|
||||||
|
* dmake server, it fails with "Stale NFS file handle" error.
|
||||||
|
* The second attempt seems to work.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
my_open(const char *path, int oflag, mode_t mode) {
|
||||||
|
int res = open(path, oflag, mode);
|
||||||
|
if (res < 0 && (errno == ESTALE || errno == EAGAIN)) {
|
||||||
|
/* Stale NFS file handle. Try again */
|
||||||
|
res = open(path, oflag, mode);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void
|
||||||
|
* redirect_io(char *stdout_file, char *stderr_file)
|
||||||
|
*
|
||||||
|
* Redirects stdout and stderr for a child mksh process.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
redirect_io(char *stdout_file, char *stderr_file)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
(void) closefrom(3);
|
||||||
|
if ((i = my_open(stdout_file,
|
||||||
|
O_WRONLY | O_CREAT | O_TRUNC | O_DSYNC,
|
||||||
|
S_IREAD | S_IWRITE)) < 0) {
|
||||||
|
fatal_mksh(gettext("Couldn't open standard out temp file `%s': %s"),
|
||||||
|
stdout_file,
|
||||||
|
errmsg(errno));
|
||||||
|
} else {
|
||||||
|
if (dup2(i, 1) == -1) {
|
||||||
|
fatal_mksh("*** Error: dup2(3, 1) failed: %s",
|
||||||
|
errmsg(errno));
|
||||||
|
}
|
||||||
|
close(i);
|
||||||
|
}
|
||||||
|
if (stderr_file == NULL) {
|
||||||
|
if (dup2(1, 2) == -1) {
|
||||||
|
fatal_mksh("*** Error: dup2(1, 2) failed: %s",
|
||||||
|
errmsg(errno));
|
||||||
|
}
|
||||||
|
} else if ((i = my_open(stderr_file,
|
||||||
|
O_WRONLY | O_CREAT | O_TRUNC | O_DSYNC,
|
||||||
|
S_IREAD | S_IWRITE)) < 0) {
|
||||||
|
fatal_mksh(gettext("Couldn't open standard error temp file `%s': %s"),
|
||||||
|
stderr_file,
|
||||||
|
errmsg(errno));
|
||||||
|
} else {
|
||||||
|
if (dup2(i, 2) == -1) {
|
||||||
|
fatal_mksh("*** Error: dup2(3, 2) failed: %s",
|
||||||
|
errmsg(errno));
|
||||||
|
}
|
||||||
|
close(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* doshell(command, ignore_error)
|
||||||
|
*
|
||||||
|
* Used to run command lines that include shell meta-characters.
|
||||||
|
* The make macro SHELL is supposed to contain a path to the shell.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The pid of the process we started
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* command The command to run
|
||||||
|
* ignore_error Should we abort on error?
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* filter_stderr If -X is on we redirect stderr
|
||||||
|
* shell_name The Name "SHELL", used to get the path to shell
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
doshell(wchar_t *command, register Boolean ignore_error, char *stdout_file, char *stderr_file, int nice_prio)
|
||||||
|
{
|
||||||
|
char *argv[6];
|
||||||
|
int argv_index = 0;
|
||||||
|
int cmd_argv_index;
|
||||||
|
int length;
|
||||||
|
char nice_prio_buf[MAXPATHLEN];
|
||||||
|
register Name shell = getvar(shell_name);
|
||||||
|
register char *shellname;
|
||||||
|
char *tmp_mbs_buffer;
|
||||||
|
|
||||||
|
|
||||||
|
if (IS_EQUAL(shell->string_mb, "")) {
|
||||||
|
shell = shell_name;
|
||||||
|
}
|
||||||
|
if ((shellname = strrchr(shell->string_mb, (int) slash_char)) == NULL) {
|
||||||
|
shellname = shell->string_mb;
|
||||||
|
} else {
|
||||||
|
shellname++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only prepend the /usr/bin/nice command to the original command
|
||||||
|
* if the nice priority, nice_prio, is NOT zero (0).
|
||||||
|
* Nice priorities can be a positive or a negative number.
|
||||||
|
*/
|
||||||
|
if (nice_prio != 0) {
|
||||||
|
argv[argv_index++] = (char *)"nice";
|
||||||
|
(void) sprintf(nice_prio_buf, "-%d", nice_prio);
|
||||||
|
argv[argv_index++] = strdup(nice_prio_buf);
|
||||||
|
}
|
||||||
|
argv[argv_index++] = shellname;
|
||||||
|
argv[argv_index++] = (char*)(ignore_error ? "-c" : "-ce");
|
||||||
|
if ((length = wcslen(command)) >= MAXPATHLEN) {
|
||||||
|
tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
|
||||||
|
(void) wcstombs(tmp_mbs_buffer, command, (length * MB_LEN_MAX) + 1);
|
||||||
|
cmd_argv_index = argv_index;
|
||||||
|
argv[argv_index++] = strdup(tmp_mbs_buffer);
|
||||||
|
retmem_mb(tmp_mbs_buffer);
|
||||||
|
} else {
|
||||||
|
WCSTOMBS(mbs_buffer, command);
|
||||||
|
cmd_argv_index = argv_index;
|
||||||
|
argv[argv_index++] = strdup(mbs_buffer);
|
||||||
|
}
|
||||||
|
argv[argv_index] = NULL;
|
||||||
|
(void) fflush(stdout);
|
||||||
|
if ((childPid = fork()) == 0) {
|
||||||
|
enable_interrupt((void (*) (int)) SIG_DFL);
|
||||||
|
#if 0
|
||||||
|
if (filter_stderr) {
|
||||||
|
redirect_stderr();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (nice_prio != 0) {
|
||||||
|
(void) execve("/usr/bin/nice", argv, environ);
|
||||||
|
fatal_mksh(gettext("Could not load `/usr/bin/nice': %s"),
|
||||||
|
errmsg(errno));
|
||||||
|
} else {
|
||||||
|
(void) execve(shell->string_mb, argv, environ);
|
||||||
|
fatal_mksh(gettext("Could not load Shell from `%s': %s"),
|
||||||
|
shell->string_mb,
|
||||||
|
errmsg(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (childPid == -1) {
|
||||||
|
fatal_mksh(gettext("fork failed: %s"),
|
||||||
|
errmsg(errno));
|
||||||
|
}
|
||||||
|
retmem_mb(argv[cmd_argv_index]);
|
||||||
|
return childPid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exec_vp(name, argv, envp, ignore_error)
|
||||||
|
*
|
||||||
|
* Like execve, but does path search.
|
||||||
|
* This starts command when make invokes it directly (without a shell).
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* Returns false if the exec failed
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* name The name of the command to run
|
||||||
|
* argv Arguments for the command
|
||||||
|
* envp The environment for it
|
||||||
|
* ignore_error Should we abort on error?
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* shell_name The Name "SHELL", used to get the path to shell
|
||||||
|
* vroot_path The path used by the vroot package
|
||||||
|
*/
|
||||||
|
static Boolean
|
||||||
|
exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error, pathpt vroot_path)
|
||||||
|
{
|
||||||
|
register Name shell = getvar(shell_name);
|
||||||
|
register char *shellname;
|
||||||
|
char *shargv[4];
|
||||||
|
Name tmp_shell;
|
||||||
|
|
||||||
|
if (IS_EQUAL(shell->string_mb, "")) {
|
||||||
|
shell = shell_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
(void) execve_vroot(name,
|
||||||
|
argv + 1,
|
||||||
|
envp,
|
||||||
|
vroot_path,
|
||||||
|
VROOT_DEFAULT);
|
||||||
|
switch (errno) {
|
||||||
|
case ENOEXEC:
|
||||||
|
case ENOENT:
|
||||||
|
/* That failed. Let the shell handle it */
|
||||||
|
shellname = strrchr(shell->string_mb, (int) slash_char);
|
||||||
|
if (shellname == NULL) {
|
||||||
|
shellname = shell->string_mb;
|
||||||
|
} else {
|
||||||
|
shellname++;
|
||||||
|
}
|
||||||
|
shargv[0] = shellname;
|
||||||
|
shargv[1] = (char*)(ignore_error ? "-c" : "-ce");
|
||||||
|
shargv[2] = argv[0];
|
||||||
|
shargv[3] = NULL;
|
||||||
|
tmp_shell = getvar(shell_name);
|
||||||
|
if (IS_EQUAL(tmp_shell->string_mb, "")) {
|
||||||
|
tmp_shell = shell_name;
|
||||||
|
}
|
||||||
|
(void) execve_vroot(tmp_shell->string_mb,
|
||||||
|
shargv,
|
||||||
|
envp,
|
||||||
|
vroot_path,
|
||||||
|
VROOT_DEFAULT);
|
||||||
|
return failed;
|
||||||
|
case ETXTBSY:
|
||||||
|
/*
|
||||||
|
* The program is busy (debugged?).
|
||||||
|
* Wait and then try again.
|
||||||
|
*/
|
||||||
|
(void) sleep((unsigned) i);
|
||||||
|
case EAGAIN:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* doexec(command, ignore_error)
|
||||||
|
*
|
||||||
|
* Will scan an argument string and split it into words
|
||||||
|
* thus building an argument list that can be passed to exec_ve()
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The pid of the process started here
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* command The command to run
|
||||||
|
* ignore_error Should we abort on error?
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* filter_stderr If -X is on we redirect stderr
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
doexec(register wchar_t *command, register Boolean ignore_error, char *stdout_file, char *stderr_file, pathpt vroot_path, int nice_prio)
|
||||||
|
{
|
||||||
|
int arg_count = 5;
|
||||||
|
char **argv;
|
||||||
|
int length;
|
||||||
|
char nice_prio_buf[MAXPATHLEN];
|
||||||
|
register char **p;
|
||||||
|
wchar_t *q;
|
||||||
|
register wchar_t *t;
|
||||||
|
char *tmp_mbs_buffer;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only prepend the /usr/bin/nice command to the original command
|
||||||
|
* if the nice priority, nice_prio, is NOT zero (0).
|
||||||
|
* Nice priorities can be a positive or a negative number.
|
||||||
|
*/
|
||||||
|
if (nice_prio != 0) {
|
||||||
|
arg_count += 2;
|
||||||
|
}
|
||||||
|
for (t = command; *t != (int) nul_char; t++) {
|
||||||
|
if (iswspace(*t)) {
|
||||||
|
arg_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argv = (char **)alloca(arg_count * (sizeof(char *)));
|
||||||
|
/*
|
||||||
|
* Reserve argv[0] for sh in case of exec_vp failure.
|
||||||
|
* Don't worry about prepending /usr/bin/nice command to argv[0].
|
||||||
|
* In fact, doing it may cause the sh command to fail!
|
||||||
|
*/
|
||||||
|
p = &argv[1];
|
||||||
|
if ((length = wcslen(command)) >= MAXPATHLEN) {
|
||||||
|
tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
|
||||||
|
(void) wcstombs(tmp_mbs_buffer, command, (length * MB_LEN_MAX) + 1);
|
||||||
|
argv[0] = strdup(tmp_mbs_buffer);
|
||||||
|
retmem_mb(tmp_mbs_buffer);
|
||||||
|
} else {
|
||||||
|
WCSTOMBS(mbs_buffer, command);
|
||||||
|
argv[0] = strdup(mbs_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nice_prio != 0) {
|
||||||
|
*p++ = strdup("/usr/bin/nice");
|
||||||
|
(void) sprintf(nice_prio_buf, "-%d", nice_prio);
|
||||||
|
*p++ = strdup(nice_prio_buf);
|
||||||
|
}
|
||||||
|
/* Build list of argument words. */
|
||||||
|
for (t = command; *t;) {
|
||||||
|
if (p >= &argv[arg_count]) {
|
||||||
|
/* This should never happen, right? */
|
||||||
|
WCSTOMBS(mbs_buffer, command);
|
||||||
|
fatal_mksh(gettext("Command `%s' has more than %d arguments"),
|
||||||
|
mbs_buffer,
|
||||||
|
arg_count);
|
||||||
|
}
|
||||||
|
q = t;
|
||||||
|
while (!iswspace(*t) && (*t != (int) nul_char)) {
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
if (*t) {
|
||||||
|
for (*t++ = (int) nul_char; iswspace(*t); t++);
|
||||||
|
}
|
||||||
|
if ((length = wcslen(q)) >= MAXPATHLEN) {
|
||||||
|
tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
|
||||||
|
(void) wcstombs(tmp_mbs_buffer, q, (length * MB_LEN_MAX) + 1);
|
||||||
|
*p++ = strdup(tmp_mbs_buffer);
|
||||||
|
retmem_mb(tmp_mbs_buffer);
|
||||||
|
} else {
|
||||||
|
WCSTOMBS(mbs_buffer, q);
|
||||||
|
*p++ = strdup(mbs_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p = NULL;
|
||||||
|
|
||||||
|
/* Then exec the command with that argument list. */
|
||||||
|
(void) fflush(stdout);
|
||||||
|
if ((childPid = fork()) == 0) {
|
||||||
|
enable_interrupt((void (*) (int)) SIG_DFL);
|
||||||
|
#if 0
|
||||||
|
if (filter_stderr) {
|
||||||
|
redirect_stderr();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
(void) exec_vp(argv[1], argv, environ, ignore_error, vroot_path);
|
||||||
|
fatal_mksh(gettext("Cannot load command `%s': %s"), argv[1], errmsg(errno));
|
||||||
|
}
|
||||||
|
if (childPid == -1) {
|
||||||
|
fatal_mksh(gettext("fork failed: %s"),
|
||||||
|
errmsg(errno));
|
||||||
|
}
|
||||||
|
for (int i = 0; argv[i] != NULL; i++) {
|
||||||
|
retmem_mb(argv[i]);
|
||||||
|
}
|
||||||
|
return childPid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* await(ignore_error, silent_error, target, command, running_pid)
|
||||||
|
*
|
||||||
|
* Wait for one child process and analyzes
|
||||||
|
* the returned status when the child process terminates.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* Returns true if commands ran OK
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* ignore_error Should we abort on error?
|
||||||
|
* silent_error Should error messages be suppressed for dmake?
|
||||||
|
* target The target we are building, for error msgs
|
||||||
|
* command The command we ran, for error msgs
|
||||||
|
* running_pid The pid of the process we are waiting for
|
||||||
|
*
|
||||||
|
* Static variables used:
|
||||||
|
* filter_file The fd for the filter file
|
||||||
|
* filter_file_name The name of the filter file
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* filter_stderr Set if -X is on
|
||||||
|
*/
|
||||||
|
Boolean
|
||||||
|
await(register Boolean ignore_error, register Boolean silent_error, Name target, wchar_t *command, pid_t running_pid, void *xdrs_p, int job_msg_id)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
char *buffer;
|
||||||
|
int core_dumped;
|
||||||
|
int exit_status;
|
||||||
|
FILE *outfp;
|
||||||
|
register pid_t pid;
|
||||||
|
struct stat stat_buff;
|
||||||
|
int termination_signal;
|
||||||
|
char tmp_buf[MAXPATHLEN];
|
||||||
|
|
||||||
|
while ((pid = wait(&status)) != running_pid) {
|
||||||
|
if (pid == -1) {
|
||||||
|
fatal_mksh(gettext("wait() failed: %s"), errmsg(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) fflush(stdout);
|
||||||
|
(void) fflush(stderr);
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
|
||||||
|
#ifdef PRINT_EXIT_STATUS
|
||||||
|
warning_mksh("I'm in await(), and status is 0.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PRINT_EXIT_STATUS
|
||||||
|
warning_mksh("I'm in await(), and status is *NOT* 0.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
exit_status = WEXITSTATUS(status);
|
||||||
|
|
||||||
|
#ifdef PRINT_EXIT_STATUS
|
||||||
|
warning_mksh("I'm in await(), and exit_status is %d.", exit_status);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
termination_signal = WTERMSIG(status);
|
||||||
|
core_dumped = WCOREDUMP(status);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the child returned an error, we now try to print a
|
||||||
|
* nice message about it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tmp_buf[0] = (int) nul_char;
|
||||||
|
if (!silent_error) {
|
||||||
|
if (exit_status != 0) {
|
||||||
|
(void) fprintf(stdout,
|
||||||
|
gettext("*** Error code %d"),
|
||||||
|
exit_status);
|
||||||
|
} else {
|
||||||
|
(void) fprintf(stdout,
|
||||||
|
gettext("*** Signal %d"),
|
||||||
|
termination_signal);
|
||||||
|
if (core_dumped) {
|
||||||
|
(void) fprintf(stdout,
|
||||||
|
gettext(" - core dumped"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ignore_error) {
|
||||||
|
(void) fprintf(stdout,
|
||||||
|
gettext(" (ignored)"));
|
||||||
|
}
|
||||||
|
(void) fprintf(stdout, "\n");
|
||||||
|
(void) fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PRINT_EXIT_STATUS
|
||||||
|
warning_mksh("I'm in await(), returning failed.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sh_command2string(command, destination)
|
||||||
|
*
|
||||||
|
* Run one sh command and capture the output from it.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* command The command to run
|
||||||
|
* destination Where to deposit the output from the command
|
||||||
|
*
|
||||||
|
* Static variables used:
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sh_command2string(register String command, register String destination)
|
||||||
|
{
|
||||||
|
register FILE *fd;
|
||||||
|
register int chr;
|
||||||
|
int status;
|
||||||
|
Boolean command_generated_output = false;
|
||||||
|
|
||||||
|
command->text.p = (int) nul_char;
|
||||||
|
WCSTOMBS(mbs_buffer, command->buffer.start);
|
||||||
|
if ((fd = popen(mbs_buffer, "r")) == NULL) {
|
||||||
|
WCSTOMBS(mbs_buffer, command->buffer.start);
|
||||||
|
fatal_mksh(gettext("Could not run command `%s' for :sh transformation"),
|
||||||
|
mbs_buffer);
|
||||||
|
}
|
||||||
|
while ((chr = getc(fd)) != EOF) {
|
||||||
|
if (chr == (int) newline_char) {
|
||||||
|
chr = (int) space_char;
|
||||||
|
}
|
||||||
|
command_generated_output = true;
|
||||||
|
append_char(chr, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't want to keep the last LINE_FEED since usually
|
||||||
|
* the output of the 'sh:' command is used to evaluate
|
||||||
|
* some MACRO. ( /bin/sh and other shell add a line feed
|
||||||
|
* to the output so that the prompt appear in the right place.
|
||||||
|
* We don't need that
|
||||||
|
*/
|
||||||
|
if (command_generated_output){
|
||||||
|
if ( *(destination->text.p-1) == (int) space_char) {
|
||||||
|
* (-- destination->text.p) = '\0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If the command didn't generate any output,
|
||||||
|
* set the buffer to a null string.
|
||||||
|
*/
|
||||||
|
*(destination->text.p) = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
status = pclose(fd);
|
||||||
|
if (status != 0) {
|
||||||
|
WCSTOMBS(mbs_buffer, command->buffer.start);
|
||||||
|
fatal_mksh(gettext("The command `%s' returned status `%d'"),
|
||||||
|
mbs_buffer,
|
||||||
|
WEXITSTATUS(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
128
lib/mksh/globals.cc
Normal file
128
lib/mksh/globals.cc
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* globals.cc
|
||||||
|
*
|
||||||
|
* This declares all global variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <mksh/globals.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defined macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs & structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global variables
|
||||||
|
*/
|
||||||
|
char char_semantics[CHAR_SEMANTICS_ENTRIES];
|
||||||
|
wchar_t char_semantics_char[] = {
|
||||||
|
ampersand_char,
|
||||||
|
asterisk_char,
|
||||||
|
at_char,
|
||||||
|
backquote_char,
|
||||||
|
backslash_char,
|
||||||
|
bar_char,
|
||||||
|
bracketleft_char,
|
||||||
|
bracketright_char,
|
||||||
|
colon_char,
|
||||||
|
dollar_char,
|
||||||
|
doublequote_char,
|
||||||
|
equal_char,
|
||||||
|
exclam_char,
|
||||||
|
greater_char,
|
||||||
|
hat_char,
|
||||||
|
hyphen_char,
|
||||||
|
less_char,
|
||||||
|
newline_char,
|
||||||
|
numbersign_char,
|
||||||
|
parenleft_char,
|
||||||
|
parenright_char,
|
||||||
|
percent_char,
|
||||||
|
plus_char,
|
||||||
|
question_char,
|
||||||
|
quote_char,
|
||||||
|
semicolon_char,
|
||||||
|
nul_char
|
||||||
|
};
|
||||||
|
Macro_list cond_macro_list;
|
||||||
|
Boolean conditional_macro_used;
|
||||||
|
Boolean do_not_exec_rule; /* `-n' */
|
||||||
|
Boolean dollarget_seen;
|
||||||
|
Boolean dollarless_flag;
|
||||||
|
Name dollarless_value;
|
||||||
|
Envvar envvar;
|
||||||
|
#ifdef lint
|
||||||
|
char **environ;
|
||||||
|
#endif
|
||||||
|
int exit_status;
|
||||||
|
wchar_t *file_being_read;
|
||||||
|
/* Variable gnu_style=true if env. var. SUN_MAKE_COMPAT_MODE=GNU (RFE 4866328) */
|
||||||
|
Boolean gnu_style = false;
|
||||||
|
Name_set hashtab;
|
||||||
|
Name host_arch;
|
||||||
|
Name host_mach;
|
||||||
|
int line_number;
|
||||||
|
char *make_state_lockfile;
|
||||||
|
Boolean make_word_mentioned;
|
||||||
|
Makefile_type makefile_type = reading_nothing;
|
||||||
|
char mbs_buffer[(MAXPATHLEN * MB_LEN_MAX)];
|
||||||
|
Name path_name;
|
||||||
|
Boolean posix = true;
|
||||||
|
Name hat;
|
||||||
|
Name query;
|
||||||
|
Boolean query_mentioned;
|
||||||
|
Boolean reading_environment;
|
||||||
|
Name shell_name;
|
||||||
|
Boolean svr4 = false;
|
||||||
|
Name target_arch;
|
||||||
|
Name target_mach;
|
||||||
|
Boolean tilde_rule;
|
||||||
|
Name virtual_root;
|
||||||
|
Boolean vpath_defined;
|
||||||
|
Name vpath_name;
|
||||||
|
wchar_t wcs_buffer[MAXPATHLEN];
|
||||||
|
Boolean working_on_targets;
|
||||||
|
Boolean out_err_same;
|
||||||
|
pid_t childPid = -1; // This variable is used for killing child's process
|
||||||
|
// Such as qrsh, running command, etc.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* timestamps defined in defs.h
|
||||||
|
*/
|
||||||
|
const timestruc_t file_no_time = { -1, 0 };
|
||||||
|
const timestruc_t file_doesnt_exist = { 0, 0 };
|
||||||
|
const timestruc_t file_is_dir = { 1, 0 };
|
||||||
|
const timestruc_t file_min_time = { 2, 0 };
|
||||||
|
const timestruc_t file_max_time = { INT_MAX, 0 };
|
91
lib/mksh/i18n.cc
Normal file
91
lib/mksh/i18n.cc
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* i18n.cc
|
||||||
|
*
|
||||||
|
* Deal with internationalization conversions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <mksh/i18n.h>
|
||||||
|
#include <mksh/misc.h> /* setup_char_semantics() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_char_semantics_value(ch)
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The character semantics of ch.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* ch character we want semantics for.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char
|
||||||
|
get_char_semantics_value(wchar_t ch)
|
||||||
|
{
|
||||||
|
static Boolean char_semantics_setup;
|
||||||
|
|
||||||
|
if (!char_semantics_setup) {
|
||||||
|
setup_char_semantics();
|
||||||
|
char_semantics_setup = true;
|
||||||
|
}
|
||||||
|
return char_semantics[get_char_semantics_entry(ch)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_char_semantics_entry(ch)
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The slot number in the array for special make chars,
|
||||||
|
* else the slot number of the last array entry.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* ch The wide character
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* char_semantics_char[] array of special wchar_t chars
|
||||||
|
* "&*@`\\|[]:$=!>-\n#()%?;^<'\""
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
get_char_semantics_entry(wchar_t ch)
|
||||||
|
{
|
||||||
|
wchar_t *char_sem_char;
|
||||||
|
|
||||||
|
char_sem_char = (wchar_t *) wcschr(char_semantics_char, ch);
|
||||||
|
if (char_sem_char == NULL) {
|
||||||
|
/*
|
||||||
|
* Return the integer entry for the last slot,
|
||||||
|
* whose content is empty.
|
||||||
|
*/
|
||||||
|
return (CHAR_SEMANTICS_ENTRIES - 1);
|
||||||
|
} else {
|
||||||
|
return (char_sem_char - char_semantics_char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1335
lib/mksh/macro.cc
Normal file
1335
lib/mksh/macro.cc
Normal file
File diff suppressed because it is too large
Load diff
1113
lib/mksh/misc.cc
Normal file
1113
lib/mksh/misc.cc
Normal file
File diff suppressed because it is too large
Load diff
131
lib/mksh/mksh.cc
Normal file
131
lib/mksh/mksh.cc
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mksh.cc
|
||||||
|
*
|
||||||
|
* Execute the command(s) of one Make or DMake rule
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <mksh/dosys.h> /* redirect_io() */
|
||||||
|
#include <mksh/misc.h> /* retmem() */
|
||||||
|
#include <mksh/mksh.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for NFS bug. Sometimes, when running 'chdir' on a remote
|
||||||
|
* dmake server, it fails with "Stale NFS file handle" error.
|
||||||
|
* The second attempt seems to work.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
my_chdir(char * dir) {
|
||||||
|
int res = chdir(dir);
|
||||||
|
if (res != 0 && (errno == ESTALE || errno == EAGAIN)) {
|
||||||
|
/* Stale NFS file handle. Try again */
|
||||||
|
res = chdir(dir);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File table of contents
|
||||||
|
*/
|
||||||
|
static void change_sunpro_dependencies_value(char *oldpath, char *newpath);
|
||||||
|
static void init_mksh_globals(char *shell);
|
||||||
|
static void set_env_vars(char *env_list[]);
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_env_vars(char *env_list[])
|
||||||
|
{
|
||||||
|
char **env_list_p;
|
||||||
|
|
||||||
|
for (env_list_p = env_list;
|
||||||
|
*env_list_p != (char *) NULL;
|
||||||
|
env_list_p++) {
|
||||||
|
putenv(*env_list_p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_mksh_globals(char *shell)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
MBSTOWCS(wcs_buffer, "SHELL");
|
||||||
|
shell_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
MBSTOWCS(wcs_buffer, shell);
|
||||||
|
(void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false);
|
||||||
|
*/
|
||||||
|
char * dmake_shell;
|
||||||
|
if ((dmake_shell = getenv("DMAKE_SHELL")) == NULL) {
|
||||||
|
dmake_shell = shell;
|
||||||
|
}
|
||||||
|
MBSTOWCS(wcs_buffer, dmake_shell);
|
||||||
|
shell_name = GETNAME(wcs_buffer, FIND_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change the pathname in the value of the SUNPRO_DEPENDENCIES env variable
|
||||||
|
* from oldpath to newpath.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
change_sunpro_dependencies_value(char *oldpath, char *newpath)
|
||||||
|
{
|
||||||
|
char buf[MAXPATHLEN];
|
||||||
|
static char *env;
|
||||||
|
int length;
|
||||||
|
int oldpathlen;
|
||||||
|
char *sp_dep_value;
|
||||||
|
|
||||||
|
/* check if SUNPRO_DEPENDENCIES is set in the environment */
|
||||||
|
if ((sp_dep_value = getenv("SUNPRO_DEPENDENCIES")) != NULL) {
|
||||||
|
oldpathlen = strlen(oldpath);
|
||||||
|
/* check if oldpath is indeed in the value of SUNPRO_DEPENDENCIES */
|
||||||
|
if (strncmp(oldpath, sp_dep_value, oldpathlen) == 0) {
|
||||||
|
(void) sprintf(buf,
|
||||||
|
"%s%s",
|
||||||
|
newpath,
|
||||||
|
sp_dep_value + oldpathlen);
|
||||||
|
length = 2 +
|
||||||
|
strlen("SUNPRO_DEPENDENCIES") +
|
||||||
|
strlen(buf);
|
||||||
|
env = getmem(length);
|
||||||
|
(void) sprintf(env,
|
||||||
|
"%s=%s",
|
||||||
|
"SUNPRO_DEPENDENCIES",
|
||||||
|
buf);
|
||||||
|
(void) putenv(env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
170
lib/mksh/read.cc
Normal file
170
lib/mksh/read.cc
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* read.c
|
||||||
|
*
|
||||||
|
* This file contains the makefile reader.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included files
|
||||||
|
*/
|
||||||
|
#include <mksh/misc.h> /* retmem() */
|
||||||
|
#include <mksh/read.h>
|
||||||
|
#include <sys/uio.h> /* read() */
|
||||||
|
#include <unistd.h> /* close(), unlink(), read() */
|
||||||
|
#include <libintl.h>
|
||||||
|
|
||||||
|
#define STRING_LEN_TO_CONVERT (8*1024)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_next_block_fn(source)
|
||||||
|
*
|
||||||
|
* Will get the next block of text to read either
|
||||||
|
* by popping one source bVSIZEOFlock of the stack of Sources
|
||||||
|
* or by reading some more from the makefile.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* The new source block to read from
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* source The old source block
|
||||||
|
*
|
||||||
|
* Global variables used:
|
||||||
|
* file_being_read The name of the current file, error msg
|
||||||
|
*/
|
||||||
|
Boolean make_state_locked;
|
||||||
|
Source
|
||||||
|
get_next_block_fn(register Source source)
|
||||||
|
{
|
||||||
|
register off_t to_read;
|
||||||
|
register int length;
|
||||||
|
register size_t num_wc_chars;
|
||||||
|
char ch_save;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
if (source == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((source->fd < 0) ||
|
||||||
|
((source->bytes_left_in_file <= 0) &&
|
||||||
|
(source->inp_buf_ptr >= source->inp_buf_end))) {
|
||||||
|
/* We can't read from the makefile, so pop the source block */
|
||||||
|
if (source->fd > 2) {
|
||||||
|
(void) close(source->fd);
|
||||||
|
if (make_state_lockfile != NULL) {
|
||||||
|
(void) unlink(make_state_lockfile);
|
||||||
|
retmem_mb(make_state_lockfile);
|
||||||
|
make_state_lockfile = NULL;
|
||||||
|
make_state_locked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (source->string.free_after_use &&
|
||||||
|
(source->string.buffer.start != NULL)) {
|
||||||
|
retmem(source->string.buffer.start);
|
||||||
|
source->string.buffer.start = NULL;
|
||||||
|
}
|
||||||
|
if (source->inp_buf != NULL) {
|
||||||
|
retmem_mb(source->inp_buf);
|
||||||
|
source->inp_buf = NULL;
|
||||||
|
}
|
||||||
|
source = source->previous;
|
||||||
|
if (source != NULL) {
|
||||||
|
source->error_converting = false;
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
if (source->bytes_left_in_file > 0) {
|
||||||
|
/*
|
||||||
|
* Read the whole makefile.
|
||||||
|
* Hopefully the kernel managed to prefetch the stuff.
|
||||||
|
*/
|
||||||
|
to_read = source->bytes_left_in_file;
|
||||||
|
source->inp_buf_ptr = source->inp_buf = getmem(to_read + 1);
|
||||||
|
source->inp_buf_end = source->inp_buf + to_read;
|
||||||
|
length = read(source->fd, source->inp_buf, (unsigned int) to_read);
|
||||||
|
if (length != to_read) {
|
||||||
|
WCSTOMBS(mbs_buffer, file_being_read);
|
||||||
|
if (length == 0) {
|
||||||
|
fatal_mksh(gettext("Error reading `%s': Premature EOF"),
|
||||||
|
mbs_buffer);
|
||||||
|
} else {
|
||||||
|
fatal_mksh(gettext("Error reading `%s': %s"),
|
||||||
|
mbs_buffer,
|
||||||
|
errmsg(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*source->inp_buf_end = nul_char;
|
||||||
|
source->bytes_left_in_file = 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Try to convert the next piece.
|
||||||
|
*/
|
||||||
|
ptr = source->inp_buf_ptr + STRING_LEN_TO_CONVERT;
|
||||||
|
if (ptr > source->inp_buf_end) {
|
||||||
|
ptr = source->inp_buf_end;
|
||||||
|
}
|
||||||
|
for (num_wc_chars = 0; ptr > source->inp_buf_ptr; ptr--) {
|
||||||
|
ch_save = *ptr;
|
||||||
|
*ptr = nul_char;
|
||||||
|
num_wc_chars = mbstowcs(source->string.text.end,
|
||||||
|
source->inp_buf_ptr,
|
||||||
|
STRING_LEN_TO_CONVERT);
|
||||||
|
*ptr = ch_save;
|
||||||
|
if (num_wc_chars != (size_t)-1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int) num_wc_chars == (size_t)-1) {
|
||||||
|
source->error_converting = true;
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
source->error_converting = false;
|
||||||
|
source->inp_buf_ptr = ptr;
|
||||||
|
source->string.text.end += num_wc_chars;
|
||||||
|
*source->string.text.end = 0;
|
||||||
|
|
||||||
|
if (source->inp_buf_ptr >= source->inp_buf_end) {
|
||||||
|
if (*(source->string.text.end - 1) != (int) newline_char) {
|
||||||
|
WCSTOMBS(mbs_buffer, file_being_read);
|
||||||
|
warning_mksh(gettext("newline is not last character in file %s"),
|
||||||
|
mbs_buffer);
|
||||||
|
*source->string.text.end++ = (int) newline_char;
|
||||||
|
*source->string.text.end = (int) nul_char;
|
||||||
|
*source->string.buffer.end++;
|
||||||
|
}
|
||||||
|
if (source->inp_buf != NULL) {
|
||||||
|
retmem_mb(source->inp_buf);
|
||||||
|
source->inp_buf = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
42
lib/vroot/access.cc
Normal file
42
lib/vroot/access.cc
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int access_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= access(path, vroot_args.access.mode);
|
||||||
|
return((vroot_result == 0) || (errno != ENOENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
int access_vroot(char *path, int mode, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.access.mode= mode;
|
||||||
|
translate_with_thunk(path, access_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
31
lib/vroot/args.cc
Normal file
31
lib/vroot/args.cc
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
union Args vroot_args;
|
||||||
|
int vroot_result;
|
41
lib/vroot/chdir.cc
Normal file
41
lib/vroot/chdir.cc
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int chdir_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= chdir(path);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int chdir_vroot(char *path, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
translate_with_thunk(path, chdir_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
46
lib/vroot/chmod.cc
Normal file
46
lib/vroot/chmod.cc
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
extern int chmod(const char *path, mode_t mode);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int chmod_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= chmod(path, vroot_args.chmod.mode);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int chmod_vroot(char *path, int mode, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.chmod.mode= mode;
|
||||||
|
translate_with_thunk(path, chmod_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
47
lib/vroot/chown.cc
Normal file
47
lib/vroot/chown.cc
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
extern int chown(const char *path, uid_t owner, gid_t group);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int chown_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= chown(path, vroot_args.chown.user, vroot_args.chown.group);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int chown_vroot(char *path, int user, int group, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.chown.user= user;
|
||||||
|
vroot_args.chown.group= group;
|
||||||
|
translate_with_thunk(path, chown_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
44
lib/vroot/chroot.cc
Normal file
44
lib/vroot/chroot.cc
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern int chroot(const char *path);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int chroot_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= chroot(path);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int chroot_vroot(char *path, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
translate_with_thunk(path, chroot_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
47
lib/vroot/creat.cc
Normal file
47
lib/vroot/creat.cc
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
extern int creat(const char *path, mode_t mode);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int creat_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= creat(path, vroot_args.creat.mode);
|
||||||
|
return(vroot_result >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int creat_vroot(char *path, int mode, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.creat.mode= mode;
|
||||||
|
translate_with_thunk(path, creat_thunk, vroot_path, vroot_vroot, rw_write);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
50
lib/vroot/execve.cc
Normal file
50
lib/vroot/execve.cc
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern int execve (const char *path, char *const argv[], char *const envp[]);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int execve_thunk(char *path)
|
||||||
|
{
|
||||||
|
execve(path, vroot_args.execve.argv, vroot_args.execve.environ);
|
||||||
|
switch (errno) {
|
||||||
|
case ETXTBSY:
|
||||||
|
case ENOEXEC: return 1;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int execve_vroot(char *path, char **argv, char **environ, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.execve.argv= argv;
|
||||||
|
vroot_args.execve.environ= environ;
|
||||||
|
translate_with_thunk(path, execve_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(-1);
|
||||||
|
}
|
175
lib/vroot/lock.cc
Normal file
175
lib/vroot/lock.cc
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h> /* errno */
|
||||||
|
#include <libintl.h>
|
||||||
|
|
||||||
|
extern char *sys_errlist[];
|
||||||
|
extern int sys_nerr;
|
||||||
|
|
||||||
|
static void file_lock_error(char *msg, char *file, char *str, int arg1, int arg2);
|
||||||
|
|
||||||
|
#define BLOCK_INTERUPTS sigfillset(&newset) ; \
|
||||||
|
sigprocmask(SIG_SETMASK, &newset, &oldset)
|
||||||
|
|
||||||
|
#define UNBLOCK_INTERUPTS \
|
||||||
|
sigprocmask(SIG_SETMASK, &oldset, &newset)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This code stolen from the NSE library and changed to not depend
|
||||||
|
* upon any NSE routines or header files.
|
||||||
|
*
|
||||||
|
* Simple file locking.
|
||||||
|
* Create a symlink to a file. The "test and set" will be
|
||||||
|
* atomic as creating the symlink provides both functions.
|
||||||
|
*
|
||||||
|
* The timeout value specifies how long to wait for stale locks
|
||||||
|
* to disappear. If the lock is more than 'timeout' seconds old
|
||||||
|
* then it is ok to blow it away. This part has a small window
|
||||||
|
* of vunerability as the operations of testing the time,
|
||||||
|
* removing the lock and creating a new one are not atomic.
|
||||||
|
* It would be possible for two processes to both decide to blow
|
||||||
|
* away the lock and then have process A remove the lock and establish
|
||||||
|
* its own, and then then have process B remove the lock which accidentily
|
||||||
|
* removes A's lock rather than the stale one.
|
||||||
|
*
|
||||||
|
* A further complication is with the NFS. If the file in question is
|
||||||
|
* being served by an NFS server, then its time is set by that server.
|
||||||
|
* We can not use the time on the client machine to check for a stale
|
||||||
|
* lock. Therefore, a temp file on the server is created to get
|
||||||
|
* the servers current time.
|
||||||
|
*
|
||||||
|
* Returns an error message. NULL return means the lock was obtained.
|
||||||
|
*
|
||||||
|
* 12/6/91 Added the parameter "file_locked". Before this parameter
|
||||||
|
* was added, the calling procedure would have to wait for file_lock()
|
||||||
|
* to return before it sets the flag. If the user interrupted "make"
|
||||||
|
* between the time the lock was acquired and the time file_lock()
|
||||||
|
* returns, make wouldn't know that the file has been locked, and therefore
|
||||||
|
* it wouldn' remove the lock. Setting the flag right after locking the file
|
||||||
|
* makes this window much smaller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
file_lock(char *name, char *lockname, int *file_locked, int timeout)
|
||||||
|
{
|
||||||
|
int counter = 0;
|
||||||
|
static char msg[MAXPATHLEN+1];
|
||||||
|
int printed_warning = 0;
|
||||||
|
int r;
|
||||||
|
struct stat statb;
|
||||||
|
sigset_t newset;
|
||||||
|
sigset_t oldset;
|
||||||
|
|
||||||
|
*file_locked = 0;
|
||||||
|
if (timeout <= 0) {
|
||||||
|
timeout = 120;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
BLOCK_INTERUPTS;
|
||||||
|
r = symlink(name, lockname);
|
||||||
|
if (r == 0) {
|
||||||
|
*file_locked = 1;
|
||||||
|
UNBLOCK_INTERUPTS;
|
||||||
|
return 0; /* success */
|
||||||
|
}
|
||||||
|
UNBLOCK_INTERUPTS;
|
||||||
|
|
||||||
|
if (errno != EEXIST) {
|
||||||
|
file_lock_error(msg, name, (char *)"symlink(%s, %s)",
|
||||||
|
(int) name, (int) lockname);
|
||||||
|
fprintf(stderr, "%s", msg);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter = 0;
|
||||||
|
for (;;) {
|
||||||
|
sleep(1);
|
||||||
|
r = lstat(lockname, &statb);
|
||||||
|
if (r == -1) {
|
||||||
|
/*
|
||||||
|
* The lock must have just gone away - try
|
||||||
|
* again.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((counter > 5) && (!printed_warning)) {
|
||||||
|
/* Print waiting message after 5 secs */
|
||||||
|
(void) getcwd(msg, MAXPATHLEN);
|
||||||
|
fprintf(stderr,
|
||||||
|
gettext("file_lock: file %s is already locked.\n"),
|
||||||
|
name);
|
||||||
|
fprintf(stderr,
|
||||||
|
gettext("file_lock: will periodically check the lockfile %s for two minutes.\n"),
|
||||||
|
lockname);
|
||||||
|
fprintf(stderr,
|
||||||
|
gettext("Current working directory %s\n"),
|
||||||
|
msg);
|
||||||
|
|
||||||
|
printed_warning = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++counter > timeout ) {
|
||||||
|
/*
|
||||||
|
* Waited enough - return an error..
|
||||||
|
*/
|
||||||
|
return EEXIST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Format a message telling why the lock could not be created.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
file_lock_error(char *msg, char *file, char *str, int arg1, int arg2)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
sprintf(msg, gettext("Could not lock file `%s'; "), file);
|
||||||
|
len = strlen(msg);
|
||||||
|
sprintf(&msg[len], str, arg1, arg2);
|
||||||
|
strcat(msg, gettext(" failed - "));
|
||||||
|
if (errno < sys_nerr) {
|
||||||
|
strcat(msg, strerror(errno));
|
||||||
|
} else {
|
||||||
|
len = strlen(msg);
|
||||||
|
sprintf(&msg[len], "errno %d", errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
46
lib/vroot/lstat.cc
Normal file
46
lib/vroot/lstat.cc
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1998 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
extern int lstat(const char *path, struct stat *buf);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int lstat_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= lstat(path, vroot_args.lstat.buffer);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lstat_vroot(char *path, struct stat *buffer, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.lstat.buffer= buffer;
|
||||||
|
translate_with_thunk(path, lstat_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
46
lib/vroot/mkdir.cc
Normal file
46
lib/vroot/mkdir.cc
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
extern int mkdir(const char *path, mode_t mode);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int mkdir_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= mkdir(path, vroot_args.mkdir.mode);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkdir_vroot(char *path, int mode, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.mkdir.mode= mode;
|
||||||
|
translate_with_thunk(path, mkdir_thunk, vroot_path, vroot_vroot, rw_write);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
47
lib/vroot/mount.cc
Normal file
47
lib/vroot/mount.cc
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1995 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
|
||||||
|
extern int mount(const char *spec, const char *dir, int mflag, ...);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int mount_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= mount(path, vroot_args.mount.name, vroot_args.mount.mode);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mount_vroot(char *target, char *name, int mode, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.mount.name= name;
|
||||||
|
vroot_args.mount.mode= mode;
|
||||||
|
translate_with_thunk(target, mount_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
49
lib/vroot/open.cc
Normal file
49
lib/vroot/open.cc
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
extern int open(const char *path, int oflag, ...);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int open_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= open(path, vroot_args.open.flags, vroot_args.open.mode);
|
||||||
|
return(vroot_result >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int open_vroot(char *path, int flags, int mode, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.open.flags= flags;
|
||||||
|
vroot_args.open.mode= mode;
|
||||||
|
translate_with_thunk(path, open_thunk, vroot_path, vroot_vroot,
|
||||||
|
((flags & (O_CREAT|O_APPEND)) != 0) ? rw_write : rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
46
lib/vroot/readlink.cc
Normal file
46
lib/vroot/readlink.cc
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern int readlink(const char *path, void *buf, size_t bufsiz);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int readlink_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= readlink(path, vroot_args.readlink.buffer, vroot_args.readlink.buffer_size);
|
||||||
|
return(vroot_result >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int readlink_vroot(char *path, char *buffer, int buffer_size, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.readlink.buffer= buffer;
|
||||||
|
vroot_args.readlink.buffer_size= buffer_size;
|
||||||
|
translate_with_thunk(path, readlink_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
333
lib/vroot/report.cc
Normal file
333
lib/vroot/report.cc
Normal file
|
@ -0,0 +1,333 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
|
||||||
|
#include <vroot/report.h>
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <mk/defs.h> /* for tmpdir */
|
||||||
|
|
||||||
|
static FILE *report_file;
|
||||||
|
static FILE *command_output_fp;
|
||||||
|
static char *target_being_reported_for;
|
||||||
|
static char *search_dir;
|
||||||
|
static char command_output_tmpfile[30];
|
||||||
|
static int is_path = 0;
|
||||||
|
static char sfile[MAXPATHLEN];
|
||||||
|
extern "C" {
|
||||||
|
static void (*warning_ptr) (char *, ...) = (void (*) (char *, ...)) NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *
|
||||||
|
get_report_file(void)
|
||||||
|
{
|
||||||
|
return(report_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
get_target_being_reported_for(void)
|
||||||
|
{
|
||||||
|
return(target_being_reported_for);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
static void
|
||||||
|
close_report_file(void)
|
||||||
|
{
|
||||||
|
(void)fputs("\n", report_file);
|
||||||
|
(void)fclose(report_file);
|
||||||
|
}
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
static void
|
||||||
|
clean_up(FILE *nse_depinfo_fp, FILE *merge_fp, char *nse_depinfo_file, char *merge_file, int unlinkf)
|
||||||
|
{
|
||||||
|
fclose(nse_depinfo_fp);
|
||||||
|
fclose(merge_fp);
|
||||||
|
fclose(command_output_fp);
|
||||||
|
unlink(command_output_tmpfile);
|
||||||
|
if (unlinkf)
|
||||||
|
unlink(merge_file);
|
||||||
|
else
|
||||||
|
rename(merge_file, nse_depinfo_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the file, if necessary. We don't want to rewrite
|
||||||
|
* the file if we don't have to because we don't want the time of the file
|
||||||
|
* to change in that case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
static void
|
||||||
|
close_file(void)
|
||||||
|
{
|
||||||
|
char line[MAXPATHLEN+2];
|
||||||
|
char buf[MAXPATHLEN+2];
|
||||||
|
FILE *nse_depinfo_fp;
|
||||||
|
FILE *merge_fp;
|
||||||
|
char nse_depinfo_file[MAXPATHLEN];
|
||||||
|
char merge_file[MAXPATHLEN];
|
||||||
|
char lock_file[MAXPATHLEN];
|
||||||
|
int err;
|
||||||
|
int len;
|
||||||
|
int changed = 0;
|
||||||
|
int file_locked;
|
||||||
|
|
||||||
|
fprintf(command_output_fp, "\n");
|
||||||
|
fclose(command_output_fp);
|
||||||
|
if ((command_output_fp = fopen(command_output_tmpfile, "r")) == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sprintf(nse_depinfo_file, "%s/%s", search_dir, NSE_DEPINFO);
|
||||||
|
sprintf(merge_file, "%s/.tmp%s.%d", search_dir, NSE_DEPINFO, getpid());
|
||||||
|
sprintf(lock_file, "%s/%s", search_dir, NSE_DEPINFO_LOCK);
|
||||||
|
err = file_lock(nse_depinfo_file, lock_file, &file_locked, 0);
|
||||||
|
if (err) {
|
||||||
|
if (warning_ptr != (void (*) (char *, ...)) NULL) {
|
||||||
|
(*warning_ptr)(gettext("Couldn't write to %s"), nse_depinfo_file);
|
||||||
|
}
|
||||||
|
unlink(command_output_tmpfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* If .nse_depinfo file doesn't exist */
|
||||||
|
if ((nse_depinfo_fp = fopen(nse_depinfo_file, "r+")) == NULL) {
|
||||||
|
if (is_path) {
|
||||||
|
if ((nse_depinfo_fp =
|
||||||
|
fopen(nse_depinfo_file, "w")) == NULL) {
|
||||||
|
fprintf(stderr, gettext("Cannot open `%s' for writing\n"),
|
||||||
|
nse_depinfo_file);
|
||||||
|
unlink(command_output_tmpfile);
|
||||||
|
|
||||||
|
unlink(lock_file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (fgets(line, MAXPATHLEN+2, command_output_fp)
|
||||||
|
!= NULL) {
|
||||||
|
fprintf(nse_depinfo_fp, "%s", line);
|
||||||
|
}
|
||||||
|
fclose(command_output_fp);
|
||||||
|
}
|
||||||
|
fclose(nse_depinfo_fp);
|
||||||
|
if (file_locked) {
|
||||||
|
unlink(lock_file);
|
||||||
|
}
|
||||||
|
unlink(command_output_tmpfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((merge_fp = fopen(merge_file, "w")) == NULL) {
|
||||||
|
fprintf(stderr, gettext("Cannot open %s for writing\n"), merge_file);
|
||||||
|
if (file_locked) {
|
||||||
|
unlink(lock_file);
|
||||||
|
}
|
||||||
|
unlink(command_output_tmpfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
len = strlen(sfile);
|
||||||
|
while (fgets(line, MAXPATHLEN+2, nse_depinfo_fp) != NULL) {
|
||||||
|
if (strncmp(line, sfile, len) == 0 && line[len] == ':') {
|
||||||
|
while (fgets(buf, MAXPATHLEN+2, command_output_fp)
|
||||||
|
!= NULL) {
|
||||||
|
if (is_path) {
|
||||||
|
fprintf(merge_fp, "%s", buf);
|
||||||
|
if (strcmp(line, buf)) {
|
||||||
|
/* changed */
|
||||||
|
changed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buf[strlen(buf)-1] == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed || !is_path) {
|
||||||
|
while (fgets(line, MAXPATHLEN, nse_depinfo_fp)
|
||||||
|
!= NULL) {
|
||||||
|
fputs(line, merge_fp);
|
||||||
|
}
|
||||||
|
clean_up(nse_depinfo_fp, merge_fp,
|
||||||
|
nse_depinfo_file, merge_file, 0);
|
||||||
|
} else {
|
||||||
|
clean_up(nse_depinfo_fp, merge_fp,
|
||||||
|
nse_depinfo_file, merge_file, 1);
|
||||||
|
}
|
||||||
|
if (file_locked) {
|
||||||
|
unlink(lock_file);
|
||||||
|
}
|
||||||
|
unlink(command_output_tmpfile);
|
||||||
|
return;
|
||||||
|
} /* entry found */
|
||||||
|
fputs(line, merge_fp);
|
||||||
|
}
|
||||||
|
/* Entry never found. Add it if there is a search path */
|
||||||
|
if (is_path) {
|
||||||
|
while (fgets(line, MAXPATHLEN+2, command_output_fp) != NULL) {
|
||||||
|
fprintf(nse_depinfo_fp, "%s", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clean_up(nse_depinfo_fp, merge_fp, nse_depinfo_file, merge_file, 1);
|
||||||
|
if (file_locked) {
|
||||||
|
unlink(lock_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
static void
|
||||||
|
report_dep(char *iflag, char *filename)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (command_output_fp == NULL) {
|
||||||
|
sprintf(command_output_tmpfile,
|
||||||
|
"%s/%s.%d.XXXXXX", tmpdir, NSE_DEPINFO, getpid());
|
||||||
|
int fd = mkstemp(command_output_tmpfile);
|
||||||
|
if ((fd < 0) || (command_output_fp = fdopen(fd, "w")) == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((search_dir = getenv("NSE_DEP")) == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
atexit(close_file);
|
||||||
|
strcpy(sfile, filename);
|
||||||
|
if (iflag == NULL || *iflag == '\0') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fprintf(command_output_fp, "%s:", sfile);
|
||||||
|
}
|
||||||
|
fprintf(command_output_fp, " ");
|
||||||
|
fprintf(command_output_fp, iflag);
|
||||||
|
if (iflag != NULL) {
|
||||||
|
is_path = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
report_libdep(char *lib, char *flag)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
char filename[MAXPATHLEN];
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if ((p= getenv(SUNPRO_DEPENDENCIES)) == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr = strchr(p, ' ');
|
||||||
|
if(ptr) {
|
||||||
|
sprintf(filename, "%s-%s", ptr+1, flag);
|
||||||
|
is_path = 1;
|
||||||
|
report_dep(lib, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
report_search_path(char *iflag)
|
||||||
|
{
|
||||||
|
char curdir[MAXPATHLEN];
|
||||||
|
char *sdir;
|
||||||
|
char *newiflag;
|
||||||
|
char filename[MAXPATHLEN];
|
||||||
|
char *p, *ptr;
|
||||||
|
|
||||||
|
if ((sdir = getenv("NSE_DEP")) == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((p= getenv(SUNPRO_DEPENDENCIES)) == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr = strchr(p, ' ');
|
||||||
|
if( ! ptr ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sprintf(filename, "%s-CPP", ptr+1);
|
||||||
|
getcwd(curdir, sizeof(curdir));
|
||||||
|
if (strcmp(curdir, sdir) != 0 && strlen(iflag) > 2 &&
|
||||||
|
iflag[2] != '/') {
|
||||||
|
/* Makefile must have had an "cd xx; cc ..." */
|
||||||
|
/* Modify the -I path to be relative to the cd */
|
||||||
|
newiflag = (char *)malloc(strlen(iflag) + strlen(curdir) + 2);
|
||||||
|
sprintf(newiflag, "-%c%s/%s", iflag[1], curdir, &iflag[2]);
|
||||||
|
report_dep(newiflag, filename);
|
||||||
|
} else {
|
||||||
|
report_dep(iflag, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
report_dependency(const char *name)
|
||||||
|
{
|
||||||
|
register char *filename;
|
||||||
|
char buffer[MAXPATHLEN+1];
|
||||||
|
register char *p;
|
||||||
|
register char *p2;
|
||||||
|
char nse_depinfo_file[MAXPATHLEN];
|
||||||
|
|
||||||
|
if (report_file == NULL) {
|
||||||
|
if ((filename= getenv(SUNPRO_DEPENDENCIES)) == NULL) {
|
||||||
|
report_file = (FILE *)-1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strlen(filename) == 0) {
|
||||||
|
report_file = (FILE *)-1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(void)strcpy(buffer, name);
|
||||||
|
name = buffer;
|
||||||
|
p = strchr(filename, ' ');
|
||||||
|
if(p) {
|
||||||
|
*p= 0;
|
||||||
|
} else {
|
||||||
|
report_file = (FILE *)-1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((report_file= fopen(filename, "a")) == NULL) {
|
||||||
|
if ((report_file= fopen(filename, "w")) == NULL) {
|
||||||
|
report_file= (FILE *)-1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
atexit(close_report_file);
|
||||||
|
if ((p2= strchr(p+1, ' ')) != NULL)
|
||||||
|
*p2= 0;
|
||||||
|
target_being_reported_for= (char *)malloc((unsigned)(strlen(p+1)+1));
|
||||||
|
(void)strcpy(target_being_reported_for, p+1);
|
||||||
|
(void)fputs(p+1, report_file);
|
||||||
|
(void)fputs(":", report_file);
|
||||||
|
*p= ' ';
|
||||||
|
if (p2 != NULL)
|
||||||
|
*p2= ' ';
|
||||||
|
}
|
||||||
|
if (report_file == (FILE *)-1)
|
||||||
|
return;
|
||||||
|
(void)fputs(name, report_file);
|
||||||
|
(void)fputs(" ", report_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
44
lib/vroot/rmdir.cc
Normal file
44
lib/vroot/rmdir.cc
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern int rmdir(const char *path);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int rmdir_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= rmdir(path);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmdir_vroot(char *path, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
translate_with_thunk(path, rmdir_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
61
lib/vroot/setenv.cc
Normal file
61
lib/vroot/setenv.cc
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1994 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
|
static short setenv_made_new_vector= 0;
|
||||||
|
|
||||||
|
char *setenv(char *name, char *value)
|
||||||
|
{ char *p= NULL, **q;
|
||||||
|
int length= 0, vl;
|
||||||
|
|
||||||
|
if ((p= getenv(name)) == NULL) { /* Allocate new vector */
|
||||||
|
for (q= environ; *q != NULL; q++, length++);
|
||||||
|
q= (char **)malloc((unsigned)(sizeof(char *)*(length+2)));
|
||||||
|
memcpy(((char *)q)+sizeof(char *), (char *)environ, sizeof(char *)*(length+1));
|
||||||
|
if (setenv_made_new_vector++)
|
||||||
|
free((char *)environ);
|
||||||
|
length= strlen(name);
|
||||||
|
environ= q;}
|
||||||
|
else { /* Find old slot */
|
||||||
|
length= strlen(name);
|
||||||
|
for (q= environ; *q != NULL; q++)
|
||||||
|
if (!strncmp(*q, name, length))
|
||||||
|
break;};
|
||||||
|
vl= strlen(value);
|
||||||
|
if (!p || (length+vl+1 > strlen(p)))
|
||||||
|
*q= p= (char *) malloc((unsigned)(length+vl+2));
|
||||||
|
else
|
||||||
|
p= *q;
|
||||||
|
(void)strcpy(p, name); p+= length;
|
||||||
|
*p++= '=';
|
||||||
|
(void)strcpy(p, value);
|
||||||
|
return(value);
|
||||||
|
}
|
46
lib/vroot/stat.cc
Normal file
46
lib/vroot/stat.cc
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1998 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
extern int stat(const char *path, struct stat *buf);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int stat_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= stat(path, vroot_args.stat.buffer);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int stat_vroot(char *path, struct stat *buffer, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.stat.buffer= buffer;
|
||||||
|
translate_with_thunk(path, stat_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
45
lib/vroot/truncate.cc
Normal file
45
lib/vroot/truncate.cc
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern int truncate(const char *path, off_t length);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int truncate_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= truncate(path, vroot_args.truncate.length);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int truncate_vroot(char *path, int length, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.truncate.length= length;
|
||||||
|
translate_with_thunk(path, truncate_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
44
lib/vroot/unlink.cc
Normal file
44
lib/vroot/unlink.cc
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern int unlink(const char *path);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int unlink_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= unlink(path);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int unlink_vroot(char *path, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
translate_with_thunk(path, unlink_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
46
lib/vroot/utimes.cc
Normal file
46
lib/vroot/utimes.cc
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
extern int utimes(char *file, struct timeval *tvp);
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
static int utimes_thunk(char *path)
|
||||||
|
{
|
||||||
|
vroot_result= utimes(path, vroot_args.utimes.time);
|
||||||
|
return(vroot_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int utimes_vroot(char *path, struct timeval *time, pathpt vroot_path, pathpt vroot_vroot)
|
||||||
|
{
|
||||||
|
vroot_args.utimes.time= time;
|
||||||
|
translate_with_thunk(path, utimes_thunk, vroot_path, vroot_vroot, rw_read);
|
||||||
|
return(vroot_result);
|
||||||
|
}
|
338
lib/vroot/vroot.cc
Normal file
338
lib/vroot/vroot.cc
Normal file
|
@ -0,0 +1,338 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <vroot/vroot.h>
|
||||||
|
#include <vroot/args.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short init;
|
||||||
|
pathpt vector;
|
||||||
|
const char *env_var;
|
||||||
|
} vroot_patht;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vroot_patht vroot;
|
||||||
|
vroot_patht path;
|
||||||
|
char full_path[MAXPATHLEN+1];
|
||||||
|
char *vroot_start;
|
||||||
|
char *path_start;
|
||||||
|
char *filename_start;
|
||||||
|
int scan_vroot_first;
|
||||||
|
int cpp_style_path;
|
||||||
|
} vroot_datat, *vroot_datapt;
|
||||||
|
|
||||||
|
static vroot_datat vroot_data= {
|
||||||
|
{ 0, NULL, "VIRTUAL_ROOT"},
|
||||||
|
{ 0, NULL, "PATH"},
|
||||||
|
"", NULL, NULL, NULL, 0, 1};
|
||||||
|
|
||||||
|
void
|
||||||
|
add_dir_to_path(const char *path, register pathpt *pointer, register int position)
|
||||||
|
{
|
||||||
|
register int size= 0;
|
||||||
|
register int length;
|
||||||
|
register char *name;
|
||||||
|
register pathcellpt p;
|
||||||
|
pathpt new_path;
|
||||||
|
|
||||||
|
if (*pointer != NULL) {
|
||||||
|
for (p= &((*pointer)[0]); p->path != NULL; p++, size++);
|
||||||
|
if (position < 0)
|
||||||
|
position= size;}
|
||||||
|
else
|
||||||
|
if (position < 0)
|
||||||
|
position= 0;
|
||||||
|
if (position >= size) {
|
||||||
|
new_path= (pathpt)calloc((unsigned)(position+2), sizeof(pathcellt));
|
||||||
|
if (*pointer != NULL) {
|
||||||
|
memcpy((char *)new_path,(char *)(*pointer), size*sizeof(pathcellt));
|
||||||
|
free((char *)(*pointer));};
|
||||||
|
*pointer= new_path;};
|
||||||
|
length= strlen(path);
|
||||||
|
name= (char *)malloc((unsigned)(length+1));
|
||||||
|
(void)strcpy(name, path);
|
||||||
|
if ((*pointer)[position].path != NULL)
|
||||||
|
free((*pointer)[position].path);
|
||||||
|
(*pointer)[position].path= name;
|
||||||
|
(*pointer)[position].length= length;
|
||||||
|
}
|
||||||
|
|
||||||
|
pathpt
|
||||||
|
parse_path_string(register char *string, register int remove_slash)
|
||||||
|
{
|
||||||
|
register char *p;
|
||||||
|
pathpt result= NULL;
|
||||||
|
|
||||||
|
if (string != NULL)
|
||||||
|
for (; 1; string= p+1) {
|
||||||
|
if (p= strchr(string, ':')) *p= 0;
|
||||||
|
if ((remove_slash == 1) && !strcmp(string, "/"))
|
||||||
|
add_dir_to_path("", &result, -1);
|
||||||
|
else
|
||||||
|
add_dir_to_path(string, &result, -1);
|
||||||
|
if (p) *p= ':';
|
||||||
|
else return(result);};
|
||||||
|
return((pathpt)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
get_vroot_name(void)
|
||||||
|
{
|
||||||
|
return(vroot_data.vroot.env_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
get_path_name(void)
|
||||||
|
{
|
||||||
|
return(vroot_data.path.env_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
flush_path_cache(void)
|
||||||
|
{
|
||||||
|
vroot_data.path.init= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
flush_vroot_cache(void)
|
||||||
|
{
|
||||||
|
vroot_data.vroot.init= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
scan_path_first(void)
|
||||||
|
{
|
||||||
|
vroot_data.scan_vroot_first= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
scan_vroot_first(void)
|
||||||
|
{
|
||||||
|
vroot_data.scan_vroot_first= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_path_style(int style)
|
||||||
|
{
|
||||||
|
vroot_data.cpp_style_path= style;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
get_vroot_path(register char **vroot, register char **path, register char **filename)
|
||||||
|
{
|
||||||
|
if (vroot != NULL) {
|
||||||
|
if ((*vroot= vroot_data.vroot_start) == NULL)
|
||||||
|
if ((*vroot= vroot_data.path_start) == NULL)
|
||||||
|
*vroot= vroot_data.filename_start;};
|
||||||
|
if (path != NULL) {
|
||||||
|
if ((*path= vroot_data.path_start) == NULL)
|
||||||
|
*path= vroot_data.filename_start;};
|
||||||
|
if (filename != NULL)
|
||||||
|
*filename= vroot_data.filename_start;
|
||||||
|
return(vroot_data.full_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
translate_with_thunk(register char *filename, int (*thunk) (char *), pathpt path_vector, pathpt vroot_vector, rwt rw)
|
||||||
|
{
|
||||||
|
register pathcellt *vp;
|
||||||
|
pathcellt *pp;
|
||||||
|
register pathcellt *pp1;
|
||||||
|
register char *p;
|
||||||
|
int flags[256];
|
||||||
|
|
||||||
|
/* Setup path to use */
|
||||||
|
if (rw == rw_write)
|
||||||
|
pp1= NULL; /* Do not use path when writing */
|
||||||
|
else {
|
||||||
|
if (path_vector == VROOT_DEFAULT) {
|
||||||
|
if (!vroot_data.path.init) {
|
||||||
|
vroot_data.path.init= 1;
|
||||||
|
vroot_data.path.vector= parse_path_string(getenv(vroot_data.path.env_var), 0);};
|
||||||
|
path_vector= vroot_data.path.vector;};
|
||||||
|
pp1= path_vector == NULL ? NULL : &(path_vector)[0];};
|
||||||
|
|
||||||
|
/* Setup vroot to use */
|
||||||
|
if (vroot_vector == VROOT_DEFAULT) {
|
||||||
|
if (!vroot_data.vroot.init) {
|
||||||
|
vroot_data.vroot.init= 1;
|
||||||
|
vroot_data.vroot.vector= parse_path_string(getenv(vroot_data.vroot.env_var), 1);};
|
||||||
|
vroot_vector= vroot_data.vroot.vector;};
|
||||||
|
vp= vroot_vector == NULL ? NULL : &(vroot_vector)[0];
|
||||||
|
|
||||||
|
/* Setup to remember pieces */
|
||||||
|
vroot_data.vroot_start= NULL;
|
||||||
|
vroot_data.path_start= NULL;
|
||||||
|
vroot_data.filename_start= NULL;
|
||||||
|
|
||||||
|
int flen = strlen(filename);
|
||||||
|
if(flen >= MAXPATHLEN) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((vp ?1:0) + (pp1 ? 2:0)) {
|
||||||
|
case 0: /* No path. No vroot. */
|
||||||
|
use_name:
|
||||||
|
(void)strcpy(vroot_data.full_path, filename);
|
||||||
|
vroot_data.filename_start= vroot_data.full_path;
|
||||||
|
(void)(*thunk)(vroot_data.full_path);
|
||||||
|
return;
|
||||||
|
case 1: /* No path. Vroot */
|
||||||
|
if (filename[0] != '/') goto use_name;
|
||||||
|
for (; vp->path != NULL; vp++) {
|
||||||
|
if((1 + flen + vp->length) >= MAXPATHLEN) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p= vroot_data.full_path;
|
||||||
|
(void)strcpy(vroot_data.vroot_start= p, vp->path);
|
||||||
|
p+= vp->length;
|
||||||
|
(void)strcpy(vroot_data.filename_start= p, filename);
|
||||||
|
if ((*thunk)(vroot_data.full_path)) return;};
|
||||||
|
(void)strcpy(vroot_data.full_path, filename);
|
||||||
|
return;
|
||||||
|
case 2: /* Path. No vroot. */
|
||||||
|
if (vroot_data.cpp_style_path) {
|
||||||
|
if (filename[0] == '/') goto use_name;
|
||||||
|
} else {
|
||||||
|
if (strchr(filename, '/') != NULL) goto use_name;
|
||||||
|
};
|
||||||
|
for (; pp1->path != NULL; pp1++) {
|
||||||
|
p= vroot_data.full_path;
|
||||||
|
if((1 + flen + pp1->length) >= MAXPATHLEN) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (vroot_data.cpp_style_path) {
|
||||||
|
(void)strcpy(vroot_data.path_start= p, pp1->path);
|
||||||
|
p+= pp1->length;
|
||||||
|
*p++= '/';
|
||||||
|
} else {
|
||||||
|
if (pp1->length != 0) {
|
||||||
|
(void)strcpy(vroot_data.path_start= p,
|
||||||
|
pp1->path);
|
||||||
|
p+= pp1->length;
|
||||||
|
*p++= '/';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
(void)strcpy(vroot_data.filename_start= p, filename);
|
||||||
|
if ((*thunk)(vroot_data.full_path)) return;};
|
||||||
|
(void)strcpy(vroot_data.full_path, filename);
|
||||||
|
return;
|
||||||
|
case 3: { /* Path. Vroot. */
|
||||||
|
int *rel_path, path_len= 1;
|
||||||
|
if (vroot_data.scan_vroot_first == 0) {
|
||||||
|
for (pp= pp1; pp->path != NULL; pp++) path_len++;
|
||||||
|
rel_path= flags;
|
||||||
|
for (path_len-= 2; path_len >= 0; path_len--) rel_path[path_len]= 0;
|
||||||
|
for (; vp->path != NULL; vp++)
|
||||||
|
for (pp= pp1, path_len= 0; pp->path != NULL; pp++, path_len++) {
|
||||||
|
int len = 0;
|
||||||
|
if (rel_path[path_len] == 1) continue;
|
||||||
|
if (pp->path[0] != '/') rel_path[path_len]= 1;
|
||||||
|
p= vroot_data.full_path;
|
||||||
|
if ((filename[0] == '/') || (pp->path[0] == '/')) {
|
||||||
|
if(vp->length >= MAXPATHLEN) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(void)strcpy(vroot_data.vroot_start= p, vp->path); p+= vp->length;
|
||||||
|
len += vp->length;
|
||||||
|
};
|
||||||
|
if (vroot_data.cpp_style_path) {
|
||||||
|
if (filename[0] != '/') {
|
||||||
|
if(1 + len + pp->length >= MAXPATHLEN) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length;
|
||||||
|
*p++= '/';
|
||||||
|
len += 1 + pp->length;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
if (strchr(filename, '/') == NULL) {
|
||||||
|
if (pp->length != 0) {
|
||||||
|
if(1 + len + pp->length >= MAXPATHLEN) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(void)strcpy(vroot_data.path_start= p,
|
||||||
|
pp->path);
|
||||||
|
p+= pp->length;
|
||||||
|
*p++= '/';
|
||||||
|
len += 1 + pp->length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(void)strcpy(vroot_data.filename_start= p, filename);
|
||||||
|
if ((*thunk)(vroot_data.full_path)) return;};}
|
||||||
|
else { pathcellt *vp1= vp;
|
||||||
|
for (pp= pp1, path_len= 0; pp->path != NULL; pp++, path_len++)
|
||||||
|
for (vp= vp1; vp->path != NULL; vp++) {
|
||||||
|
int len = 0;
|
||||||
|
p= vroot_data.full_path;
|
||||||
|
if ((filename[0] == '/') || (pp->path[0] == '/')) {
|
||||||
|
if(vp->length >= MAXPATHLEN) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(void)strcpy(vroot_data.vroot_start= p, vp->path); p+= vp->length;
|
||||||
|
len += vp->length;
|
||||||
|
}
|
||||||
|
if (vroot_data.cpp_style_path) {
|
||||||
|
if (filename[0] != '/') {
|
||||||
|
if(1 + len + pp->length >= MAXPATHLEN) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length;
|
||||||
|
*p++= '/';
|
||||||
|
len += 1 + pp->length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (strchr(filename, '/') == NULL) {
|
||||||
|
if(1 + len + pp->length >= MAXPATHLEN) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length;
|
||||||
|
*p++= '/';
|
||||||
|
len += 1 + pp->length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void)strcpy(vroot_data.filename_start= p, filename);
|
||||||
|
if ((*thunk)(vroot_data.full_path)) return;};};
|
||||||
|
(void)strcpy(vroot_data.full_path, filename);
|
||||||
|
return;};};
|
||||||
|
}
|
2788
man/man1/make.1
Normal file
2788
man/man1/make.1
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue