/*
	This is the unix domain finger host client. It simply
	reads in the remote host name and the requested service
	and tries to send it to the server program via a socket.
	If it can't open a socket to the server it transforms
	itself into the server by doing an exec system call.
	We use a unix domain socket here as the client and
	server are running on the same host.

    Copyright (C) 1996 <Ed Alley, Email: wea@llnl.gov>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdio.h>

#include <syslog.h>

/********************************************************************

	These defines must be set properly for fhost to work.

********************************************************************/

#define ADDRESS	"/tmp/fhost_socket"		/* Socket address */
#define SPATH	"/home/ed/Signals/fhostd"	/* Server path */
#define SNAME	"fhostd"			/* Server name */
#define LOCALHOST "localhost"			/* Localhost name */

main(argc, argv, envp)
int argc;
char **argv;
char **envp;
{
	char c, cc[2];
	char localhost[64], host[64], service[64];
	char mess[192];
	int i, j, s, len, nbr;
	struct sockaddr_un saun;

	/*
	  Number of arguments must be three.
	*/

	if (argc != 3) {
		printf("Usage: fhost @host service\n");
		exit(1);
	}

	/*
	  Check argument lengths (must be less than 64 characters).
	*/

	for (i=0; i<argc; i++) {
	 if (strlen(argv[i]) > 63) {
	  printf("You have exceeded the argument length. ...Exiting\n");
	  syslog(LOG_ERR,"%.32s: Possible buffer overrun attack.\n", argv[i]);
	  exit (1);
	 }
	}

	/*
	  Load arguments: arg[1] = "@remote_host_name"
			  arg[2] = "requested_service"
	*/

	i = 0;
	while ((c = argv[1][i]) != '\0')
		host[i++] = c;
	host[i]   = '\0';

	cc[0] = host[0];
	cc[1] = '\0';

	strcpy(localhost, LOCALHOST);

	/*
	  Check to see if we have a host name.
	*/

	if (strcmp(cc, "@") != 0) {
		printf("FHOST: hostname error.\n");
		exit(1);
	}

	i = 0;
	while ((c = argv[2][i]) != '\0')
		service[i++] = c;
	service[i] = '\0';

	/*
	  Get a socket. This socket will be in the UNIX domain,
	  and will be a stream socket.
	*/

	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
		perror("Socket");
		exit(1);
	}

	/*
	  Create the address we will be connecting to by
	  storing the address info into the socket structure.
	*/

	bzero((char *) &saun, sizeof(saun));
	saun.sun_family = AF_UNIX;
	strcpy(saun.sun_path, ADDRESS);

	len = sizeof(saun.sun_family) + strlen(saun.sun_path);

	/*
	  Try to connect to the socket. For this to work,
	  the server must already have bound this address,
	  and must have issued a listen() request.

	  The third argument indicates the "length" of the
	  structure, and not just the length of the socket
	  name.

	  If we cannot connect to a server then we assume
	  that this is a new event. In that case we exec
	  the server.
	*/

	if (connect(s, (struct sockaddr *) &saun, len) < 0) {
		close(s);
		execl(SPATH, SNAME , host, service, (char *) 0);
		perror("execl");
		exit(1);
	}

	/*
	  If we do connect then the server is active. Send
	  the localhost name, the remote host's name and
	  the name of the service which was requested.
	*/

	i = 0;
	j = 0;
	while ((c = localhost[i++]) != '\0')
		mess[j++] = c;
	mess[j++] = '\0';

	i = 0;
	while ((c = host[i++]) != '\0')
		mess[j++] = c;
	mess[j++] = '\0';

	i = 0;
	while ((c = service[i++]) != '\0')
		mess[j++] = c;
	mess[j++] = '\0';

	send(s, mess, j, 0);

	/*
	  Terminate the connection.
	*/

	close(s);

	exit(0);
}
