import Sun's dmake from illumos
Source:
svn export https://github.com/illumos/illumos-gate/trunk/usr/src/cmd/make/
Yes, github also has a Subversion compatible interface - which seems to
be useful when one is only interested in a set of files.
The Github Subversion server printed: Exported revision 15816.
This corresponds to:
67c3092ccd/usr/src/cmd/make
This commit is contained in:
parent
c2f5d8001b
commit
6804ba69d6
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;};};
|
||||
}
|
Loading…
Reference in a new issue