DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T t

⟦82fb23901⟧ TextFile

    Length: 7427 (0x1d03)
    Types: TextFile
    Names: »trash-channel.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« 
        └─⟦e5a54fb17⟧ 
            └─⟦this⟧ »pp-5.0/Chans/trashman/trash-channel.c« 

TextFile

/* trash_channel.c: message trash collection channel */

# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/trashman/RCS/trash-channel.c,v 5.0 90/09/20 15:55:03 pp Exp Locker: pp $";
# endif

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Chans/trashman/RCS/trash-channel.c,v 5.0 90/09/20 15:55:03 pp Exp Locker: pp $
 *
 * $Log:	trash-channel.c,v $
 * Revision 5.0  90/09/20  15:55:03  pp
 * rcsforce : 5.0 public release
 * 
 */



#include        <sys/param.h>
#include        "head.h"
#include        "qmgr.h"
#include        "q.h"
#include        "prm.h"
#include        <sys/stat.h>
#include        <sys/file.h>
#include        <isode/usr.dirent.h>


extern char     *mquedir;
extern char     *aquedir;
extern char	*tquedir;
extern char     *quedfldir;
extern char     *chndfldir;
extern CHAN     *ch_nm2struct();
extern void	rd_end(), sys_init(), err_abrt();
extern time_t	time();
/* CHANGE LATER */
char *cmdname = "xtake_out_the_trash";
CHAN            *mychan;

static struct type_Qmgr_DeliveryStatus *process ();
static int initialise ();
static void dirinit ();

/* \f

 */
/* main routine */

main (argc, argv)
int     argc;
char    **argv;
{
	sys_init(argv[0]);
	dirinit ();
#ifdef PP_DEBUG
	if (argc>1 && (strcmp(argv[1],"debug") == 0))
		debug_channel_control(argc,argv,initialise,process,NULLIFP);
	else
#endif
		channel_control (argc, argv, initialise, process, NULLIFP);
}

/* \f

 */
/* routine to move to correct place in file system */

static void dirinit ()
{
	if (chdir (quedfldir) < 0)
		err_abrt (RP_LIO, " Unable to change directory to '%s'",
			  quedfldir);
}

/* \f

 */
/* routine to initialise channel */
/* also does all the work */

char    fullname[MAXPATHLEN];
char    currentdir[MAXPATHLEN];
time_t  interval, 
	current;

#define DEFAULT_INTERVAL        (60*60*24*3)	/* 3 days for normal files */
#define TMP_INTERVAL		(60*60*24)	/* 1 day for temp files */

int	hasMsg(entry)
struct dirent	*entry;
{
	struct	stat statbuf;

	if ((strcmp(entry->d_name,".") == 0)
	    || (strcmp(entry->d_name, "..") == 0))
	    return 0;

	/* fullname */
	(void) sprintf(fullname, "%s/%s", mquedir, entry->d_name);
	if (stat(fullname, &statbuf) != OK)
		PP_OPER(NULLCP,
			("Addr file '%s' does not have a msg directory",
			 entry->d_name));
	else if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
		PP_OPER(NULLCP,
			("Msg entry for '%s' is not a directory",
			 entry->d_name));
	return 0;
}
		
	    
int     isDir(entry)
struct dirent   *entry;
{
	struct stat statbuf;

	if ((strcmp(entry->d_name,".") == 0)
	    || (strcmp(entry->d_name,"..") == 0))
		return 0;

	/* fullname */
	(void) sprintf(fullname, "%s/%s", mquedir,entry->d_name);

	if ((stat(fullname,&statbuf) == OK)
	    && ((statbuf.st_mode & S_IFMT) == S_IFDIR))
		/* directory */
		return 1;
	else
		/* ignore */
		return 0;
}

int isOld (entry)
struct dirent *entry;
{
	struct stat statbuf;

	if (strcmp (entry->d_name, ".") == 0 ||
	    strcmp (entry->d_name, "..") == 0)
		return 0;
	(void) sprintf (fullname, "%s/%s", tquedir, entry->d_name);
	if (stat (fullname, &statbuf) == NOTOK)
		return 0;
	if (current - statbuf.st_mtime > TMP_INTERVAL) {
		PP_NOTICE (("Removing temp message %s", entry->d_name));
		currentdir[0] = 0;
		if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
			rec_rmdir (fullname);
		else
			if (unlink (fullname) == NOTOK)
				PP_SLOG (LLOG_EXCEPTIONS, fullname,
					 ("Can't unlink file"));
	}
	return 0;
}

static int initialise (arg)
struct type_Qmgr_Channel *arg;
{
	char *name;
	int     num,
		i;
	struct dirent **namelist, **ix;


	name = qb2str(arg);

	if ((mychan = ch_nm2struct(name)) == NULLCHAN) {
		PP_OPER(NULLCP,
			("Channel '%s' not known",name));
		if (name != NULL) free(name);
		return NOTOK;
	}
	if (name != NULL) free(name);
	interval = DEFAULT_INTERVAL;
	(void) time(&current);

	num = _scandir(mquedir, &namelist, isDir, NULLIFP);

	i = 0;
	ix = namelist;
	while ((i++ < num) && (*ix != 0)) {

		if (check_addrfile((*ix)->d_name)!= OK)
			/* addr file does not exist or has not been touched for a while */
			/* try trash collection */
			trashcollect((*ix)->d_name);
		ix++;
	}
	free((char *)namelist);

	/* now check for addr files with no msg directories */

	num = _scandir(aquedir, &namelist, hasMsg, NULLIFP);

	/* now check the tmp directory for junk */

	num = _scandir (tquedir, &namelist, isOld, NULLIFP);

	return OK;
}

int check_addrfile(name) 
char    *name;
{
	struct stat statbuf;
	struct prm_vars prm;
	Q_struct        que;
	ADDR            *sender = NULL;
	ADDR            *recips = NULL;
	int             rcount;
	ADDR            *ix = NULL;

	bzero ((char *)&prm, sizeof(prm));
	bzero ((char *)&que, sizeof(que));

	(void) sprintf(fullname, "%s/%s", aquedir,name);
	if (stat(fullname,&statbuf) != OK) 
		/* no addr file so try trash */
		return NOTOK;
	else {
		if ((current - statbuf.st_mtime) > interval) {
			/* check to see if all recipients are done */

			if (rp_isbad(rd_msg(name,&prm,&que,&sender,&recips,&rcount))) {
				PP_LOG(LLOG_EXCEPTIONS,
				       ("rd_msg failure: '%s'", name));
				/* don't delete */
				return OK;
			}
			rd_end();

			ix = que.Oaddress;
			while ((ix != NULL) && (ix->ad_status == AD_STAT_DONE))
				ix = ix->ad_next;
			if (ix != NULL) 
				/* don't trash as some work needs to be done */
				return OK;
			/* now the recips */
			ix = que.Raddress;
			while ((ix != NULL) && (ix->ad_status == AD_STAT_DONE))
				ix = ix->ad_next;
			if (ix != NULL) 
				/* don't trash as some work needs to be done */
				return OK;

			return NOTOK;
		}
	}
	return OK;
}

trashcollect(name)
char    *name;
{
	struct stat statbuf;
	(void) sprintf(fullname, "%s/%s", mquedir,name);
	if (stat(fullname,&statbuf) == OK) {
		if ((current - statbuf.st_mtime) > interval) {
			PP_NOTICE (("trash removing '%s'", name));
			currentdir[0] = '\0';
			rec_rmdir(fullname);
			/* now remove addr file if there */
			sprintf(fullname,"%s/%s", aquedir, name);
			if (stat(fullname,&statbuf) == OK)
				unlink(fullname);
		}
	}
}

int rmFiles(entry)
struct dirent *entry;
{
	struct stat statbuf;

	if ((strcmp(entry->d_name,".") == 0)
	    || (strcmp(entry->d_name,"..") == 0))
		return 0;
	/* full name */
	(void) sprintf(fullname,"%s/%s",currentdir,entry->d_name);

	if ((stat(fullname,&statbuf) == OK) 
	    && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) 
		return 1;
	else {
		if (unlink(fullname) == NOTOK)
			PP_SLOG(LLOG_EXCEPTIONS,fullname,("can't remove file"));
		return 0;
	}
}

/* recursive rmdir */
rec_rmdir(dir)
char    *dir;
{
	struct dirent **namelist, **ix;
	int             noOfSubdirs, i;
	char            *temp;

	if (currentdir[0] == '\0') 
		strcpy(currentdir,dir);
	else 
		(void) sprintf(currentdir,"%s/%s",currentdir,dir);

	noOfSubdirs = _scandir(currentdir,&namelist, rmFiles, NULLIFP);

	i = 0;
	ix = namelist;
	while ((i++ < noOfSubdirs) && (*ix != NULL)) {
		rec_rmdir((*ix)->d_name);
		ix++;
	}

	if (rmdir(currentdir) == NOTOK) 
		PP_SLOG(LLOG_EXCEPTIONS,currentdir,
			("unable to remove directory"));


	/* knock of one level of directories */
	if ((temp = (char *) rindex(currentdir, '/')) != NULL)
		*temp = '\0';

	free((char *) namelist);
}



/* \f

 */
/* all work done in initialise */
/* process is just a dummy routine */

static struct type_Qmgr_DeliveryStatus *process (arg)
struct type_Qmgr_ProcMsg *arg;
{
	delivery_init(arg->users);
	delivery_setall(int_Qmgr_status_success);
	return deliverystate;
}