/*
** ttyloc.c - Setup names for ttys.
**          - For the finger distribution.
**
** Written by Keith Gabryelski
** Released into public domain September 1, 1988.
** Please keep this header.
**
** Main routine for ttyloc.
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pwd.h>
#include "defs.h"
#include "ttyloc.h"

extern int errno;
extern char *getlogin(), *ttyname(), *strrchr();
extern struct passwd *getpwnam();

extern char *mymalloc(), *myrealloc();

char *progname;			/* Our name */

main(argc, argv)
int argc;
char **argv;
{
    char *ptr, *ttymess = mymalloc(1);
    char *tty_name = NULL;
    char *ttyfile, *word;
    int options, dflag = FALSE, newdefault = FALSE, specified = FALSE;

    ttymess[0] = '\0';
    progname = *argv++; --argc;

    options = TRUE;
    while (argc--)
    {
	if (**argv != '-')
	    options = FALSE;
	else
	    if (options)
	    {
		if (!strcmp(*argv, "--"))
		    options = FALSE;
		else
		{
		    /*
		    ** Do the option thing.
		    */
		    word = *argv+1;

		    while (*word != '\0')
			switch(*word++)
			{
			case 'd':	/* Use defaults file (~/.ttyloc). */
			    dflag = TRUE;
			    if (*word == '\0')
			    {
				if (argc > 0)
				    if (**argv != '-')
				    {
					ttyfile = *argv++; /* Use this file. */
					--argc;
					newdefault = TRUE;
				    }
			    }
			    else
			    {
				ttyfile = word;
				newdefault = TRUE;
			    }
			    word = "";
			    break;

			case 't':		/* For a specific TTY.       */
			    if (*word == '\0')	/* ttyfrob -- with apologize */
				if (argc--)	/*	      to GZT.COLE.   */
				    word = *++argv;
				else
				{
				    fprintf(stderr,
			       "%s: `-t' switch specified with no argument.\n",
					    progname);
				    exit(-1);
				}

			    tty_name = word;
			    word = "";
			    break;

			default:
			    fprintf(stderr, "%s: invalid switch '%c'.\n",
				    progname, *word);
			    usage();
			}
		}
		*argv++;
		continue;
	    }

	specified = TRUE;
	ttymess = myrealloc(ttymess, strlen(ttymess) + strlen(*argv) +
			    sizeof(" "));
	strcat(ttymess, *argv++);

	if (argc)
	    strcat(ttymess, " ");
    }

#ifdef DEBUG
    if (specified)
    {
	puts("specified");
	puts(ttymess);
    }
#endif /* DEBUG */

    if (tty_name == NULL)
    {
	if ((ptr = ttyname(2)) == NULL)	/* I can just feel the bogusity */
	{
	    fprintf(stderr, "%s: not connected to a tty.\n", progname);
	    exit(-1);
	}

	if ((ptr = strrchr(ptr, '/')) != NULL)
	    tty_name = ptr + 1;
	else
	{
	    fprintf(stderr, "%s: can't grok your tty.\n", progname);
	    exit(-1);
	}
    }

    if (dflag)
	if (specified)
	{
	    fprintf(stderr, "%s: `-d' switch with literal ttyloc string.\n",
		    progname);
	    exit(-1);
	}
	else
	{
	    char *buffer, *bufferend, *bp, *cp;
	    int fd, size;
	    struct stat stbuf;

	    /* Read from default ttyloc file. */
	    if (!newdefault)	/* Tack on users home directory? */
	    {
		char *name = getlogin();
		struct passwd *pw;

		if (name == NULL)
		{
		    fprintf(stderr, "%s: can't figure you out.\n", progname);
		    exit(-1);
		}

		if ((pw = getpwnam(name)) == (struct passwd *)NULL)
		{
		    fprintf(stderr, "%s: can't find your home directory.\n",
			    progname);
		    exit(-1);
		}
		ttyfile = mymalloc(strlen(pw->pw_dir) + 1 +
			       sizeof(DEFAULT_TTYLOC_FILE));

		strcpy(ttyfile, pw->pw_dir);
		strcat(ttyfile, "/");
		strcat(ttyfile, DEFAULT_TTYLOC_FILE);
	    }

	    if ((fd = open(ttyfile, O_RDONLY)) < 0)
	    {
		fprintf(stderr, "%s: couldn't open defaults file %s (%s).\n",
			progname, ttyfile, puterr(errno));
		exit(-1);
	    }

	    if (fstat(fd, &stbuf) < 0)
	    {
		fprintf(stderr, "%s: couldn't stat defaults file %s (%s).\n",
			progname, ttyfile, puterr(errno));
		exit(-1);
	    }

	    size = stbuf.st_size;
	    buffer = mymalloc(size + 1);
	    bufferend = buffer + size;

	    if (read(fd, buffer, size) != size)
	    {
		fprintf(stderr, "%s: read failed on %s (%s).\n", progname,
			ttyfile, puterr(errno));
		exit(-1);
	    }

	    bp = buffer;
	    while (bp < bufferend)
	    {
		for (cp = bp; *bp != ':' && bp < bufferend; ++bp) ;

		*bp++ = '\0';
		if (!strcmp(cp, tty_name) || !strcmp(cp, "default"))
		{
		    ttymess = bp;
		    while (*bp != '\n' && bp < bufferend)
			bp++;
		    *bp = '\0';
		    break;
		}
		else
		{
		    while (*bp != '\n' && bp < bufferend)
			++bp;

		    if (*bp == '\n' && bp < bufferend)
			++bp;
		}
	    }
	}

    if (specified || dflag)
    {
	if (set_ttyloc(tty_name, ttymess) == -1)
	{
	    fprintf(stderr, "%s: couldn't set ttyloc.\n", progname);
	    exit(-1);
	}
    }
    else
	if ((ptr = get_ttyloc(tty_name)) == NULL)
	{
	    fprintf(stderr, "%s: No ttyloc entry for %s.\n", progname,
		    tty_name);
	    exit(-1);
	}
	else
	    printf("%.*s\n", strnlen(ptr, TTYLOC_LENGTH), ptr);

    exit(0);
}

usage()
{
    fprintf(stderr, "%s: usage %s [-d [deffile]] [-t ttyname].\n", progname,
	    progname);
    exit(-1);
}
