#include "make.h"
#include "dep.h"
#include "debug.h"
#if HAVE_VPRINTF || HAVE_DOPRNT
# define HAVE_STDVARARGS 1
# if __STDC__
# include <stdarg.h>
# define VA_START(args, lastarg) va_start(args, lastarg)
# else
# include <varargs.h>
# define VA_START(args, lastarg) va_start(args)
# endif
# if HAVE_VPRINTF
# define VA_PRINTF(fp, lastarg, args) vfprintf((fp), (lastarg), (args))
# else
# define VA_PRINTF(fp, lastarg, args) _doprnt((lastarg), (args), (fp))
# endif
# define VA_END(args) va_end(args)
#else
# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
# define VA_START(args, lastarg)
# define VA_PRINTF(fp, lastarg, args) fprintf((fp), (lastarg), va_alist)
# define VA_END(args)
#endif
int
alpha_compare (v1, v2)
const void *v1, *v2;
{
const char *s1 = *((char **)v1);
const char *s2 = *((char **)v2);
if (*s1 != *s2)
return *s1 - *s2;
return strcmp (s1, s2);
}
void
collapse_continuations (line)
char *line;
{
register char *in, *out, *p;
register int backslash;
register unsigned int bs_write;
in = strchr (line, '\n');
if (in == 0)
return;
out = in;
while (out > line && out[-1] == '\\')
--out;
while (*in != '\0')
{
backslash = 0;
bs_write = 0;
for (p = in - 1; p >= line && *p == '\\'; --p)
{
if (backslash)
++bs_write;
backslash = !backslash;
if (in == out - 1)
abort ();
}
while (bs_write-- > 0)
*out++ = '\\';
++in;
if (backslash)
{
in = next_token (in);
while (out > line && isblank ((unsigned char)out[-1]))
--out;
*out++ = ' ';
}
else
*out++ = '\n';
while (*in != '\0')
if (*in == '\\')
{
p = in + 1;
while (*p == '\\')
++p;
if (*p == '\n')
{
in = p;
break;
}
while (in < p)
*out++ = *in++;
}
else
*out++ = *in++;
}
*out = '\0';
}
void
remove_comments (line)
char *line;
{
char *comment;
comment = find_char_unquote (line, '#', 0, 0);
if (comment != 0)
*comment = '\0';
}
void
print_spaces (n)
unsigned int n;
{
while (n-- > 0)
putchar (' ');
}
char *
concat (s1, s2, s3)
const char *s1, *s2, *s3;
{
unsigned int len1, len2, len3;
char *result;
len1 = *s1 != '\0' ? strlen (s1) : 0;
len2 = *s2 != '\0' ? strlen (s2) : 0;
len3 = *s3 != '\0' ? strlen (s3) : 0;
result = (char *) xmalloc (len1 + len2 + len3 + 1);
if (*s1 != '\0')
bcopy (s1, result, len1);
if (*s2 != '\0')
bcopy (s2, result + len1, len2);
if (*s3 != '\0')
bcopy (s3, result + len1 + len2, len3);
*(result + len1 + len2 + len3) = '\0';
return result;
}
void
#if __STDC__ && HAVE_STDVARARGS
message (int prefix, const char *fmt, ...)
#else
message (prefix, fmt, va_alist)
int prefix;
const char *fmt;
va_dcl
#endif
{
#if HAVE_STDVARARGS
va_list args;
#endif
log_working_directory (1);
if (fmt != 0)
{
if (prefix)
{
if (makelevel == 0)
printf ("%s: ", program);
else
printf ("%s[%u]: ", program, makelevel);
}
VA_START (args, fmt);
VA_PRINTF (stdout, fmt, args);
VA_END (args);
putchar ('\n');
}
fflush (stdout);
}
void
#if __STDC__ && HAVE_STDVARARGS
error (const struct floc *flocp, const char *fmt, ...)
#else
error (flocp, fmt, va_alist)
const struct floc *flocp;
const char *fmt;
va_dcl
#endif
{
#if HAVE_STDVARARGS
va_list args;
#endif
log_working_directory (1);
if (flocp && flocp->filenm)
fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno);
else if (makelevel == 0)
fprintf (stderr, "%s: ", program);
else
fprintf (stderr, "%s[%u]: ", program, makelevel);
VA_START(args, fmt);
VA_PRINTF (stderr, fmt, args);
VA_END (args);
putc ('\n', stderr);
fflush (stderr);
}
void
#if __STDC__ && HAVE_STDVARARGS
fatal (const struct floc *flocp, const char *fmt, ...)
#else
fatal (flocp, fmt, va_alist)
const struct floc *flocp;
const char *fmt;
va_dcl
#endif
{
#if HAVE_STDVARARGS
va_list args;
#endif
log_working_directory (1);
if (flocp && flocp->filenm)
fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno);
else if (makelevel == 0)
fprintf (stderr, "%s: *** ", program);
else
fprintf (stderr, "%s[%u]: *** ", program, makelevel);
VA_START(args, fmt);
VA_PRINTF (stderr, fmt, args);
VA_END (args);
fputs (_(". Stop.\n"), stderr);
die (2);
}
#ifndef HAVE_STRERROR
#undef strerror
char *
strerror (errnum)
int errnum;
{
extern int errno, sys_nerr;
#ifndef __DECC
extern char *sys_errlist[];
#endif
static char buf[] = "Unknown error 12345678901234567890";
if (errno < sys_nerr)
return sys_errlist[errnum];
sprintf (buf, _("Unknown error %d"), errnum);
return buf;
}
#endif
void
perror_with_name (str, name)
const char *str, *name;
{
error (NILF, _("%s%s: %s"), str, name, strerror (errno));
}
void
pfatal_with_name (name)
const char *name;
{
fatal (NILF, _("%s: %s"), name, strerror (errno));
}
#ifndef HAVE_DMALLOC_H
#undef xmalloc
#undef xrealloc
#undef xstrdup
char *
xmalloc (size)
unsigned int size;
{
char *result = (char *) malloc (size);
if (result == 0)
fatal (NILF, _("virtual memory exhausted"));
return result;
}
char *
xrealloc (ptr, size)
char *ptr;
unsigned int size;
{
char *result;
result = ptr ? realloc (ptr, size) : malloc (size);
if (result == 0)
fatal (NILF, _("virtual memory exhausted"));
return result;
}
char *
xstrdup (ptr)
const char *ptr;
{
char *result;
#ifdef HAVE_STRDUP
result = strdup (ptr);
#else
result = (char *) malloc (strlen (ptr) + 1);
#endif
if (result == 0)
fatal (NILF, _("virtual memory exhausted"));
#ifdef HAVE_STRDUP
return result;
#else
return strcpy(result, ptr);
#endif
}
#endif
char *
savestring (str, length)
const char *str;
unsigned int length;
{
register char *out = (char *) xmalloc (length + 1);
if (length > 0)
bcopy (str, out, length);
out[length] = '\0';
return out;
}
char *
sindex (big, blen, small, slen)
const char *big;
unsigned int blen;
const char *small;
unsigned int slen;
{
if (!blen)
blen = strlen (big);
if (!slen)
slen = strlen (small);
if (slen && blen >= slen)
{
register unsigned int b;
--slen;
blen -= slen;
for (b = 0; b < blen; ++b, ++big)
if (*big == *small && strneq (big + 1, small + 1, slen))
return (char *)big;
}
return 0;
}
char *
lindex (s, limit, c)
register const char *s, *limit;
int c;
{
while (s < limit)
if (*s++ == c)
return (char *)(s - 1);
return 0;
}
char *
end_of_token (s)
char *s;
{
while (*s != '\0' && !isblank ((unsigned char)*s))
++s;
return s;
}
#ifdef WINDOWS32
char *
end_of_token_w32 (s, stopchar)
char *s;
char stopchar;
{
register char *p = s;
register int backslash = 0;
while (*p != '\0' && *p != stopchar
&& (backslash || !isblank ((unsigned char)*p)))
{
if (*p++ == '\\')
{
backslash = !backslash;
while (*p == '\\')
{
backslash = !backslash;
++p;
}
}
else
backslash = 0;
}
return p;
}
#endif
char *
next_token (s)
const char *s;
{
while (isblank ((unsigned char)*s))
++s;
return (char *)s;
}
char *
find_next_token (ptr, lengthptr)
char **ptr;
unsigned int *lengthptr;
{
char *p = next_token (*ptr);
char *end;
if (*p == '\0')
return 0;
*ptr = end = end_of_token (p);
if (lengthptr != 0)
*lengthptr = end - p;
return p;
}
struct dep *
copy_dep_chain (d)
register struct dep *d;
{
register struct dep *c;
struct dep *firstnew = 0;
struct dep *lastnew = 0;
while (d != 0)
{
c = (struct dep *) xmalloc (sizeof (struct dep));
bcopy ((char *) d, (char *) c, sizeof (struct dep));
if (c->name != 0)
c->name = xstrdup (c->name);
c->next = 0;
if (firstnew == 0)
firstnew = lastnew = c;
else
lastnew = lastnew->next = c;
d = d->next;
}
return firstnew;
}
#ifdef iAPX286
char *
dep_name (dep)
struct dep *dep;
{
return dep->name == 0 ? dep->file->name : dep->name;
}
#endif
#ifdef GETLOADAVG_PRIVILEGED
#ifdef POSIX
#undef HAVE_SETREUID
#undef HAVE_SETREGID
#else
#undef HAVE_SETEUID
#undef HAVE_SETEGID
#endif
#ifndef HAVE_UNISTD_H
extern int getuid (), getgid (), geteuid (), getegid ();
extern int setuid (), setgid ();
#ifdef HAVE_SETEUID
extern int seteuid ();
#else
#ifdef HAVE_SETREUID
extern int setreuid ();
#endif
#endif
#ifdef HAVE_SETEGID
extern int setegid ();
#else
#ifdef HAVE_SETREGID
extern int setregid ();
#endif
#endif
#endif
static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
#define access_inited (user_uid != -1)
static enum { make, user } current_access;
static void
log_access (flavor)
char *flavor;
{
if (! ISDB (DB_JOBS))
return;
fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
(unsigned long) getegid (), (unsigned long) getgid ());
fflush (stderr);
}
static void
init_access ()
{
#ifndef VMS
user_uid = getuid ();
user_gid = getgid ();
make_uid = geteuid ();
make_gid = getegid ();
if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
pfatal_with_name ("get{e}[gu]id");
log_access (_("Initialized access"));
current_access = make;
#endif
}
#endif
void
user_access ()
{
#ifdef GETLOADAVG_PRIVILEGED
if (!access_inited)
init_access ();
if (current_access == user)
return;
#ifdef HAVE_SETEUID
if (seteuid (user_uid) < 0)
pfatal_with_name ("user_access: seteuid");
#else
#ifndef HAVE_SETREUID
if (setuid (user_uid) < 0)
pfatal_with_name ("user_access: setuid");
#else
if (setreuid (make_uid, user_uid) < 0)
pfatal_with_name ("user_access: setreuid");
#endif
#endif
#ifdef HAVE_SETEGID
if (setegid (user_gid) < 0)
pfatal_with_name ("user_access: setegid");
#else
#ifndef HAVE_SETREGID
if (setgid (user_gid) < 0)
pfatal_with_name ("user_access: setgid");
#else
if (setregid (make_gid, user_gid) < 0)
pfatal_with_name ("user_access: setregid");
#endif
#endif
current_access = user;
log_access (_("User access"));
#endif
}
void
make_access ()
{
#ifdef GETLOADAVG_PRIVILEGED
if (!access_inited)
init_access ();
if (current_access == make)
return;
#ifdef HAVE_SETEUID
if (seteuid (make_uid) < 0)
pfatal_with_name ("make_access: seteuid");
#else
#ifndef HAVE_SETREUID
if (setuid (make_uid) < 0)
pfatal_with_name ("make_access: setuid");
#else
if (setreuid (user_uid, make_uid) < 0)
pfatal_with_name ("make_access: setreuid");
#endif
#endif
#ifdef HAVE_SETEGID
if (setegid (make_gid) < 0)
pfatal_with_name ("make_access: setegid");
#else
#ifndef HAVE_SETREGID
if (setgid (make_gid) < 0)
pfatal_with_name ("make_access: setgid");
#else
if (setregid (user_gid, make_gid) < 0)
pfatal_with_name ("make_access: setregid");
#endif
#endif
current_access = make;
log_access (_("Make access"));
#endif
}
void
child_access ()
{
#ifdef GETLOADAVG_PRIVILEGED
if (!access_inited)
abort ();
#ifndef HAVE_SETREUID
if (setuid (user_uid) < 0)
pfatal_with_name ("child_access: setuid");
#else
if (setreuid (user_uid, user_uid) < 0)
pfatal_with_name ("child_access: setreuid");
#endif
#ifndef HAVE_SETREGID
if (setgid (user_gid) < 0)
pfatal_with_name ("child_access: setgid");
#else
if (setregid (user_gid, user_gid) < 0)
pfatal_with_name ("child_access: setregid");
#endif
log_access (_("Child access"));
#endif
}
#ifdef NEED_GET_PATH_MAX
unsigned int
get_path_max ()
{
static unsigned int value;
if (value == 0)
{
long int x = pathconf ("/", _PC_PATH_MAX);
if (x > 0)
value = x;
else
return MAXPATHLEN;
}
return value;
}
#endif
#ifdef HAVE_BROKEN_RESTART
#undef stat
#undef readdir
int
atomic_stat(file, buf)
const char *file;
struct stat *buf;
{
int r;
while ((r = stat (file, buf)) < 0)
if (errno != EINTR)
break;
return r;
}
struct dirent *
atomic_readdir(dir)
DIR *dir;
{
struct dirent *r;
while ((r = readdir (dir)) == NULL)
if (errno != EINTR)
break;
return r;
}
#endif