/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1989-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*
*
* three installation possibilities, from most inter-user sharing to least
*
* (1) $INSTALLROOT/lib/probe/probe set-uid to the owner of the
* probe hierarchy
* (2) probe hierarchy owned by the caller geteuid() (e.g., FAT fs)
* (3) otherwise info maintained per-user in $HOME/.probe/
*/
static const char usage[] =
"[-?\n@(#)$Id: probe (AT&T Research) 2007-02-22 $\n]"
"[+DESCRIPTION?\bprobe\b generates, installs and displays on the standard"
" output probe information for the \alanguage\a programming language"
" with respect to the \atool\a command as implemented by the"
" \aprocessor\a command. The probe information is in"
" the \atool\a command syntax. In general the commands that rely on"
" probe information (re)generate the information when it is out of date"
" (see \b--generate\b), so direct control is not usually"
" necessary. However, not all changes to \aprocessor\a that"
" would affect the probe information are detected by this mechanism;"
" such changes require manual intervention (see \b--delete\b and"
" \b--override\b.) A probe information file (see \b--key\b) with"
" write mode enabled signifies that manual changes have been made"
" and disables automatic regeneration (see \b--generate\b.)]"
"[+?\bprobe\b information is kept in a file with a pathname based on a"
" hash of \alanguage\a, \atool\a, and \aprocessor\a. The information"
" is generated by a \bsh\b(1) script (\aprobe script\a) specific to"
" each \alanguage-processor\a pair. Any options that change the"
" semantics of the language handled by \aprocessor\a should be included"
" in the \aprocessor\a operand. e.g., if \bcc -++\b processes C++ files,"
" then \aprocessor\a should be \bcc -++\b, not \bcc\b.]"
"[+?\bprobe\b generation may take a few minutes on some systems or for"
" some \aprocessors\a. Information is shared between users as much"
" as possible. If the \b--key\b option produces a path under your"
" \b$HOME\b directory then the probe installation does not support"
" sharing and each user will have private copies of the generated"
" information.]"
"[+?For some \alanguage\a/\atool\a combinations, the file"
" exists in the same directory as the \bprobe\b script, is sourced"
" (via the \b.\b \bsh\b(1) command) before the probe variables are"
" emitted. The emitted values may be modified by assigning appropriate"
" \bsh\b variables (non-identifier name characters converted"
" to \b_\b.) Additional non-standard values may be written directly"
" to the standard output.]"
"[+?For all \alanguage\a/\atool\a combinations, the file"
" exists in the same directory as the \bprobe\b script, is sourced"
" (via the \b.\b \bsh\b(1) command) before the \bprobe\b script proper."
" \bprobe.ini\b may completely override the \bprobe\b script by"
" exiting (presumably after printing its own values on the"
" standard output.)]"
"[+?Sometimes it is necessary to maintain private \bprobe\b information"
" for some processors or tools. See \b--override\b for details.]"
"[a:attributes?List probe attribute definitions.]"
"[d:delete?Delete the current information. Information can only be deleted by"
" the generating user.]"
"[f:force?Force information generation even if it is out of date. Only probe"
" information files with write mode disabled can be regenerated.]"
"[g:generate?Generate the probe information if it is out of date. Only probe"
" information files with write mode disabled can be regenerated.]"
"[k:key?List the probe key path name on the standard output.]"
"[l:list?List the probe information on the standard output. An error occurs"
" if the information has not been generated, unless \b--generate\b"
" is also specified.]"
"[o:override?Make a writable copy of the probe information file in the"
" generated file pathname on the standard output. If \b--key\b is also"
" specified then the override path is listed but not created. When"
" \bprobe\b-based commands are run with \abindir\a in \b$PATH\b before"
" the bin directory of the standard probe information the override"
" information will be used. Note that since the override file is user"
" writable automatic regeneration is disabled.]:[bindir]"
"[s:silent?By default a message is printed on the standard error when probe"
" generation starts; \b--silent\b disables this message.]"
"[t:test?Start probe generation but do not save the results. Used for"
" debugging probe scripts.]"
"[v:verify?Each probe information file contains a comment (in the"
" \atool\a syntax) that can be used to verify the contents. This"
" option does that verification.]"
"[D:debug?Start probe generation, do not save the results, and write the"
" probe script trace (see \bsh\b(1) \b-x\b) to the standard error.]"
"\n"
"\nlanguage tool processor\n"
"\n"
"[+FILES]{"
" directory for \alanguage\a processors.]"
" [+$HOME/.probe?Per-user directory when \bprobe\b is installed"
" non-set-uid or the probe directory is on a readonly"
" filesystem.]"
"}"
"[+CAVEATS?To allow probe information to be generated and shared among all"
" filesystem must be mounted read-write.]"
"[+?Automatic language processor probing is mostly black magic, but then"
" so are most language processor implementations.]"
"[+SEE ALSO?\bcpp\b(1), \bnmake\b(1), \bpathkey\b(3), \bpathprobe\b(3)]"
;
#include <ast.h>
#include <ctype.h>
#include <error.h>
#include <ls.h>
#include <preroot.h>
#include <proc.h>
#include <sig.h>
#include <times.h>
static char* tmp;
{
#ifdef SIGALRM
#endif
#ifdef SIGHUP
#endif
#ifdef SIGQUIT
#endif
};
/*
* return non-0 if path is in a readonly or non-setuid fs
*/
static int
{
{
#if defined(ST_RDONLY)
return 1;
#endif
#if defined(ST_NOSUID)
return 1;
#endif
}
return 0;
}
#else
#define rofs(p) 0
#endif
/*
* check path for old processor name clash
* if old!=0 then file path compared with file old
* 0 returned if clash or file path the same as old
*/
static int
{
char* ns;
char* os;
int nz;
int oz;
int r;
r = 0;
{
{
r = 1;
else
}
{
for (;;)
{
break;
break;
break;
}
r = 0;
}
}
else if (must)
return r;
}
/*
* yes this is sleazy
*/
static void
{
if (tmp)
pause();
/*NOTREACHED*/
}
int
{
register int n;
register char* base;
register char* path;
char* script;
char* probe;
char* language;
char* tool;
char* processor;
char* sentinel;
char* s;
char* v;
char* override;
int i;
int suid;
int options = 0;
unsigned long ptime;
for (;;)
{
{
case 'a':
options |= ATTRIBUTES;
continue;
case 'd':
continue;
case 'f':
continue;
case 'g':
continue;
case 'k':
continue;
case 'l':
continue;
case 'o':
continue;
case 's':
continue;
case 't':
continue;
case 'v':
continue;
case 'D':
continue;
case '?':
break;
case ':':
break;
}
break;
}
if (error_info.errors || !(language = *argv++) || !(tool = *argv++) || !(processor = *argv++) || *argv)
if (*processor != '/')
{
{
n = s - processor;
*(processor + n) = 0;
}
v = processor;
if (!(processor = pathpath(processor, NiL, PATH_ABSOLUTE|PATH_REGULAR|PATH_EXECUTE, cmd, sizeof(cmd))))
if (s)
}
#if FS_PREROOT
#endif
if (!(path = pathprobe(language, tool, processor, (options & TEST) ? -3 : -2, NiL, 0, attributes, sizeof(attributes))))
{
}
{
/*
* verify the hierarchy before any ops
*/
{
}
else
suid = -1;
*(script + n) = 0;
if (suid >= 0)
else if (!(path = pathprobe(language, tool, processor, -1, NiL, 0, attributes, sizeof(attributes))))
else
{
{
}
}
}
/*
* ops ok now
*/
{
{
/*
* request not by owner of processor
* so limit to probe owner
*/
}
}
else
{
if (!(options & (FORCE|TEST)) && ps.st_mode && (ptime <= (unsigned long)ps.st_mtime || ptime <= (unsigned long)ps.st_ctime || (ps.st_mode & S_IWUSR)))
{
{
if (!options)
}
error(0, "%s probe information for %s language processor %s must be manually regenerated", tool, language, processor);
}
{
/*
* recursion check using environment sentinel
*/
for (s = sentinel; *s; s++)
if (!isalnum(*s))
*s = '_';
/*
* generate the new info in a tmp file
*/
if (suid < 0)
{
{
*s = 0;
}
}
for (n = 0; n < elementsof(signals); n++)
{
}
n = 0;
cmdargv[n++] = "-d";
cmdargv[n++] = attributes;
cmdargv[n] = 0;
n = 0;
cmdenvv[n] = 0;
if (!(pp = procopen(script, cmdargv, cmdenvv, NiL, PROC_UID|PROC_GID|((options&TEST)?0:PROC_READ))))
n = -1;
else if (!(options & TEST) && (!(pf = sfnew(NiL, NiL, SF_UNBOUND, pp->rfd, SF_READ)) || !(pp->rfd = -1) || sfmove(pf, fp, SF_UNBOUND, -1) < 0 || sfclose(pf) || sfclose(fp)))
n = -2;
else
n = 0;
if (!n)
n = i;
if (n < -1)
else if (n == -1)
else if (n > 0)
{
/*
* verify and rename to the real probe key path
*/
{
{
/*
* warp the file to yesterday to
* accomodate make installations
*/
{
}
}
{
n = -1;
}
}
else
n = -1;
}
}
if (!error_info.errors)
{
{
n = 5;
v = override;
{
{
{
*s = 0;
}
}
}
}
else
{
if (options & ATTRIBUTES)
{
{
}
}
}
}
}
return error_info.errors != 0;
}