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 m

⟦15dd2c4d2⟧ TextFile

    Length: 14533 (0x38c5)
    Types: TextFile
    Names: »move.c«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z« 
        └─⟦dcb95597f⟧ 
            └─⟦this⟧ »move.c« 

TextFile

#ifndef lint
static char rcsid[] =
	"$Header: move.c,v 2.11 88/01/13 19:08:30 deboor Exp $";

static char notice[] =
	"This program is in the public domain and is available for unlimited \
distribution as long as this notice is enclosed.";
#endif

/*
 * Routines to move messages between folders
 *
 * $Source: /c/support/deboor/usr/src/old/vmh/RCS/move.c,v $
 * $Revision: 2.11 $
 * $Author: deboor $
 *
 * FUNCTIONS:
 *	cmdDelete	delete messages
 *	cmdLink		link messages
 *	cmdMove		move messages
 *	getfolderpath	prompt for and verify folder name with default
 *	mkfolder	prompt to and create a folder
 *	path_ok		prompt for and verify new folder
 *	renamemsg	rename one message to anothe in current folder
 */

#include "vmh.h"

/*
 *  Current lackings:
 *      a) Can't move to another filesys
 *      b) Doesn't work right if moving to self
 */

cmdMove(count, undo, ac, av)
	int	count,
		undo,
		ac;
	char	**av;
{
	static	char	dest[PATHLENGTH];         /* Dest folder name */
	static	int	rc;
	static	int	undone;
	register int	*msgs;
	FLDR		*dF;
	char		*srcname = F->f_name;	/* for undo */
	
	register	i;

	if ((msgs = GetMessages(&count)) == NULL)
		return;
	if (count > 1) {
		prt_action (" %sove messages %d..%d ",(undo && !undone)?
			"Unm":"M",msgs[0],msgs[count-1]);
	} else
		prt_action (" %sove message %d ",(undo && !undone)?
			"Unm":"M", msgs[0]);
				/**** Prompt and get dest folder name ****/
	if (! undo ) {
		/*
		 * this is a normal move. if no folder given as argument,
		 * prompt for one. pass through msgs array doing a movesub
		 * on each one, letting it decide where to put the damn thing.
		 * If at any time path_ok returns true, break out of the loop
		 */
		if (ac) {
			(void) strcpy (dest, av[0]);
			rc = getpath (dest, dest, sizeof(dest));
		} else
			rc =getfolderpath("Move to folder",dest,sizeof(dest),1);

	do_move:
		undone = 0;
		for (i = 0; msgs[i]; i++) {

			if( path_ok( rc, dest, "new" ) == 0 ) {
#ifdef DEBUG
				DeBuG ("moving message %d to |%s| # %d\n", msgs[i], dest, getF(dest)->f_msgs.m_hghmsg + 1);
#endif
				movesub(srcname, dest, 1, msgs[i], 0);
				if (rc == 1)
					rc = 0;
			} else {
				i++;
				break;
			}

		}
	} else if (!undone) {
		/*
		 * we are undoing what we did last time.
		 */
		undone = 1;
		if (rc) {
			errormsg ("that folder was bad last time", 1);
			return;
		}
		dF = getF(dest);
		for (i = 0; msgs[i]; i++)
			;		/* get to the end of the array */
		for (i--; i >= 0; i--) {

#ifdef DEBUG
			DeBuG ("src = |%s| dest = |%s| srcno = %d destno = %d",
				srcname, dest, msgs[i], F->f_msgs.m_hghmsg);
#endif
			movesub (dest, srcname, 1, dF -> f_msgs.m_hghmsg, msgs[i]);
		}
		i = 1;
	} else {
		if (rc) {
			errormsg ("that folder was bad last time", 1);
			return;
		}
		goto do_move;
	}

	scroll_to (msgs[i-1]);	/* goes to the one after the last moved one */
}

cmdLink(count, undo)
	int	count;
	int	undo;
{
	static	char	dest[PATHLENGTH];         /* Dest folder name */
	static	int	rc;
	static	int	undone;
	char		*dmsg;
	struct	fldr	*f;
	register int	*msgs;
	
	register	i;

	if ((msgs = GetMessages(&count)) == NULL)
		return;
	if (count > 1) {
		prt_action (" %sink messages %d..%d ",(undo && !undone)?
			"Unl":"L", msgs[0], msgs[count-1]);
	} else
		prt_action (" %sink message %d ",(undo && !undone)?
			"Unl":"L", msgs[0]);
				/**** Prompt and get dest folder name ****/
	if ( ! undo) {
		rc = getfolderpath("Link to folder", dest, sizeof(dest), 1);

	do_link:
		undone = 0;
		for (i = 0; msgs[i]; i++) {

			if( path_ok( rc, dest, "new" ) == 0 ) {
				movesub(F->f_name, dest, 0, msgs[i], 0);    /* Zero means don't delete the src! */
				if (rc == 1)
					rc = 0;
			} else {
				i++;
				break;
			}

		}
	} else if (!undone) {
		undone = 1;
		if (rc) {
			errormsg ("that folder was bad last time", 1);
			return;
		}
		f = getF(dest);
		dmsg = dest + strlen(dest);
		for (i = 0; msgs[i]; i++) {
			(void) sprintf (dmsg, "/%d", f->f_msgs.m_hghmsg);
			(void) unlink (dest);
			unlinkinfo (findinfoR(f->f_msgs.m_hghmsg,f->f_tail), f);
			Del_Msg (f->f_msgs.m_hghmsg, &f->f_msgs);
			f->f_msgs.m_nummsg--, f->f_msgs.m_hghmsg--;
		}
		*dmsg = '\0';
	} else {
		if (rc) {
			errormsg ("that folder was bad last time", 1);
			return;
		}
		goto do_link;
	}
	scroll_to (msgs[i-1]);
}

cmdDelete(count, undo)
	int	count,
		undo;
{
	char		dest[PATHLENGTH];
	static		rc;
	static		undone = 0;
	FLDR		*dF;
	char		*srcname = F->f_name;
	register int	*msgs;
	register	i;

	if ((msgs = GetMessages(&count)) == NULL)
		return;
	if (count > 1) {
		prt_action (" %selete messages %d..%d ",(undo && !undone)?
			"Und":"D", msgs[0], msgs[count-1]);
	} else
		prt_action (" %selete message %d ",(undo && !undone)?
			"Und":"D", msgs[0]);

	rc = getpath("deleted", dest, sizeof(dest));

	if (! undo) {
	do_delete:
		undone = 0;
		for (i = 0; msgs[i]; i++) {

			if( path_ok( rc, dest, "`deleted\'" ) == 0 ) {
#ifdef DEBUG
				DeBuG ("moving message %d to |%s| # %d\n", msgs[i], dest, getF(dest)->f_msgs.m_hghmsg + 1);
#endif
				movesub(F->f_name, dest, 1, msgs[i], 0);
				if (rc == 1)
					rc = 0;
			} else {
				i++;
				break;
			}
		}
	} else if (! undone) {
		/*
		 * we are undoing what we did last time.
		 */
		undone = 1;
		if (rc) {
			errormsg (" deleted folder was bad last time ", 1);
			return;
		}
		dF = getF(dest);
		for (i = count - 1; i >= 0; i--) {

#ifdef DEBUG
			DeBuG ("src = |%s| dest = |%s| srcno = %d destno = %d",
				srcname, dest, msgs[i], dF->f_msgs.m_hghmsg);
#endif
			movesub (dest, srcname, 1, dF ->f_msgs.m_hghmsg, msgs[i]);
		}
		i = 1;	/* display 1st restored message */
	} else {
		if (rc) {
			errormsg (" deleted folder was bad last time ", 1);
			return;
		}
		goto do_delete;
	}
	scroll_to (msgs[i-1]);
	if (F->f_cur->i_mnum >= msgs[i-1] && autoprint)
		cmdType (1, 0, 0, (char **) 0);
	CurSequence = msgs;
}

/*
 *  check return code from getpath, possibly prompting user
 *      to create new folder.
 */

path_ok( rc, name, prompt )
	register int rc;
	register char *name;
	register char *prompt;
{

	switch( rc ) {
	    case 0:                 /* ok */
		break;

	    case 1:                 /* folder didn't exist */
		if( mkfolder( name, prompt ) < 0 )
		    return( 1 );
		break;

	    case -2:                /* no write access */
		errormsg("No write access to that folder!", 0);
		return( 1 );

	    case -3:
		errormsg("Need non-empty folder name", 0);
		return( 1 );

	    case 2:                 /* quit signal in mywgetstr... */
		return( 1 );

	    default:
		errormsg( "Can't do that here.", 0 );
		return( 1 );
	}

	return( 0 );
}

/*
 * Move srcmsgno msg into destfolder
 */

movesub(srcfolder, destfolder, deleteflg, srcmsgno, destmsgno)
	char	*srcfolder,
		*destfolder;
	int	deleteflg;          /* If non-zero, delete from src folder */
	int	srcmsgno;		/* source message number */
	int	destmsgno;		/* new dest number...if != 0 */
{
	char			srcmsg[PATHLENGTH];       /* Source foldername/number */
	char			destmsg[PATHLENGTH];      /* Dest foldername/number */
	char			line[150];         /* Line of text from .info file (& temp) */
	
	register FLDR		*fSrc,
				*fDest;     /* Folder structure for destination */
	
	register struct msgs	*m;
	
	INFO			*ss;


	fDest = getF(destfolder);       /* Get (or build) F for destination */
	fSrc = getF(srcfolder);

				/**** Make full dest msg pathname **/
	if (! destmsgno)
		destmsgno = nextmsgno(&fDest->f_msgs);   /* Get "next msg" number of folder */
#ifdef DEBUG
	DeBuG (" destmsgno = %d\n", destmsgno);
#endif
	if (destmsgno < 0)
		return;     /* If can't, return */
	if (!destmsgno) {
		errormsg ("destmsgno still 0", 1);
		cmdShowM();
		return;
	}

	(void) sprintf(destmsg, "%s/%d", destfolder, destmsgno);

				/**** Make full src msg pathname ***/
	(void) sprintf(srcmsg, "%s/%d", srcfolder, srcmsgno);
	if (srcmsgno <= 0) {
		errormsg("Bad source msg number", 1);
		return;
	}

	if (link(srcmsg, destmsg) != 0)  /* Copy over (to same filesys) */
	{
		(void) sprintf(line, "Couldn't link %s to %s", &srcmsg[rootlen+1],
			&destmsg[rootlen+1]);
		errormsg(line, 1);
		return;
	}

					/*** Get the info record for the msg ***/
	ss = findinfoR (srcmsgno, fSrc->f_cur);
	if (ss->i_mnum != srcmsgno)
		punt ("info record # not same as source message number");

	if (deleteflg)          /* Delete file, update src .info */
	{
		int	diff = i_diff (F->f_top, ss);

		(void) unlink(srcmsg);        		/* Delete src file */

		unlinkinfo (ss, fSrc);

		m = &fSrc->f_msgs;
		Del_Msg (srcmsgno, m);			/* mark it as gone */
		m->m_nummsg--;					/* " */
		if (srcmsgno == m->m_hghmsg && fSrc->f_tail) {
			m->m_hghmsg = fSrc->f_tail->i_mnum;
		}
		if (srcmsgno == m->m_lowmsg && fSrc->f_head) {
			m->m_lowmsg = fSrc->f_head->i_mnum;
		}
				
		if (fSrc == F && diff >= 0 && diff < topSize) {
			mydeleteline(topWin, diff,
			 topWin->_maxy -1);
		}
		/* play with pointers here */
		/*
		 * if we mucked with any of the pointers, move them forward one, if possible.
		 *	is this The Right Thing?
		 */
		if (ss == fSrc->f_cur)
			fSrc->f_cur = (fSrc->f_cur->i_next) ? fSrc->f_cur->i_next : fSrc->f_cur->i_prev;
		if (ss == fSrc->f_top)
			fSrc->f_top = (fSrc->f_top->i_next) ? fSrc->f_top->i_next : fSrc->f_top->i_prev;

		if (fSrc == F && diff >= 0 && diff < topSize) {
			showinfo();                     /* Update screen */
			wrefresh(topWin);               /* Sigh */
		}

	} else {	/* make duplicate of info entry for dest folder */
		INFO	*sd = AllocST(INFO);

		Bcopy (ss, sd, sizeof (INFO));
		ss = sd;
	}
				/* Update destination folder info */

	ss->i_mnum = destmsgno;	/* set in new message number */
	linkinfo (ss, fDest);	/* link it in */

	if (fDest->f_head == fDest->f_tail) /* Special case for transition from */
	{                               /* empty to non-empty folder */
					/* must set f_top and f_cur */
		fDest->f_top = fDest->f_cur = fDest->f_head;
	}

	/* mark the new number as existing */
	Add_Msg (destmsgno, &fDest->f_msgs);

	if (destmsgno > fDest->f_msgs.m_hghmsg)
		fDest->f_msgs.m_hghmsg = destmsgno;
	if (destmsgno < fDest->f_msgs.m_lowmsg)
		fDest->f_msgs.m_lowmsg = destmsgno;
	fDest->f_msgs.m_nummsg++;

	werase(cmdWin);
	wrefresh(cmdWin);
}


/*
 * getfolderpath:
 *
 *      input:  string to prompt user with
 *              string space to put full folder path, size of it
 *      output:
 *              folder path filled in
 *              returns same return code as getpath()
 */

char lastfolder[PATHLENGTH];   /* Assumes gets init'd to zero by loader */

getfolderpath(prompt, folder, szfolder, defaultflg)
	char	*prompt,
		*folder;
	int	szfolder;
	int	defaultflg;    /* If non-zero, ok to default to "last" buffer */
{
	int t;
	char newprompt[80];

	/*
	 *  If we're called by "move" or "link" (the default flag is set)
	 *      and there was a last folder, notify user that he gets
	 *      the last folder if he hits <CR>.
	 *  Otherwise, we're doing a "change" and <CR> gives "inbox".
	 */

	(void) sprintf( newprompt, "%s +", prompt );

	if( defaultflg )
		(void) strcpy(folder, lastfolder);
	else
		(void) strcpy(folder, "inbox");

	wclear(cmdWin);
	wmove(cmdWin, 0, 0);
	wprintw(cmdWin, newprompt);        /* Put up the prompt */
	wrefresh(cmdWin);

	t = mywgetstr(cmdWin, folder, 0);  /* Get a string */

	if (t == 0) return(2);          /* Abort now, if getstr aborted */

	if (defaultflg)                 /* If doing last-buffer trick */
		(void) strcpy(lastfolder, folder);   /* Save for next time */

	t = getpath(folder, folder, szfolder);

	return(t);
}

/*
 * Nextmsgno
 *    Input:  msgs structure
 *
 *    Return: integer number for next new msg in folder or -1 if err
 */

nextmsgno(m)
	MSGS	*m;
{
	if (m->m_hghmsg >= MAXFOLDER)     /* If folder already full */
	{
		errormsg("Destination folder is full.", 1);
		return(-1);
	}
	return(m->m_hghmsg + 1);
}


/*
 *  make a new folder
 */

mkfolder( foldername, prompt )
	char	*foldername;
	char	*prompt;
{
	register int	rc;
	char		buf[80],
			cmd[150];
	int		mode;
	char		*folder,
			*rindex();

	/*
	 *  Get last component of foldername
	 */

	folder = rindex( foldername, '/' );
	folder++;

	/*
	 *  Issue the prompt
	 */

	wclear( cmdWin );
	wmove( cmdWin, 0, 0 );
	wprintw( cmdWin, "Create %s folder \"%s\"? (y or n): ",
		prompt, folder );
	wrefresh( cmdWin );

	/*
	 * Check the reply
	 */

	buf[0] = '\0';
	rc = mywgetstr( cmdWin, buf, 0 );
	if( rc == 0 )
		return( -1 );
	if( buf[0] != 'y' && buf[0] != 'Y' ) {
		/*
		 *  Clear lastfolder name so next move or link won't
		 *      be prompted for this default folder name.
		 */
		lastfolder[0] = '\0';
		infomsg( " No action taken.", 0 );
		return( -1 );
	}

	if (mkdir(foldername, FOLDERMODE) < 0 ) {
		wclear( cmdWin );
		wmove( cmdWin, 0, 0 );
		wprintw( cmdWin, "%s failed!", cmd );
		wrefresh( cmdWin );
		lastfolder[0] = '\0';
		return( -1 );
	}

	/*
	 *  Set folder mode.
	 */

	rc = readprofile( "Folder-Protect:", buf, sizeof( buf ));
	if( rc == 1 )   /* found it */
		(void) sscanf( buf, "%o", &mode );
	else
		mode = FOLDERMODE;

	if( chmod( foldername, mode ) < 0 ) {
		wclear( cmdWin );
		wmove( cmdWin, 0, 0 );
		wprintw( cmdWin, "chmod(%s, %o) failed!", foldername, mode );
		wrefresh( cmdWin );
	}

	return( 0 );
}

/*
 * renamemsg(s, d) int s,d;
 *	rename message s to d in the current folder
 */
renamemsg(s, d)
	int	s,
		d;
{
	char srcname[PATHLENGTH];
	char destname[PATHLENGTH];
	int  rc;
	INFO	*ss;
	extern	int	errno,
			sys_nerr;
	extern	char	*sys_errlist[];

				/**** Move the file ****/

	(void) sprintf(srcname,  "%s/%d", F->f_name, s);
	(void) sprintf(destname, "%s/%d", F->f_name, d);

#ifdef DEBUG
	DeBuG ("renaming %s to %s\n", srcname, destname);
#endif

#ifndef BSD4_3
	rc = link(srcname, destname);
	if (rc != 0) {
		char   oops[150];

		(void) sprintf(oops, "Pack: Could not link '%s' to '%s'.",
				&srcname[rootlen+1], &destname[rootlen+1]);
		punt(oops);
	}
	(void) unlink(srcname);
#else BSD4_3
	if (rename (srcname, destname) < 0) {
		char   oops[150];

		(void) sprintf (oops, "pack: couldn't rename %d to %d (%s)",
			s, d, (errno < sys_nerr)?sys_errlist[errno]:"?");
		punt (oops);
	}
#endif

				/**** Update msgs structure ****/
	Del_Msg(s,&F->f_msgs);
	Add_Msg(d,&F->f_msgs);


				/**** Update info structures */

	ss = findinfo (s, F);	/* find it */
#ifdef DEBUG
	if (ss->i_mnum != s) {
		punt ("renamemsg: i_mnum != s");
	}
#endif
	/*
	 * this is all that is needed since the messages stay in the
	 * same order, they just change numbers. So DON'T UNLINK ss!!
	 */
	ss->i_mnum = d;		/* put in new number */

	F->f_modified = 1;

}