/*
 * Copyright (c) 2005 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: statit.c,v 1.3 2006/12/26 20:09:08 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/test.h"
#include "sm/stat.h"
#include "sm/sysexits.h"
#include <stdio.h>

static int Verbose = 0;

#define STATIT_MODE	0x01
#define STATIT_UID	0x02
#define STATIT_GID	0x04
#define CMPIT_MODE	0x10
#define CMPIT_UID	0x20
#define CMPIT_GID	0x40

#define MODE_MASK	07777

static int
statit(const char *path, int opts, mode_t mode, uid_t uid, gid_t gid)
{
	int r;
	struct stat sb;

	r = stat(path, &sb);
	if (r != 0)
	{
		fprintf(stderr, "errno=%d\n", errno);
		return r;
	}
	if (opts & STATIT_MODE)
		fprintf(stdout, "%o\n", sb.st_mode & MODE_MASK);
	if (opts & STATIT_UID)
		fprintf(stdout, "%d\n", (int) sb.st_uid);
	if (opts & STATIT_GID)
		fprintf(stdout, "%d\n", (int) sb.st_gid);
	if (opts & CMPIT_MODE && mode != (sb.st_mode & MODE_MASK))
	{
		fprintf(stdout, "file=%s, mismatch=mode, expected=%o, got=%o\n",
			path, mode, sb.st_mode & MODE_MASK);
		r = 1;
	}
	if (opts & CMPIT_UID && uid != sb.st_uid)
	{
		fprintf(stdout, "file=%s, mismatch=uid, expected=%d, got=%d\n",
			path, (int) uid, (int) sb.st_uid);
		r = 1;
	}
	if (opts & CMPIT_GID && gid != sb.st_gid)
	{
		fprintf(stdout, "file=%s, mismatch=gid, expected=%d, got=%d\n",
			path, (int) gid, (int) sb.st_gid);
		r = 1;
	}
	return r;
}

int
main(int argc, char *argv[])
{
	int c, opts, r;
	mode_t mode;
	uid_t uid;
	gid_t gid;
	char *name;

	opts = 0;
	mode = 0;
	uid = 0;
	gid = 0;
	while ((c = getopt(argc, argv, "G:gM:mU:uV")) != -1)
	{
		switch (c)
		{
		  case 'G':
			opts |= CMPIT_GID;
			gid = strtol(optarg, NULL, 0);
			break;
		  case 'g':
			opts |= STATIT_GID;
			break;
		  case 'M':
			opts |= CMPIT_MODE;
			mode = strtol(optarg, NULL, 0);
			break;
		  case 'm':
			opts |= STATIT_MODE;
			break;
		  case 'U':
			opts |= CMPIT_UID;
			uid = strtol(optarg, NULL, 0);
			break;
		  case 'u':
			opts |= STATIT_UID;
			break;
		  case 'V':
			++Verbose;
			break;
		  default:
			/* usage(argv[0]); */
			return EX_USAGE;
		}
	}

	argc -= optind;
	argv += optind;

	r = 0;
	for (c = 0; c < argc; c++)
	{
		name = argv[c];
		if (name == NULL || *name == '\0')
			continue;
		r |= statit(name, opts, mode, uid, gid);
	}
	return r;
}


syntax highlighted by Code2HTML, v. 0.9.1