// $Id: Login.h,v 1.8 2003/08/31 00:38:11 vern Exp $
//
// Copyright (c) 1999, 2001, 2002
//      The Regents of the University of California.  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that: (1) source code distributions
// retain the above copyright notice and this paragraph in its entirety, (2)
// distributions including binary code include the above copyright notice and
// this paragraph in its entirety in the documentation or other materials
// provided with the distribution, and (3) all advertising materials mentioning
// features or use of this software display the following acknowledgement:
// ``This product includes software developed by the University of California,
// Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
// the University nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

#ifndef login_h
#define login_h

#include "TCP.h"

typedef enum {
	LOGIN_STATE_AUTHENTICATE,	// trying to authenticate

	LOGIN_STATE_LOGGED_IN,	// successful authentication
	LOGIN_STATE_SKIP,	// skip any further processing
	LOGIN_STATE_CONFUSED,	// we're confused
} login_state;

// If no action by this many lines, we're definitely confused.
#define MAX_AUTHENTICATE_LINES 50

// Maximum # lines look after login for failure.
#define MAX_LOGIN_LOOKAHEAD 10

class LoginConn : public TCP_Connection {
public:
	LoginConn(NetSessions* s, HashKey* k, double t, const ConnID* id,
			const struct tcphdr* tp);
	~LoginConn();

	void NewLine(TCP_Endpoint* sender, char* line);
	void NewLine(TCP_Endpoint* sender, int length, const char* line, int is_const);

	void SetEnv(TCP_Endpoint* sender, char* name, char* val);

	login_state LoginState() const		{ return state; }
	void SetLoginState(login_state s)	{ state = s; }

	void EndpointEOF(TCP_EndpointContents* endp);

protected:
	void BuildEndpoints() = 0;

	void AuthenticationDialog(TCP_Endpoint* sender, char* line);

	void LoginEvent(EventHandlerPtr f, const char* line, int no_user_okay=0);
	const char* GetUsername(const char* line) const;
	void LineEvent(EventHandlerPtr f, const char* line);
	void Confused(const char* msg, const char* addl);
	void ConfusionText(const char* line);

	int IsPloy(const char* line);
	int IsSkipAuthentication(const char* line) const;
	const char* IsLoginPrompt(const char* line) const;	// nil if not
	int IsDirectLoginPrompt(const char* line) const;
	int IsFailureMsg(const char* line) const;
	int IsSuccessMsg(const char* line) const;
	int IsTimeout(const char* line) const;
	int IsEmpty(const char* line) const;

	void AddUserText(const char* line);	// complains on overflow
	char* PeekUserText() const;	// internal error on underflow
	char* PopUserText();		// internal error on underflow
	Val* PopUserTextVal();

	int MatchesTypeahead(const char* line) const;
	int HaveTypeahead() const	{ return num_user_text > 0; }
	void FlushEmptyTypeahead();

// If we have more user text than this unprocessed, we complain about
// excessive typeahead.
#define MAX_USER_TEXT 12
	char* user_text[MAX_USER_TEXT];
	int user_text_first, user_text_last;	// indices into user_text
	int num_user_text;	// number of entries in user_text

	Val* username;	// last username reported
	Val* client_name;	// rlogin client name (or nil if none)

	login_state state;
	int lines_scanned;
	int num_user_lines_seen;
	int last_failure_num_user_lines;
	int login_prompt_line;
	int failure_line;

	int is_VMS;
	int saw_ploy;
};

#endif
