home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / mm-0.90 / move.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  9.3 KB  |  325 lines

  1. /*
  2.  * Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  * the City of New York.  Permission is granted to any individual or
  4.  * institution to use, copy, or redistribute this software so long as it
  5.  * is not sold for profit, provided this copyright notice is retained.
  6.  */
  7.  
  8. #ifndef lint
  9. static char *rcsid = "$Header: /f/src2/encore.bin/cucca/mm/tarring-it-up/RCS/move.c,v 2.5 90/10/04 18:25:08 melissa Exp $";
  10. #endif
  11.  
  12. /*
  13.  * move.c - support for the move and copy commands
  14.  */
  15.  
  16. #include "mm.h"                /* for msgvec */
  17. #include "cmds.h"            /* for CMD_MOVE */
  18. #include "parse.h"            /* for atmbuf */
  19. #include "rd.h"                /* for PR_xxx's */
  20.  
  21. /* global guys just for move and copy */
  22. static msgvec *dest;            /* file to copy to */
  23. static int delete;            /* delete the message after copy? */
  24. static int copy_err;            /* did we have a problem copying? */
  25.  
  26. msgvec *getdestfile();            /* get this type right... */
  27. int do_copy();                /* this exists... */
  28.  
  29. /*
  30.  * cmd_move:
  31.  * copy a message from the current file to another file
  32.  * if n = CMD_MOVE, delete it as well
  33.  */
  34. int
  35. cmd_copy (n)
  36. int n;
  37. {
  38.     string fname;            /* new file to copy to */
  39.     int format;                /* format to use for new file */
  40.  
  41.     if (!check_cf (O_RDONLY))        /* make sure we have current file */
  42.     return;
  43.     delete = (n == CMD_MOVE);        /* delete if it's "move" not "copy" */
  44.  
  45.     noise ("into file");        /* hint hint */
  46.     parse_copyfile (fname, &format);    /* parse filename and maybe switches */
  47.  
  48.     parse_sequence ("current",NULL,NULL); /* parse a message sequence */
  49.  
  50.     if (delete && (cf->flags & MF_RDONLY)) { /* trying to delete? */
  51.     if (modify_read_only == SET_NEVER) {
  52.        fprintf(stderr, 
  53.            "Warning: cannot modify a file visited with \"examine\"\n");
  54.        delete = FALSE;        /* don't bother trying */
  55.         }
  56.     else if (modify_read_only == SET_ASK)
  57.        delete = yesno("File is read-only, delete messages anyway? ", "no");
  58.     }
  59.     dest = getdestfile (fname, format,
  60.                        (cmcsb._cmflg & CM_ITTY) ? TRUE : FALSE);
  61.         if (dest == NULL) {
  62.     return false;
  63.     }
  64.     sequence_loop (do_copy);        /* copy each message */
  65.     (*msg_ops[dest->type].close)(dest->filep); /* close it */
  66.     free (dest);            /* maybe free other guys too */
  67.     if ((mode == MM_TOP_LEVEL) && !copy_err)
  68.     seq_print (true);
  69.     return true;
  70. }
  71.  
  72. /*
  73.  * parse_copyfile:
  74.  * parse the switches for the move/copy command and the filename
  75.  * switches are optional, filename is not
  76.  */
  77. parse_copyfile (name,ptype)
  78. char name[];
  79. int *ptype;
  80. {
  81.     pval parseval;
  82.     fdb *used;
  83.     extern keytab formattab;
  84.     static char *def = NULL;
  85.     extern char cmswbeg;
  86.     static fdb formatfdb = {
  87.     _CMSWI, 0, NULL, (pdat)&formattab, NULL, NULL, NULL };
  88.     static fdb filefdb = {
  89.     _CMFIL, FIL_PO|FIL_VAL, NULL, NULL, "file to copy to", 
  90.     NULL, NULL};
  91.     filblk fb;
  92.     char *dirs[3];
  93.     char *cp;
  94.     char wd[MAXPATHLEN];
  95.     char *getwd();
  96.  
  97.     /* don't list files twice, also if mail_directory is unset, it means "." */
  98.     if (mail_directory[0] == '\0' || same_file(mail_directory, ".")) {
  99.     dirs[0] = ".";
  100.     dirs[1] = nil;
  101.     }
  102.     else {
  103.     dirs[0] = mail_directory;
  104.     dirs[1] = ".";
  105.     }
  106.     dirs[2] = nil;
  107.  
  108.     fb.pathv = dirs;
  109.     fb.exceptionspec = nil;
  110.     fb.def_extension = nil;
  111.     filefdb._cmdat = (pdat) &fb;
  112.  
  113.     /* set up defaults for parse */
  114.     if (def != nil)            /* in case of reparse */
  115.     free(def);
  116.     if (default_mail_type.current != NULL) {
  117.     def = (char *) malloc (strlen (default_mail_type.current) +2);
  118.     def[0] = cmswbeg;
  119.     strcpy (&def[1], default_mail_type.current); /* get our default */
  120.     }
  121.     else
  122.     def = NULL;
  123.     formatfdb._cmdef = def;        /* insert the default */
  124.     *ptype = -1;            /* mark that it hasn't been set */
  125.  
  126.     if (directory_folders)
  127.     filefdb._cmffl &= ~FIL_NODIR;
  128.     else
  129.     filefdb._cmffl |= FIL_NODIR;
  130.     parse(fdbchn (&formatfdb,&filefdb,NULL), &parseval, &used);
  131.     if (used == &formatfdb) {
  132.     *ptype = parseval._pvint;    /* what they want */
  133.     parse (fdbchn (&filefdb,NULL), &parseval, &used); /* NEED a file */
  134.     }
  135.  
  136.     free (def);                /* free us some space */
  137.     def = NULL;
  138.  
  139.     /* handle the parsed file now */
  140. #ifdef UNDEF
  141.     if (rindex(parseval._pvfil[0], '/') == NULL) { /* XXX assumes name */
  142.     if (access (parseval._pvfil[0], F_OK) != 0 && /* XXX is big enough */
  143.         mail_directory[0] != '\0')               
  144.         sprintf (name, "%s/%s", mail_directory, parseval._pvfil[0]);
  145.     else
  146.         sprintf (name, "./%s", parseval._pvfil[0]);
  147.     }
  148.     else                /* directory specified by user */
  149.     strncpy(name, parseval._pvfil[0], STRLEN);
  150. #endif /* UNDEF */
  151.  
  152.     /* ****  SEE ALSO, similar code in parse.c: parse_in_out_file **** */
  153.     if (*parseval._pvfil[0] == '/') {        /* absolute path specified */
  154.       strcpy (name, parseval._pvfil[0]);
  155.     }
  156.     else {
  157.     /* 
  158.      * file does not exist in mail-directory (mail-directory is an
  159.      * absolute path), so see if it is in .
  160.      * in which case use it, otherwise, try to default to new file
  161.      * in mail-directory
  162.      */
  163.     if ((index(parseval._pvfil[0], '/') != NULL) || /* a dir specified */
  164.         access (parseval._pvfil[0], F_OK) == 0 || /* file exists in . */
  165.         mail_directory[0] == '\0') { /* or no mail_directory, use wd */
  166.         if (getwd (wd) == NULL) {    /* got some kind of error */
  167.         fprintf (stderr, "%s\n", wd); /* print the error message */
  168.         strcpy (name, parseval._pvfil[0]);
  169.         }
  170.         else {
  171.         cp = parseval._pvfil[0];
  172.         if (cp[0] == '.' && cp[1] == '/')
  173.             cp += 2;
  174.         sprintf (name, "%s/%s", wd, cp);
  175.         }
  176.     }
  177.     else                /* use mail_directory */
  178.         sprintf (name, "%s/%s", mail_directory, parseval._pvfil[0]);
  179.     }
  180.  
  181.     if (access (name, F_OK) != 0)    { /* does it exist? */
  182.     int ok;
  183.     char c = 0;
  184.     char *p = rindex(name, '/');    /* no, check directory */
  185.                     /* (NOTE: there WILL be a slash) */
  186.     c = *p; *p = 0;            /* consider only the directory */
  187.     ok = access(name, F_OK|W_OK);    /* can we create a file in there? */
  188.     *p = c;                /* fix the path again */
  189.     if (ok < 0)
  190.         cmerr(errstr(-1));        /* nope, complain */
  191.     }
  192. }
  193.  
  194. /*
  195.  * getdestfile:
  196.  * open up this file for appending to, figure out its type
  197.  */
  198. msgvec *
  199. getdestfile(name,format,inter)
  200. char name[];
  201. int format;                /* default format */
  202. int inter;                /* interactive errors */
  203. {
  204.     msgvec *df;
  205.     int type;
  206.     int flags;                /* flags for msg_ops.open */
  207.     extern int num_msg_ops;        /* how many mail formats we know */
  208.     extern int mail_probe();        /* to probe the mail */
  209.     extern int auto_create_files;    /* do we need to ask? */
  210.     int fd;
  211.  
  212.     if (same_file (cf->filename, name)) {
  213.     if (inter)
  214.         cmerr ("Cannot append to current mail file");
  215.     else
  216.         return (NULL);
  217.     }
  218.     switch (mail_probe (name, &type))    /* can we read this? */
  219.     {
  220.     case PR_NAME:
  221.     if (inter)
  222.         cmerr ("Badly formed filename: %s", name);
  223.     else 
  224.         return (NULL);
  225.     case PR_PERM:
  226.     if (inter)
  227.         cmerr ("Cannot determine mail format: %s", name); /* can't read */
  228.     else 
  229.         return (NULL);
  230.     case PR_NOEX:            /* must make new file */
  231.     if (inter) {
  232.         fprintf (stderr, "File does not exist: %s\n", name);
  233.         if ((auto_create_files == SET_NO) || 
  234.         (auto_create_files == SET_ASK &&
  235.          !yesno("Do you want to create it? ", "yes")))
  236.         return(NULL);
  237.     }
  238.     fd = creat(name, new_file_mode); /* XXX assuming local file */
  239.     if (fd >= 0)            /* error msg on open later */
  240.         close(fd);
  241.     /* ** fall through ** */
  242.     case PR_EMPTY:
  243.     if (format != -1)        /* did we parse something? */
  244.         type = format;        /* whatever we parsed in switch */
  245.     else {
  246.         for (type = 0; type < num_msg_ops; type++) /* try default */
  247.         if (strcmp (default_mail_type.current, msg_ops[type].typename)
  248.             == 0)
  249.             break;        /* use their default */
  250.         if (type == num_msg_ops)
  251.         type = TYPE_MTXT;    /* no match, pick some type */
  252.     }
  253.     break;
  254.     case PR_NOTOK:
  255.     if (inter)
  256.         cmerr ("File is damaged or in unknown format: %s", name);
  257.     else 
  258.         return (NULL);
  259.     default:
  260.     if ((format != type) && (format != -1) 
  261.         && inter)            /* they guessed wrong */
  262.         fprintf (stderr, "File is in %s format, ignoring switch\n",
  263.              msg_ops[type].typename);
  264.     }
  265.     df = (msgvec *) malloc (sizeof (msgvec)); /* room to put all this stuff */
  266.     if (df == NULL) {
  267.     if (inter)
  268.         cmerr ("No room to handle file: %s", name);
  269.     else 
  270.         return (NULL);
  271.     }
  272.  
  273.     bzero (df, sizeof (msgvec));
  274.  
  275.     df->type = type;
  276.  
  277.     strcpy (df->filename, name);
  278.  
  279.     flags = inter ? (OP_INT|OP_APP) : OP_APP;
  280.     if ((*msg_ops[df->type].open)(df,flags) != 0) /* open */
  281.     return (NULL);
  282.     return (df);            /* don't need data filled in */
  283. }
  284.  
  285. /*
  286.  * do_copy:
  287.  * copy the nth message from cf (current file) into dest
  288.  * delete it if in CMD_MOVE.
  289.  */
  290. static int
  291. do_copy (n)
  292. int n;                    /* which message */
  293. {
  294.     int oldflags;
  295.  
  296.     if (n == 0) {
  297.     copy_err = FALSE;        /* no errors yet */
  298.     return (true);
  299.     }
  300.     if (n < 0)
  301.     return (true);            /* no special ending */
  302.  
  303.     if (!copy_err && !ignore (n)) {
  304.     oldflags = cf->msgs[n].flags;
  305.     cf->msgs[n].flags &= ~M_DELETED; /* copy we move not deleted */
  306.  
  307.     /* copy this message to the end of dest (0 for this unused field) */
  308.     if (copy_err = (*msg_ops[dest->type].wr_msg)
  309.                  (dest,&cf->msgs[n],0,WR_COPY)) {
  310.         cf->msgs[n].flags = oldflags;
  311.         fprintf (stderr, "Trouble writing message %d to %s, aborting %s\n",
  312.              n, dest->filename, delete ? "move" : "copy");
  313.         return (false);
  314.     }
  315.     cf->msgs[n].flags = oldflags;
  316.     if (delete && !(cf->msgs[n].flags & M_DELETED)) { /* changing it? */
  317.         cf->msgs[n].flags |= (M_DELETED|M_MODIFIED); /* delete it */
  318.         cf->flags |= MF_DIRTY;    /* file (msg flags) must be saved */
  319.     }
  320.     }
  321.     return (copy_err);
  322. }
  323.  
  324.  
  325.