1: /* refile.c - file messages away */ 2: 3: #include "../h/mh.h" 4: #include <errno.h> 5: #include <stdio.h> 6: #include <sys/types.h> 7: #include <sys/stat.h> 8: 9: /* */ 10: 11: static struct swit switches[] = { 12: #define DRAFTSW 0 13: "draft", 0, 14: 15: #define LINKSW 1 16: "link", 0, 17: #define NLINKSW 2 18: "nolink", 0, 19: 20: #define PRESSW 3 21: "preserve", 0, 22: #define NPRESSW 4 23: "nopreserve", 0, 24: 25: #define SRCSW 5 26: "src +folder", 0, 27: 28: #define FILESW 6 29: "file file", 0, 30: 31: #define HELPSW 7 32: "help", 4, 33: 34: NULL, NULL 35: }; 36: 37: /* */ 38: 39: extern int errno; 40: 41: 42: static char maildir[BUFSIZ]; 43: 44: 45: struct st_fold { 46: char *f_name; 47: struct msgs *f_mp; 48: }; 49: 50: /* */ 51: 52: /* ARGSUSED */ 53: 54: main (argc, argv) 55: int argc; 56: char **argv; 57: { 58: int linkf = 0, 59: prsrvf = 0, 60: filep = 0, 61: foldp = 0, 62: msgp = 0, 63: isdf = 0, 64: i, 65: msgnum; 66: char *cp, 67: *folder = NULL, 68: buf[100], 69: **ap, 70: **argp, 71: *arguments[MAXARGS], 72: *files[NFOLDERS + 1], 73: *msgs[MAXARGS]; 74: struct st_fold folders[NFOLDERS + 1]; 75: struct msgs *mp; 76: 77: invo_name = r1bindex (argv[0], '/'); 78: if ((cp = m_find (invo_name)) != NULL) { 79: ap = brkstring (cp = getcpy (cp), " ", "\n"); 80: ap = copyip (ap, arguments); 81: } 82: else 83: ap = arguments; 84: (void) copyip (argv + 1, ap); 85: argp = arguments; 86: 87: /* */ 88: 89: while (cp = *argp++) { 90: if (*cp == '-') 91: switch (smatch (++cp, switches)) { 92: case AMBIGSW: 93: ambigsw (cp, switches); 94: done (1); 95: case UNKWNSW: 96: adios (NULLCP, "-%s unknown\n", cp); 97: case HELPSW: 98: (void) sprintf (buf, "%s [msgs] [switches] +folder ...", 99: invo_name); 100: help (buf, switches); 101: done (1); 102: 103: case LINKSW: 104: linkf++; 105: continue; 106: case NLINKSW: 107: linkf = 0; 108: continue; 109: 110: case PRESSW: 111: prsrvf++; 112: continue; 113: case NPRESSW: 114: prsrvf = 0; 115: continue; 116: 117: case SRCSW: 118: if (folder) 119: adios (NULLCP, "only one source folder at a time!"); 120: if (!(cp = *argp++) || *cp == '-') 121: adios (NULLCP, "missing argument to %s", argp[-2]); 122: folder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, 123: *cp != '@' ? TFOLDER : TSUBCWF); 124: continue; 125: case DRAFTSW: 126: if (filep > NFOLDERS) 127: adios (NULLCP, "only %d files allowed!", NFOLDERS); 128: isdf = 0; 129: files[filep++] = getcpy (m_draft (NULLCP, NULLCP, 1, &isdf)); 130: continue; 131: case FILESW: 132: if (filep > NFOLDERS) 133: adios (NULLCP, "only %d files allowed!", NFOLDERS); 134: if (!(cp = *argp++) || *cp == '-') 135: adios (NULLCP, "missing argument to %s", argp[-2]); 136: files[filep++] = path (cp, TFILE); 137: continue; 138: } 139: if (*cp == '+' || *cp == '@') { 140: if (foldp > NFOLDERS) 141: adios (NULLCP, "only %d folders allowed!", NFOLDERS); 142: folders[foldp++].f_name = 143: path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF); 144: } 145: else 146: msgs[msgp++] = cp; 147: } 148: 149: /* */ 150: 151: if (!m_find ("path")) 152: free (path ("./", TFOLDER)); 153: if (foldp == 0) 154: adios (NULLCP, "no folder specified"); 155: 156: #ifdef WHATNOW 157: if (!msgp && !filep && (cp = getenv ("mhdraft")) && *cp) 158: files[filep++] = cp; 159: #endif WHATNOW 160: 161: if (filep > 0) { 162: if (folder || msgp) 163: adios (NULLCP, "use -file or some messages, not both"); 164: opnfolds (folders, foldp); 165: for (i = 0; i < filep; i++) 166: if (m_file (files[i], folders, foldp, prsrvf)) 167: done (1); 168: if (!linkf) 169: remove (NULLMP, filep, files); 170: done (0); 171: } 172: 173: if (!msgp) 174: msgs[msgp++] = "cur"; 175: if (!folder) 176: folder = m_getfolder (); 177: (void) strcpy (maildir, m_maildir (folder)); 178: 179: if (chdir (maildir) == NOTOK) 180: adios (maildir, "unable to change directory to"); 181: if (!(mp = m_gmsg (folder))) 182: adios (NULLCP, "unable to read folder %s", folder); 183: if (mp -> hghmsg == 0) 184: adios (NULLCP, "no messages in %s", folder); 185: 186: for (msgnum = 0; msgnum < msgp; msgnum++) 187: if (!m_convert (mp, msgs[msgnum])) 188: done (1); 189: m_setseq (mp); 190: 191: opnfolds (folders, foldp); 192: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 193: if (mp -> msgstats[msgnum] & SELECTED) { 194: cp = getcpy (m_name (msgnum)); 195: if (m_file (cp, folders, foldp, prsrvf)) 196: done (1); 197: free (cp); 198: if (!linkf) { 199: #ifdef notdef 200: mp -> msgstats[msgnum] |= DELETED; 201: #endif notdef 202: mp -> msgstats[msgnum] &= ~EXISTS; 203: } 204: } 205: if (!linkf) 206: mp -> msgflags |= SEQMOD; 207: clsfolds (folders, foldp); 208: 209: m_replace (pfolder, folder); 210: if (mp -> hghsel != mp -> curmsg 211: && (mp -> numsel != mp -> nummsg || linkf)) 212: m_setcur (mp, mp -> hghsel); 213: m_sync (mp); 214: m_update (); 215: 216: if (!linkf) 217: remove (mp, filep, files); 218: 219: done (0); 220: } 221: 222: /* */ 223: 224: static opnfolds (folders, nfolders) 225: register struct st_fold *folders; 226: int nfolders; 227: { 228: register char *cp; 229: char nmaildir[BUFSIZ]; 230: register struct st_fold *fp, 231: *ep; 232: register struct msgs *mp; 233: struct stat st; 234: 235: for (ep = (fp = folders) + nfolders; fp < ep; fp++) { 236: (void) chdir (m_maildir ("")); 237: (void) strcpy (nmaildir, m_maildir (fp -> f_name)); 238: 239: if (stat (nmaildir, &st) == NOTOK) { 240: if (errno != ENOENT) 241: adios (nmaildir, "error on folder"); 242: cp = concat ("Create folder \"", nmaildir, "\"? ", NULLCP); 243: if (!getanswer (cp)) 244: done (1); 245: free (cp); 246: if (!makedir (nmaildir)) 247: adios (NULLCP, "unable to create folder %s", nmaildir); 248: } 249: 250: if (chdir (nmaildir) == NOTOK) 251: adios (nmaildir, "unable to change directory to"); 252: if (!(mp = m_gmsg (fp -> f_name))) 253: adios (NULLCP, "unable to read folder %s", fp -> f_name); 254: mp -> curmsg = 0; 255: 256: fp -> f_mp = mp; 257: 258: (void) chdir (maildir); 259: } 260: } 261: 262: /* */ 263: 264: static clsfolds (folders, nfolders) 265: register struct st_fold *folders; 266: int nfolders; 267: { 268: register struct st_fold *fp, 269: *ep; 270: register struct msgs *mp; 271: 272: for (ep = (fp = folders) + nfolders; fp < ep; fp++) { 273: mp = fp -> f_mp; 274: m_setseq (mp); 275: m_sync (mp); 276: } 277: } 278: 279: /* */ 280: 281: static remove (mp, filep, files) 282: register struct msgs *mp; 283: register int filep; 284: register char **files; 285: { 286: register int i, 287: vecp; 288: register char *cp, 289: **vec; 290: 291: if (rmmproc) { 292: if (filep > 0) 293: vec = files; 294: else { 295: if (mp -> numsel > MAXARGS - 2) 296: adios (NULLCP, "more than %d messages for %s exec", 297: MAXARGS - 2, rmmproc); 298: vec = (char **) calloc ((unsigned) (mp -> numsel + 2), sizeof *vec); 299: if (vec == NULL) 300: adios (NULLCP, "unable to allocate exec vector"); 301: vecp = 1; 302: for (i = mp -> lowsel; i <= mp -> hghsel; i++) 303: if (mp -> msgstats[i] & SELECTED) 304: vec[vecp++] = getcpy (m_name (i)); 305: vec[vecp] = NULL; 306: } 307: 308: (void) fflush (stdout); 309: vec[0] = r1bindex (rmmproc, '/'); 310: execvp (rmmproc, vec); 311: adios (rmmproc, "unable to exec"); 312: } 313: 314: if (filep > 0) { 315: for (i = 0; i < filep; i++) 316: if (unlink (files[i]) == NOTOK) 317: admonish (files[i], "unable to unlink"); 318: } 319: else 320: for (i = mp -> lowsel; i <= mp -> hghsel; i++) 321: if (mp -> msgstats[i] & SELECTED) 322: if (unlink (cp = m_name (i)) == NOTOK) 323: admonish (cp, "unable to unlink"); 324: } 325: 326: /* */ 327: 328: m_file (msg, folders, nfolders, prsrvf) 329: register char *msg; 330: struct st_fold *folders; 331: int nfolders, 332: prsrvf; 333: { 334: int in, 335: out, 336: linkerr, 337: msgnum; 338: register char *nmsg; 339: char newmsg[BUFSIZ]; 340: register struct st_fold *fp, 341: *ep; 342: register struct msgs *mp; 343: struct stat st, 344: s1; 345: 346: for (ep = (fp = folders) + nfolders; fp < ep; fp++) { 347: mp = fp -> f_mp; 348: if (prsrvf && (msgnum = m_atoi (nmsg = msg)) > 0) { 349: if (msgnum >= mp -> hghoff) 350: if (mp = m_remsg (mp, 0, msgnum + MAXFOLDER)) 351: fp -> f_mp = mp; 352: else 353: adios (NULLCP, "unable to allocate folder storage"); 354: if (!(mp -> msgstats[msgnum] & EXISTS)) { 355: mp -> msgstats[msgnum] |= EXISTS; 356: #ifdef notdef 357: mp -> msgstats[msgnum] &= ~DELETED; 358: #endif notdef 359: mp -> nummsg++; 360: } 361: mp -> msgstats[msgnum] |= SELECTED; 362: if (msgnum > mp -> hghmsg) 363: mp -> hghmsg = msgnum; 364: } 365: else { 366: if (mp -> hghmsg >= mp -> hghoff) 367: if (mp = m_remsg (mp, 0, mp -> hghoff + MAXFOLDER)) 368: fp -> f_mp = mp; 369: else 370: adios (NULLCP, "unable to allocate folder storage"); 371: 372: nmsg = m_name (msgnum = ++mp -> hghmsg); 373: mp -> nummsg++; 374: mp -> msgstats[msgnum] |= EXISTS | SELECTED; 375: } 376: if (mp -> lowmsg == 0) 377: mp -> lowmsg = msgnum; 378: if (mp -> lowsel == 0 || msgnum < mp -> lowsel) 379: mp -> lowsel = msgnum; 380: if (msgnum > mp -> hghsel) 381: mp -> hghsel = msgnum; 382: 383: /* */ 384: 385: (void) sprintf (newmsg, "%s/%s", mp -> foldpath, nmsg); 386: if (link (msg, newmsg) == NOTOK) { 387: linkerr = errno; 388: if (linkerr == EEXIST 389: || (linkerr == EXDEV && stat (newmsg, &st) != NOTOK)) { 390: if (linkerr != EEXIST 391: || stat (msg, &s1) == NOTOK 392: || stat (newmsg, &st) == NOTOK 393: || s1.st_ino != st.st_ino) { 394: advise (NULLCP, "message %s:%s already exists", 395: fp -> f_name, newmsg); 396: return 1; 397: } 398: continue; 399: } 400: if (linkerr == EXDEV) { 401: if ((in = open (msg, 0)) == NOTOK) { 402: advise (msg, "unable to open message %s"); 403: return 1; 404: } 405: (void) fstat (in, &st); 406: if ((out = creat (newmsg, (int) st.st_mode & 0777)) 407: == NOTOK) { 408: advise (newmsg, "unable to create"); 409: (void) close (in); 410: return 1; 411: } 412: cpydata (in, out, msg, newmsg); 413: (void) close (in); 414: (void) close (out); 415: } 416: else { 417: advise (newmsg, "error linking %s to", msg); 418: return 1; 419: } 420: } 421: } 422: 423: return 0; 424: }