"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.11/cmd-write.c" (8 Aug 2018, 9336 Bytes) of package /linux/misc/s-nail-14.9.11.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.10_vs_14.9.11.

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