|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 14533 (0x38c5)
Types: TextFile
Names: »move.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z«
└─⟦dcb95597f⟧
└─⟦this⟧ »move.c«
#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;
}