/*
 *	Find executable binaries with magic numbers other than ZMAGIC.
 *
 *	Unlinked .o files are OMAGIC, but are not counted because they have
 *	not got execute permission turned on.
 *
 *	Martin Guy, UKC, November 1986
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <a.out.h>
#include <signal.h>

int checkmagic();
int coredump();

char *progname;

/* counts of file types */
int nomagic = 0;	/* an appropriate name! */
int nnmagic = 0;
int nzmagic = 0;

main(argc,argv)
char **argv;
{
	progname = argv[0];

	/* It's a real bugger trying to find the core dumps from this thing! */
	(void) signal(SIGSEGV, coredump);
	(void) signal(SIGFPE, coredump);
	(void) signal(SIGBUS, coredump);

	if (argc != 2) {
		fprintf(stderr, "Usage: %s <dir>\n", progname);
		exit(1);
	}
	if (descend(argv[1], checkmagic) == 0) fputs("None found.\n", stderr);

	printf("o=%d, n=%d, z=%d.\n", nomagic, nnmagic, nzmagic);
	exit(0);
}

/*
 * Arguments to fn are:
 * name of file relative to cwd.
 * full name of file from starting directory.
 * pointer to stat structure for that file.
 *	(may be NULL if not stattable)
 */
int
checkmagic(name, fullname, stbuf)
char *name;
char *fullname;
struct stat *stbuf;
{
	register int fd;
	int magic;

	if (stbuf == NULL) return(0);

	/* don't open it unless it's a likely binary on the info we have */
	/* binaries have to be regular files */
	if ((stbuf->st_mode & S_IFMT) != S_IFREG) return(0);
	/* and be executable */
	if (!(stbuf->st_mode & 0111)) return(0);
	/* and of a certain size */
	if (stbuf->st_size < sizeof(struct exec)) return(0);

	/* open it and inspect its magic number */
	fd = open(name, 0);
	if (fd < 0) {
		fprintf(stderr, "%s: Cannot open", progname);
		perror(fullname);
		return(0);
	}

	if (read(fd, (char *) &magic, sizeof(magic)) != sizeof(magic)) {
		(void) close(fd);
		fprintf(stderr, "%s: cannot read magic from ", progname);
		perror(fullname);
		return(0);
	}

	(void) close(fd);

	switch (magic) {
	case OMAGIC:
		nomagic++;
		puts(fullname);
		break;
	case NMAGIC:
		nnmagic++;
		break;
	case ZMAGIC:
		nzmagic++;
		break;
#ifdef orion
/* what to & orion magics it with to get vax magics */
# define VAXMAGIC 0417
	case OMAGIC & VAXMAGIC:
	case NMAGIC & VAXMAGIC:
	case ZMAGIC & VAXMAGIC:
		printf(stdout, "%s: alien magic number 0%o,\n", magic);
		break;
#endif
	}
	return(1);
}

int
coredump(sig)
int sig;
{
	(void) chdir("/tmp");
	(void) signal(sig, SIG_DFL);
	kill(getpid(), sig);
	abort();
}
