"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.10/cmd-write.c" (25 Mar 2018, 10447 Bytes) of package /linux/misc/s-nail-14.9.10.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "cmd-write.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 14.9.9_vs_14.9.10.

    1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
    2  *@ User commands which save, copy, write (parts of) messages.
    3  *
    4  * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
    5  * Copyright (c) 2012 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
    6  */
    7 /*
    8  * Copyright (c) 1980, 1993
    9  *      The Regents of the University of California.  All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  */
   35 #undef n_FILE
   36 #define n_FILE cmd_write
   37 
   38 #ifndef HAVE_AMALGAMATION
   39 # include "nail.h"
   40 #endif
   41 
   42 /* Save/copy the indicated messages at the end of the passed file name.
   43  * If mark is true, mark the message "saved" */
   44 static int     save1(char *str, int domark, char const *cmd,
   45                   struct n_ignore const *itp, int convert, int sender_record,
   46                   int domove);
   47 
   48 /* Snarf the file from the end of the command line and return a pointer to it.
   49  * If there is no file attached, return the mbox file.  Put a null in front of
   50  * the file name so that the message list processing won't see it, unless the
   51  * file name is the only thing on the line, in which case, return 0 in the
   52  * reference flag variable */
   53 static char *  snarf(char *linebuf, bool_t *flag, bool_t usembox);
   54 
   55 static int
   56 save1(char *str, int domark, char const *cmd, struct n_ignore const *itp,
   57    int convert, int sender_record, int domove)
   58 {
   59    ui64_t mstats[1], tstats[2];
   60    enum n_fopen_state fs;
   61    int last, *msgvec, *ip;
   62    struct message *mp;
   63    char *file, *cp, *cq;
   64    char const *disp, *shell;
   65    FILE *obuf;
   66    bool_t success, isflag;
   67    NYD_ENTER;
   68 
   69    success = FAL0;
   70    last = 0;
   71    shell = NULL;
   72    file = NULL;
   73 
   74    msgvec = salloc((msgCount + 2) * sizeof *msgvec);
   75    if (sender_record) {
   76       for (cp = str; *cp != '\0' && spacechar(*cp); ++cp)
   77          ;
   78       isflag = (*cp != '\0');
   79    } else {
   80       if ((file = snarf(str, &isflag, convert != SEND_TOFILE)) == NULL)
   81          goto jleave;
   82       while(spacechar(*file))
   83          ++file;
   84       if (*file == '|') {
   85          ++file;
   86          shell = ok_vlook(SHELL);
   87       }
   88    }
   89 
   90    if (!isflag) {
   91       *msgvec = first(0, MMNORM);
   92       msgvec[1] = 0;
   93    } else if (getmsglist(str, msgvec, 0) < 0)
   94       goto jleave;
   95    if (*msgvec == 0) {
   96       if (n_pstate & (n_PS_HOOK_MASK | n_PS_ROBOT)) {
   97          success = TRU1;
   98          goto jleave;
   99       }
  100       fprintf(n_stdout, _("No messages to %s.\n"), cmd);
  101       goto jleave;
  102    }
  103 
  104    if (sender_record) {
  105       if ((cp = nameof(message + *msgvec - 1, 0)) == NULL) {
  106          fprintf(n_stdout, _("Cannot determine message sender to %s.\n"), cmd);
  107          goto jleave;
  108       }
  109 
  110       for (cq = cp; *cq != '\0' && *cq != '@'; cq++)
  111          ;
  112       *cq = '\0';
  113       if (ok_blook(outfolder)) {
  114          size_t sz = strlen(cp) +1;
  115          file = salloc(sz + 1);
  116          file[0] = '+';
  117          memcpy(file + 1, cp, sz);
  118       } else
  119          file = cp;
  120    }
  121 
  122    /* Pipe target is special TODO hacked in later, normalize flow! */
  123    if (shell != NULL) {
  124       if ((obuf = Popen(file, "w", shell, NULL, 1)) == NULL) {
  125          int esave;
  126 
  127          esave = n_err_no;
  128          n_perr(file, esave);
  129          n_err_no = esave;
  130          goto jleave;
  131       }
  132       isflag = FAL0;
  133       disp = A_("[Piped]");
  134       goto jsend;
  135    }
  136 
  137    if ((file = fexpand(file, FEXP_FULL)) == NULL)
  138       goto jleave;
  139 
  140    /* TODO all this should be URL and Mailbox-"VFS" based, and then finally
  141     * TODO end up as Mailbox()->append().  Unless SEND_TOFILE, of course.
  142     * TODO However, URL parse because that file:// prefix check is a HACK! */
  143    if(convert == SEND_TOFILE && !is_prefix("file://", file))
  144       file = savecat("file://", file);
  145    if((obuf = n_fopen_any(file, "a+", &fs)) == NULL){
  146       n_perr(file, 0);
  147       goto jleave;
  148    }
  149 
  150 #if defined HAVE_POP3 && defined HAVE_IMAP
  151    if(mb.mb_type == MB_POP3 && (fs & n_PROTO_MASK) == n_PROTO_IMAP){
  152       Fclose(obuf);
  153       n_err(_("Direct copy from POP3 to IMAP not supported before v15\n"));
  154       goto jleave;
  155    }
  156 #endif
  157 
  158    disp = (fs & n_FOPEN_STATE_EXISTS) ? A_("[Appended]") : A_("[New file]");
  159 
  160    if((fs & (n_PROTO_MASK | n_FOPEN_STATE_EXISTS)) ==
  161          (n_PROTO_FILE | n_FOPEN_STATE_EXISTS)){
  162       int xerr;
  163 
  164       /* TODO RETURN check, but be aware of protocols: v15: Mailbox->lock()!
  165        * TODO BETTER yet: should be returned in lock state already! */
  166       n_file_lock(fileno(obuf), FLT_WRITE, 0,0, UIZ_MAX);
  167 
  168       if((xerr = n_folder_mbox_prepare_append(obuf, NULL)) != n_ERR_NONE){
  169          n_perr(file, xerr);
  170          goto jleave;
  171       }
  172    }
  173 
  174 jsend:
  175    success = TRU1;
  176    tstats[0] = tstats[1] = 0;
  177 #ifdef HAVE_IMAP
  178    imap_created_mailbox = 0;
  179 #endif
  180 
  181    srelax_hold();
  182    for (ip = msgvec; *ip != 0 && UICMP(z, PTR2SIZE(ip - msgvec), <, msgCount);
  183          ++ip) {
  184       mp = &message[*ip - 1];
  185 #ifdef HAVE_IMAP
  186       if((fs & n_PROTO_MASK) == n_PROTO_IMAP &&
  187             !n_ignore_is_any(n_IGNORE_SAVE) && imap_thisaccount(file)){
  188          if(imap_copy(mp, PTR2SIZE(mp - message + 1), file) == STOP){
  189             success = FAL0;
  190             goto jferr;
  191          }
  192          mstats[0] = mp->m_xsize;
  193       }else
  194 #endif
  195       if (sendmp(mp, obuf, itp, NULL, convert, mstats) < 0) {
  196          success = FAL0;
  197          goto jferr;
  198       }
  199       srelax();
  200 
  201       touch(mp);
  202       if (domark)
  203          mp->m_flag |= MSAVED;
  204       if (domove) {
  205          mp->m_flag |= MDELETED | MSAVED;
  206          last = *ip;
  207       }
  208 
  209       tstats[0] += mstats[0];
  210       tstats[1] += mp->m_lines;/* TODO won't work, need target! v15!! */
  211    }
  212    srelax_rele();
  213 
  214    fflush(obuf);
  215 
  216    /* TODO Should be a VFS, then n_MBOX knows what to do upon .close()! */
  217    if((fs & n_PROTO_MASK) == n_PROTO_FILE && convert == SEND_MBOX)
  218       n_folder_mbox_prepare_append(obuf, NULL);
  219 
  220    if (ferror(obuf)) {
  221 jferr:
  222       n_perr(file, 0);
  223       if (!success)
  224          srelax_rele();
  225       success = FAL0;
  226    }
  227    if (shell != NULL) {
  228       if (!Pclose(obuf, TRU1))
  229          success = FAL0;
  230    } else if (Fclose(obuf) != 0)
  231       success = FAL0;
  232 
  233    if (success) {
  234 #ifdef HAVE_IMAP
  235       if((fs & n_PROTO_MASK) == n_PROTO_IMAP){
  236          if(disconnected(file))
  237             disp = A_("[Queued]");
  238          else if(imap_created_mailbox)
  239             disp = A_("[New file]");
  240          else
  241             disp = A_("[Appended]");
  242       }
  243 #endif
  244       fprintf(n_stdout, "%s %s %" /*PRIu64 "/%"*/ PRIu64 " bytes\n",
  245          n_shexp_quote_cp(file, FAL0), disp,
  246          /*tstats[1], TODO v15: lines written */ tstats[0]);
  247    } else if (domark) {
  248       for (ip = msgvec; *ip != 0 &&
  249             UICMP(z, PTR2SIZE(ip - msgvec), <, msgCount); ++ip) {
  250          mp = message + *ip - 1;
  251          mp->m_flag &= ~MSAVED;
  252       }
  253    } else if (domove) {
  254       for (ip = msgvec; *ip != 0 &&
  255             UICMP(z, PTR2SIZE(ip - msgvec), <, msgCount); ++ip) {
  256          mp = message + *ip - 1;
  257          mp->m_flag &= ~(MSAVED | MDELETED);
  258       }
  259    }
  260 
  261    if (domove && last && success) {
  262       setdot(message + last - 1);
  263       last = first(0, MDELETED);
  264       setdot(message + (last != 0 ? last - 1 : 0));
  265    }
  266 jleave:
  267    NYD_LEAVE;
  268    return (success == FAL0);
  269 }
  270 
  271 static char *
  272 snarf(char *linebuf, bool_t *flag, bool_t usembox)
  273 {
  274    char *cp;
  275    NYD_ENTER;
  276 
  277    if ((cp = laststring(linebuf, flag, TRU1)) == NULL) {
  278       if (usembox) {
  279          *flag = FAL0;
  280          cp = fexpand("&", FEXP_NVAR);
  281       } else
  282          n_err(_("No file specified\n"));
  283    }
  284    NYD_LEAVE;
  285    return cp;
  286 }
  287 
  288 FL int
  289 c_save(void *v)
  290 {
  291    char *str = v;
  292    int rv;
  293    NYD_ENTER;
  294 
  295    rv = save1(str, 1, "save", n_IGNORE_SAVE, SEND_MBOX, 0, 0);
  296    NYD_LEAVE;
  297    return rv;
  298 }
  299 
  300 FL int
  301 c_Save(void *v)
  302 {
  303    char *str = v;
  304    int rv;
  305    NYD_ENTER;
  306 
  307    rv = save1(str, 1, "save", n_IGNORE_SAVE, SEND_MBOX, 1, 0);
  308    NYD_LEAVE;
  309    return rv;
  310 }
  311 
  312 FL int
  313 c_copy(void *v)
  314 {
  315    char *str = v;
  316    int rv;
  317    NYD_ENTER;
  318 
  319    rv = save1(str, 0, "copy", n_IGNORE_SAVE, SEND_MBOX, 0, 0);
  320    NYD_LEAVE;
  321    return rv;
  322 }
  323 
  324 FL int
  325 c_Copy(void *v)
  326 {
  327    char *str = v;
  328    int rv;
  329    NYD_ENTER;
  330 
  331    rv = save1(str, 0, "copy", n_IGNORE_SAVE, SEND_MBOX, 1, 0);
  332    NYD_LEAVE;
  333    return rv;
  334 }
  335 
  336 FL int
  337 c_move(void *v)
  338 {
  339    char *str = v;
  340    int rv;
  341    NYD_ENTER;
  342 
  343    rv = save1(str, 0, "move", n_IGNORE_SAVE, SEND_MBOX, 0, 1);
  344    NYD_LEAVE;
  345    return rv;
  346 }
  347 
  348 FL int
  349 c_Move(void *v)
  350 {
  351    char *str = v;
  352    int rv;
  353    NYD_ENTER;
  354 
  355    rv = save1(str, 0, "move", n_IGNORE_SAVE, SEND_MBOX, 1, 1);
  356    NYD_LEAVE;
  357    return rv;
  358 }
  359 
  360 FL int
  361 c_decrypt(void *v)
  362 {
  363    char *str = v;
  364    int rv;
  365    NYD_ENTER;
  366 
  367    rv = save1(str, 0, "decrypt", n_IGNORE_SAVE, SEND_DECRYPT, 0, 0);
  368    NYD_LEAVE;
  369    return rv;
  370 }
  371 
  372 FL int
  373 c_Decrypt(void *v)
  374 {
  375    char *str = v;
  376    int rv;
  377    NYD_ENTER;
  378 
  379    rv = save1(str, 0, "decrypt", n_IGNORE_SAVE, SEND_DECRYPT, 1, 0);
  380    NYD_LEAVE;
  381    return rv;
  382 }
  383 
  384 FL int
  385 c_write(void *v)
  386 {
  387    char *str = v;
  388    int rv;
  389    NYD_ENTER;
  390 
  391    if (str == NULL || *str == '\0')
  392       str = savestr(n_path_devnull);
  393    rv = save1(str, 0, "write", n_IGNORE_ALL, SEND_TOFILE, 0, 0);
  394    NYD_LEAVE;
  395    return rv;
  396 }
  397 
  398 /* s-it-mode */