/*
 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
 * Copyright (c) 1993, 1994 Rick Sladkey <jrs@world.std.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by Paul Kranenburg,
 *      Branko Lankester and Rick Sladkey.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *	mem.c,v 2.20 1994/03/21 05:45:30 jrs Exp
 */

#include "defs.h"

#include <sys/mman.h>

int
sys_brk(tcp)
struct tcb *tcp;
{
	if (entering(tcp)) {
		tprintf("%#x", tcp->u_arg[0]);
	}
#ifdef linux
	return RVAL_HEX;
}
#else
	return 0;
}

int
sys_sbrk(tcp)
struct tcb *tcp;
{
	if (entering(tcp)) {
		tprintf("%u", tcp->u_arg[0]);
	}
	return RVAL_HEX;
}
#endif

static struct xlat mmap_prot[] = {
	{ PROT_NONE,	"PROT_NONE",	},
	{ PROT_READ,	"PROT_READ"	},
	{ PROT_WRITE,	"PROT_WRITE"	},
	{ PROT_EXEC,	"PROT_EXEC"	},
	{ 0,		NULL		},
};
static struct xlat mmap_flags[] = {
	{ MAP_SHARED,	"MAP_SHARED"	},
	{ MAP_PRIVATE,	"MAP_PRIVATE"	},
	{ MAP_FIXED,	"MAP_FIXED"	},
#ifdef MAP_ANONYMOUS
	{ MAP_FIXED,	"MAP_ANONYMOUS"	},
#endif
#ifdef MAP_RENAME
	{ MAP_RENAME,	"MAP_RENAME"	},
#endif
#ifdef MAP_NORESERVE
	{ MAP_NORESERVE,"MAP_NORESERVE"	},
#endif
#ifdef _MAP_NEW
	{ _MAP_NEW,	"_MAP_NEW"	},
#endif
	{ 0,		NULL		},
};

int
sys_mmap(tcp)
struct tcb *tcp;
{
#ifdef LINUX
	int u_arg[6];
#else /* !LINUX */
	int *u_arg = tcp->u_arg;
#endif /* !LINUX */

	if (entering(tcp)) {
#ifdef LINUX
		if (umoven(tcp, tcp->u_arg[0], sizeof u_arg,
				(char *) u_arg) == -1)
			return 0;
#endif /* LINUX */

		/* addr */
		tprintf("%#x, ", u_arg[0]);
		/* len */
		tprintf("%u, ", u_arg[1]);
		/* prot */
		printflags(mmap_prot, u_arg[2]);
		tprintf(", ");
		/* flags */
		printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
		addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
		/* fd */
		tprintf(", %u, ", u_arg[4]);
		/* offset */
		tprintf("%#x", u_arg[5]);
	}
	return RVAL_HEX;
}

int
sys_munmap(tcp)
struct tcb *tcp;
{
	if (entering(tcp)) {
		tprintf("%#x, %u",
			tcp->u_arg[0], tcp->u_arg[1]);
	}
	return 0;
}

int
sys_mprotect(tcp)
struct tcb *tcp;
{
	if (entering(tcp)) {
		tprintf("%#x, %u, ",
			tcp->u_arg[0], tcp->u_arg[1]);
		if (!printflags(mmap_prot, tcp->u_arg[2]))
			tprintf("PROT_???");
	}
	return 0;
}

#ifdef HAVE_MCTL

static struct xlat mctl_funcs[] = {
	{ MC_LOCK,	"MC_LOCK"	},
	{ MC_LOCKAS,	"MC_LOCKAS"	},
	{ MC_SYNC,	"MC_SYNC"	},
	{ MC_UNLOCK,	"MC_UNLOCK"	},
	{ MC_UNLOCKAS,	"MC_UNLOCKAS"	},
	{ 0,		NULL		},
};

static struct xlat mctl_lockas[] = {
	{ MCL_CURRENT,	"MCL_CURRENT"	},
	{ MCL_FUTURE,	"MCL_FUTURE"	},
	{ 0,		NULL		},
};

static struct xlat mctl_sync[] = {
	{ MS_ASYNC,	"MS_ASYNC"	},
	{ MS_INVALIDATE,"MS_INVALIDATE"	},
	{ 0,		NULL		},
};

int
sys_mctl(tcp)
struct tcb *tcp;
{
	int arg, function;

	if (entering(tcp)) {
		/* addr */
		tprintf("%#x", tcp->u_arg[0]);
		/* len */
		tprintf(", %u, ", tcp->u_arg[1]);
		/* function */
		function = tcp->u_arg[2];
		if (!printflags(mctl_funcs, function))
			tprintf("MC_???");
		/* arg */
		arg = tcp->u_arg[3];
		tprintf(", ");
		switch (function) {
		case MC_SYNC:
			if (!printflags(mctl_sync, arg))
				tprintf("MS_???");
			break;
		case MC_LOCKAS:
			if (!printflags(mctl_lockas, arg))
				tprintf("MCL_???");
			break;
		default:
			tprintf("%#x", arg);
			break;
		}
	}
	return 0;
}

#endif /* HAVE_MCTL */

int
sys_mincore(tcp)
struct tcb *tcp;
{
	int i, len;
	char *vec = NULL;

	if (entering(tcp)) {
		tprintf("%#x, %u, ", tcp->u_arg[0], tcp->u_arg[1]);
	} else {
		len = tcp->u_arg[1];
		if (syserror(tcp) || tcp->u_arg[2] == 0 ||
			(vec = malloc((u_int)len)) == NULL ||
			umoven(tcp, tcp->u_arg[2], len, vec) < 0)
			tprintf("%#x", tcp->u_arg[2]);
		else {
			tprintf("[");
			for (i = 0; i < len; i++) {
				if (abbrev(tcp) && i >= max_strlen) {
					tprintf("...");
					break;
				}
				tprintf((vec[i] & 1) ? "1" : "0");
			}
			tprintf("]");
		}
		if (vec)
			free(vec);
	}
	return 0;
}

int
sys_getpagesize(tcp)
struct tcb *tcp;
{
	if (exiting(tcp))
		return RVAL_HEX;
	return 0;
}
