|
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; }