#ifndef lint
static char *RCSid = "$Header: service.c,v 1.4 90/03/19 10:39:55 mr-frog Exp $";
#endif

/*
 * service.c
 *
 * service a user socket by reading all the
 * commands and executing the right routines.
 *
 * Dave Pare, 1986
 */

#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <errno.h>
#include <signal.h>
#include "misc.h"
#include "user.h"
#include "tm.h"
#include "io.h"

int	tm_answer[10];
int	seq;

/*ARGSUSED*/
service(iop, op, assoc)
	iop_t	iop;
	int	op;
	s_char	*assoc;
{
	static	int tm_parse();
	extern	int tm_flags;
	extern	int errno;
	struct	user *up = (struct user *) assoc;
	s_char	*argp[64];
	s_char	buf[1024];
	int	detail;
	int	which;

	if (io_error(iop) || io_eof(iop)) {
		user_remove(up);
		return;
	}
	while (io_gets(iop, buf, sizeof(buf)) >= 0) {
		if (tm_parse(buf, argp) <= 0) {
			/* error */
			continue;
		}
		seq = tm_answer[1];
		which = tm_answer[2];
		detail = tm_answer[3];
		switch (tm_answer[0]) {
		case C_IDENT:
			up->u_pid = which;
			up->u_cnum = detail;
			sendnum(iop, seq, TM_OK);
			/*logerror("user sends ident");*/
			break;
		case C_LOCK:
			if (tm_flags) {
				/* update is waiting to occur */
				sendnum(iop, seq, TM_ERROR);
				logerror("user lock failed during update wait");
				break;
			}
			/* lock will complain if it needs to */
			if (lock(up, detail))
				sendnum(iop, seq, TM_OK);
			break;
		case C_UNLOCK:
			unlock(up, detail);
			sendnum(iop, seq, TM_OK);
			/*logerror("unlock file");*/
			break;
		case C_NATMOD:
			/* natmod verifies stuff, bcasts if ok */
			if (natmod(argp, tm_answer) == 0) {
				logerror("bad natmod string: %s", buf);
				sendnum(iop, seq, TM_ERROR);
			}
			break;
		case C_NEWS:
			nreport(tm_answer[2], tm_answer[3], tm_answer[4],
				tm_answer[5]);
			break;
		case C_SYNC:
			sendnum(iop, seq, TM_OK);
			break;
#ifdef	DEMANDUPDATE
		case C_WANTUPDATE:
			sendnum(iop, seq, TM_OK);
			if (demandupdatecheck())
				kill(getpid(), SIGALRM);
			break;
#endif	DEMANDUPDATE
		case C_CLOSE:
			io_close(iop);
			user_remove(up);
			break;
		default:
			sendnum(iop, seq, TM_PANIC);
			logerror("bad tm request type: %s", buf);
			break;
		}
		*buf = 0;
	}
}

static
int
tm_parse(buf, argp)
	s_char	*buf;
	s_char	**argp;
{
	static	s_char space[255];
	int	i;
	int	n;

	n = parse(buf, argp, (s_char **)0, space, 0);
	if (n <= 0 || n > 10)
		return 0;
	for (i=0; i<n; i++) {
		tm_answer[i] = atoi(argp[i]);
	}
	return n;
}
