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:
Georg Sauthoff 2016-08-21 14:32:02 +02:00
parent c2f5d8001b
commit 6804ba69d6
65 changed files with 26642 additions and 0 deletions

846
bin/ar.cc Normal file
View 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
View 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

File diff suppressed because it is too large Load diff

163
bin/dosys.cc Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

167
bin/macro.cc Normal file
View 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

File diff suppressed because it is too large Load diff

498
bin/make.rules.file Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

420
bin/pmake.cc Normal file
View 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

File diff suppressed because it is too large Load diff

1898
bin/read2.cc Normal file

File diff suppressed because it is too large Load diff

394
bin/rep.cc Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

1113
lib/mksh/misc.cc Normal file

File diff suppressed because it is too large Load diff

131
lib/mksh/mksh.cc Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;};};
}