/*
 * $Id: close.c,v 1.5 2002/08/23 13:38:14 howardjp Exp $
 *
 * Copyright (c) 1990
 *      Jan Wolter.  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 Jan Wolter
 *      and his contributors.
 * 4. Neither the name of Jan Wolter nor the names of his contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY JAN WOLTER AND CONTRIBUTORS ``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 JAN WOLTER OR CONTRIBUTORS 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.
 */

/* PARTY PROGRAM -- ROUTINES TO HANDLE CLOSED CHANNELS -- Jan Wolter */

#ifndef NOCLOSE

#include "party.h"
#include "opt.h"
#include <setjmp.h>
#include <errno.h>

extern jmp_buf jenv;
extern int inhelp;

/* USR_FILE_NAME: Return the name of the user file name associated with the
 * given channel name.  This must be free()ed by someone else eventually.
 * This will normally contain a list of login id's, listed one per line, of
 * people who are permitted to join the channel.
 */

char *usr_file_name(chn)
char *chn;
{
char *usr_file;

    usr_file= (char *)malloc((mtype)(strlen(opt[OPT_DIR].str)+CHN_LEN+6));
    sprintf(usr_file,"%s/%s.usr", opt[OPT_DIR].str, chn);
    return(usr_file);
}


/* CHECK_OPEN:  This checks to see if we can enter the named channel.  Return
 * codes are:
 *   0 - channel is closed and we aren't allowed in. 
 *   1 - channel is open.
 *   2 - channel is closed and we are allowed in. 
 */

int check_open(chn)
char *chn;
{
FILE *fp;
char *fn;
char buf[BFSZ+1];

    /* Open the user list -- if it doesn't exist, anyone can enter */
    fp= fopen(fn= usr_file_name(chn),"r");
    free(fn);
    if (fp == NULL) return(1);

    /* See if I am in the user list */
    while (fgets(buf,BFSZ,fp) != NULL)
    {
	*firstin(buf," \t\n")= '\0';
	if (!strcmp(buf,realname))
	{
	    fclose(fp);
	    return(2);
	}
    }
    fclose(fp);
    return(0);
}


/* IS_CLOSED:  Is the channel the user is in closed? */

int is_closed()
{
char *fn;
int rc;

    if (channel == NULL) return(0);
    rc= access(fn= usr_file_name(channel), 0);
    free(fn);
    return(!rc);
}

/* OPEN_CHAN:  Open up the current channel */

open_chan()
{
char *fn;
long now= time((long *)0);

    if (channel == NULL) return;
    unlink(fn= usr_file_name(channel));
    free(fn);

    /* Closable channels are now left depermitted even when open */
    /*fchmod(rst,CHN_MODE);*/

    sprintf(txbuf, "---- %s opened this channel (%.12s)\n",name,ctime(&now)+4);
    append(txbuf,wfd);
}


/* CLOSE_CHAN:  Close the current channel.  Create the .usr file and write in a list of
 * the people already in the channel. */

close_chan()
{
char *fn;
int fd;
FILE *fp;
long now= time((long *)0);

    if (channel == NULL) return;
    fd= open(fn= usr_file_name(channel),O_WRONLY|O_CREAT|O_EXCL,USR_MODE);
    free(fn);
    if (fd < 0)
    {
	if (errno == EEXIST)
		printf("channel is already closed\n");
	else
		printf("error - cannot create user file\n");
	return;
    }

    fp= fdopen(fd,"w");
    who_ison(fp,channel);
    fclose(fp);

    /* Closable channels are now left depermitted even when open */
    /*fchmod(rst,DEP_MODE);*/

    sprintf(txbuf, "---- %s closed this channel (%.12s)\n",name,ctime(&now)+4);
    append(txbuf,wfd);
}


/* INVITE:  invite a user into the the channel.  Well, really just permit them
 * to enter.
 */

invite(login)
char *login;
{
char *fn;
FILE *fp;
long now= time((long *)0);

    if (channel == NULL) return;
    fp= fopen(fn= usr_file_name(channel),"a");
    free(fn);
    if (fp == NULL)
    {
	printf("error - cannot append to user file\n");
	return;
    }

    fprintf(fp,"%s\n",login);

    fclose(fp);

    sprintf(txbuf, "---- %s invited %s to this channel (%.12s)\n",name,
	    login,ctime(&now)+4);
    append(txbuf,wfd);
}


/* READYN -- in cooked mode, read in a line.  It it starts with Y, return true.
 */

int read_yn()
{
int ch;

    if ((ch= getchar()) != '\n')
	while (getchar() != '\n')
		;
    return(ch == 'y' || ch == 'Y');
}
	
/* KNOCK -- stuff a knock-knock message into the named channel.
 */

knock(chn)
char *chn;
{
char bf[BFSZ], *fn;
FILE *tmp_wfd;

    sprintf(bf,"---- %s knocking on the door\n",logname);
    /* No time on this message so norepeat can be used against knock bombers */
    if (access(fn= chn_file_name(chn,0), 0))
	fn= chn_file_name(chn,1);
    if ((tmp_wfd= fopen(fn,"a")) == NULL)
	return(1);
    append(bf,tmp_wfd);
    fclose(tmp_wfd);
    return(0);
}

/* ENTER_CLOSED -- Go through the business of passing the doorway of a
 * channel.  If it is closed (a .usr file exists), check if we are in it.
 * If not, go through the knocking routine.  Return codes are:
 *
 *   0 - channel is closed and we aren't allowed in. 
 *   1 - channel is open.
 *   2 - channel is closed and we are allowed in. 
 */

enter_closed(newchannel)
char *newchannel;
{
int was_open;
int i= 0;

    /* If he already has access, let him in */
    if (was_open= check_open(newchannel)) return(was_open);

    /* If the user doesn't want to knock, keep him out */
    err("channel %s is a closed channel\n",newchannel);
    fprintf(stderr,"Would you like to knock on the door? ");
    if (!read_yn()) return(0);

    /* Do the knock */
    if (!setjmp(jenv))
    {
	inhelp= 1;
	fprintf(stderr,"Waiting...");
	fflush(stderr);
	knock(newchannel);
	while (!check_open(newchannel))
	{
	    if (i++ >= convert(opt[OPT_KNOCKWAIT].str))
	    {
		fprintf(stderr,"there seems to be no answer\n");
		/*unknock(newchannel);*/
		return(0);
	    }
	    sleep(1);
	}
	inhelp= 0;
	return(2);
    }
    else
    {
	inhelp= 0;
	fprintf(stderr,"wait interrupted\n");
	return(0);
    }
}
#endif /* NOCLOSE */


syntax highlighted by Code2HTML, v. 0.9.1