"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.7/quit.c" (16 Feb 2018, 17681 Bytes) of package /linux/misc/s-nail-14.9.7.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 "quit.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 14.9.6_vs_14.9.7.

    1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
    2  *@ Termination processing.
    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 quit
   37 
   38 #ifndef HAVE_AMALGAMATION
   39 # include "nail.h"
   40 #endif
   41 
   42 #include <utime.h>
   43 
   44 enum quitflags {
   45    QUITFLAG_HOLD      = 1<<0,
   46    QUITFLAG_KEEP      = 1<<1,
   47    QUITFLAG_KEEPSAVE  = 1<<2,
   48    QUITFLAG_APPEND    = 1<<3
   49 };
   50 
   51 struct quitnames {
   52    enum quitflags flag;
   53    enum okeys     okey;
   54 };
   55 
   56 static struct quitnames const _quitnames[] = {
   57    {QUITFLAG_HOLD, ok_b_hold},
   58    {QUITFLAG_KEEP, ok_b_keep},
   59    {QUITFLAG_KEEPSAVE, ok_b_keepsave},
   60    {QUITFLAG_APPEND, ok_b_append}
   61 };
   62 
   63 static char _mboxname[PATH_MAX];  /* Name of mbox */
   64 
   65 /* Touch the indicated file */
   66 static void _alter(char const *name);
   67 
   68 /* Preserve all the appropriate messages back in the system mailbox, and print
   69  * a nice message indicated how many were saved.  On any error, just return -1.
   70  * Else return 0.  Incorporate the any new mail that we found */
   71 static int  writeback(FILE *res, FILE *obuf);
   72 
   73 /* Terminate an editing session by attempting to write out the user's file from
   74  * the temporary.  Save any new stuff appended to the file */
   75 static bool_t edstop(void);
   76 
   77 static void
   78 _alter(char const *name) /* TODO error handling */
   79 {
   80 #ifdef HAVE_UTIMENSAT
   81    struct timespec tsa[2];
   82 #else
   83    struct stat sb;
   84    struct utimbuf utb;
   85 #endif
   86    struct n_timespec const *tsp;
   87    NYD_ENTER;
   88 
   89    tsp = n_time_now(TRU1); /* TODO -> eventloop */
   90 
   91 #ifdef HAVE_UTIMENSAT
   92    tsa[0].tv_sec = tsp->ts_sec + 1;
   93    tsa[0].tv_nsec = tsp->ts_nsec;
   94    tsa[1].tv_nsec = UTIME_OMIT;
   95    utimensat(AT_FDCWD, name, tsa, 0);
   96 #else
   97    if (!stat(name, &sb)) {
   98       utb.actime = tsp->ts_sec;
   99       utb.modtime = sb.st_mtime;
  100       utime(name, &utb);
  101    }
  102 #endif
  103    NYD_LEAVE;
  104 }
  105 
  106 static int
  107 writeback(FILE *res, FILE *obuf)
  108 {
  109    struct message *mp;
  110    int rv = -1, p, c;
  111    NYD_ENTER;
  112 
  113    if (fseek(obuf, 0L, SEEK_SET) == -1)
  114       goto jleave;
  115 
  116 #ifndef APPEND
  117    if (res != NULL)
  118       while ((c = getc(res)) != EOF)
  119          putc(c, obuf);
  120 #endif
  121    srelax_hold();
  122    for (p = 0, mp = message; PTRCMP(mp, <, message + msgCount); ++mp)
  123       if ((mp->m_flag & MPRESERVE) || !(mp->m_flag & MTOUCH)) {
  124          ++p;
  125          if (sendmp(mp, obuf, NULL, NULL, SEND_MBOX, NULL) < 0) {
  126             n_perr(mailname, 0);
  127             srelax_rele();
  128             goto jerror;
  129          }
  130          srelax();
  131       }
  132    srelax_rele();
  133 #ifdef APPEND
  134    if (res != NULL)
  135       while ((c = getc(res)) != EOF)
  136          putc(c, obuf);
  137 #endif
  138    ftrunc(obuf);
  139 
  140    if (ferror(obuf)) {
  141       n_perr(mailname, 0);
  142 jerror:
  143       fseek(obuf, 0L, SEEK_SET);
  144       goto jleave;
  145    }
  146    if (fseek(obuf, 0L, SEEK_SET) == -1)
  147       goto jleave;
  148 
  149    _alter(mailname);
  150    if (p == 1)
  151       fprintf(n_stdout, _("Held 1 message in %s\n"), displayname);
  152    else
  153       fprintf(n_stdout, _("Held %d messages in %s\n"), p, displayname);
  154    rv = 0;
  155 jleave:
  156    NYD_LEAVE;
  157    return rv;
  158 }
  159 
  160 static bool_t
  161 edstop(void) /* TODO oh my god */
  162 {
  163    int gotcha, c;
  164    struct message *mp;
  165    FILE *obuf = NULL, *ibuf = NULL;
  166    struct stat statb;
  167    bool_t rv;
  168    NYD_ENTER;
  169 
  170    rv = TRU1;
  171 
  172    if (mb.mb_perm == 0)
  173       goto j_leave;
  174 
  175    for (mp = message, gotcha = 0; PTRCMP(mp, <, message + msgCount); ++mp) {
  176       if (mp->m_flag & MNEW) {
  177          mp->m_flag &= ~MNEW;
  178          mp->m_flag |= MSTATUS;
  179       }
  180       if (mp->m_flag & (MODIFY | MDELETED | MSTATUS | MFLAG | MUNFLAG |
  181             MANSWER | MUNANSWER | MDRAFT | MUNDRAFT))
  182          ++gotcha;
  183    }
  184    if (!gotcha)
  185       goto jleave;
  186 
  187    rv = FAL0;
  188 
  189    /* TODO This is too simple minded?  We should regenerate an index file
  190     * TODO to be able to truly tell whether *anything* has changed!
  191     * TODO (Or better: only come here.. then!  It is an *object method!* */
  192    /* TODO Ignoring stat error is easy, huh? */
  193    if (!stat(mailname, &statb) && statb.st_size > mailsize) {
  194       if ((obuf = Ftmp(NULL, "edstop", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
  195             NULL) {
  196          n_perr(_("tmpfile"), 0);
  197          goto jleave;
  198       }
  199       if ((ibuf = n_fopen_any(mailname, "r", NULL)) == NULL) {
  200          n_perr(mailname, 0);
  201          goto jleave;
  202       }
  203 
  204       n_file_lock(fileno(ibuf), FLT_READ, 0,0, UIZ_MAX); /* TODO ign. lock err*/
  205       fseek(ibuf, (long)mailsize, SEEK_SET);
  206       while ((c = getc(ibuf)) != EOF) /* xxx bytewise??? TODO ... I/O error? */
  207          putc(c, obuf);
  208       Fclose(ibuf);
  209       ibuf = obuf;
  210       fflush_rewind(obuf);
  211       /*obuf = NULL;*/
  212    }
  213 
  214    fprintf(n_stdout, _("%s "), n_shexp_quote_cp(displayname, FAL0));
  215    fflush(n_stdout);
  216 
  217    if ((obuf = n_fopen_any(mailname, "r+", NULL)) == NULL) {
  218       int e = n_err_no;
  219       n_perr(n_shexp_quote_cp(mailname, FAL0), e);
  220       goto jleave;
  221    }
  222    n_file_lock(fileno(obuf), FLT_WRITE, 0,0, UIZ_MAX); /* TODO ign. lock err! */
  223    ftrunc(obuf);
  224 
  225    srelax_hold();
  226    c = 0;
  227    for (mp = message; PTRCMP(mp, <, message + msgCount); ++mp) {
  228       if (mp->m_flag & MDELETED)
  229          continue;
  230       ++c;
  231       if (sendmp(mp, obuf, NULL, NULL, SEND_MBOX, NULL) < 0) {
  232          srelax_rele();
  233          n_err(_("Failed to finalize %s\n"), n_shexp_quote_cp(mailname, FAL0));
  234          goto jleave;
  235       }
  236       srelax();
  237    }
  238    srelax_rele();
  239 
  240    gotcha = (c == 0 && ibuf == NULL);
  241    if (ibuf != NULL) {
  242       while ((c = getc(ibuf)) != EOF)
  243          putc(c, obuf);
  244    }
  245    fflush(obuf);
  246    if (ferror(obuf)) {
  247       n_err(_("Failed to finalize %s\n"), n_shexp_quote_cp(mailname, FAL0));
  248       goto jleave;
  249    }
  250 
  251    if(gotcha){
  252       /* Non-system boxes are never removed except forced via POSIX mode */
  253 #ifdef HAVE_FTRUNCATE
  254       ftruncate(fileno(obuf), 0);
  255 #else
  256       int fd;
  257 
  258       if((fd = open(mailname, (O_WRONLY | O_CREAT | n_O_NOXY_BITS | O_TRUNC),
  259             0600)) != -1)
  260          close(fd);
  261 #endif
  262 
  263       if(ok_blook(posix) && !ok_blook(keep) && n_path_rm(mailname))
  264          fputs(_("removed\n"), n_stdout);
  265       else
  266          fputs(_("truncated\n"), n_stdout);
  267    } else
  268       fputs((ok_blook(bsdcompat) || ok_blook(bsdmsgs))
  269          ? _("complete\n") : _("updated.\n"), n_stdout);
  270    fflush(n_stdout);
  271 
  272    rv = TRU1;
  273 jleave:
  274    if (obuf != NULL)
  275       Fclose(obuf);
  276    if (ibuf != NULL)
  277       Fclose(ibuf);
  278    if(!rv){
  279       /* TODO The codebase aborted by jumping to the main loop here.
  280        * TODO The OpenBSD mailx simply ignores this error.
  281        * TODO For now we follow the latter unless we are interactive,
  282        * TODO in which case we ask the user whether the error is to be
  283        * TODO ignored or not.  More of this around here in this file! */
  284       rv = getapproval(_("Continue, possibly loosing changes"), TRU1);
  285    }
  286 j_leave:
  287    NYD_LEAVE;
  288    return rv;
  289 }
  290 
  291 FL bool_t
  292 quit(bool_t hold_sigs_on)
  293 {
  294    int p, modify, anystat, c;
  295    FILE *fbuf, *lckfp, *rbuf, *abuf;
  296    struct message *mp;
  297    struct stat minfo;
  298    bool_t rv;
  299    NYD_ENTER;
  300 
  301    if(!hold_sigs_on)
  302       hold_sigs();
  303 
  304    rv = FAL0;
  305    fbuf = lckfp = rbuf = NULL;
  306    temporary_folder_hook_unroll();
  307 
  308    /* If we are read only, we can't do anything, so just return quickly */
  309    /* TODO yet we cannot return quickly if resources have to be released!
  310     * TODO somewhen it'll be mailbox->quit() anyway, for now do it by hand
  311     *if (mb.mb_perm == 0)
  312     *   goto jleave;*/
  313    p = (mb.mb_perm == 0);
  314 
  315    switch (mb.mb_type) {
  316    case MB_FILE:
  317       break;
  318    case MB_MAILDIR:
  319       rv = maildir_quit(TRU1);
  320       goto jleave;
  321 #ifdef HAVE_POP3
  322    case MB_POP3:
  323       rv = pop3_quit(TRU1);
  324       goto jleave;
  325 #endif
  326 #ifdef HAVE_IMAP
  327    case MB_IMAP:
  328    case MB_CACHE:
  329       rv = imap_quit(TRU1);
  330       goto jleave;
  331 #endif
  332    case MB_VOID:
  333       rv = TRU1;
  334       /* FALLTHRU */
  335    default:
  336       goto jleave;
  337    }
  338    if (p) {
  339       rv = TRU1;
  340       goto jleave; /* TODO */
  341    }
  342 
  343    /* If editing (not reading system mail box), then do the work in edstop() */
  344    if (n_pstate & n_PS_EDIT) {
  345       rv = edstop();
  346       goto jleave;
  347    }
  348 
  349    /* See if there any messages to save in mbox.  If no, we
  350     * can save copying mbox to /tmp and back.
  351     *
  352     * Check also to see if any files need to be preserved.
  353     * Delete all untouched messages to keep them out of mbox.
  354     * If all the messages are to be preserved, just exit with
  355     * a message */
  356    fbuf = n_fopen_any(mailname, "r+", NULL);
  357    if (fbuf == NULL) {
  358       if (n_err_no != n_ERR_NOENT)
  359 jnewmail:
  360          fprintf(n_stdout, _("Thou hast new mail.\n"));
  361       rv = TRU1;
  362       goto jleave;
  363    }
  364 
  365    if ((lckfp = n_dotlock(mailname, fileno(fbuf), FLT_WRITE, 0,0, UIZ_MAX)
  366          ) == NULL) {
  367       n_perr(_("Unable to (dot) lock mailbox"), 0);
  368       Fclose(fbuf);
  369       fbuf = NULL;
  370       rv = getapproval(_("Continue, possibly loosing changes"), TRU1);
  371       goto jleave;
  372    }
  373 
  374    rbuf = NULL;
  375    if (!fstat(fileno(fbuf), &minfo) && minfo.st_size > mailsize) {
  376       fprintf(n_stdout, _("New mail has arrived.\n"));
  377       rbuf = Ftmp(NULL, "quit", OF_RDWR | OF_UNLINK | OF_REGISTER);
  378       if (rbuf == NULL || fbuf == NULL)
  379          goto jnewmail;
  380 #ifdef APPEND
  381       fseek(fbuf, (long)mailsize, SEEK_SET);
  382       while ((c = getc(fbuf)) != EOF)
  383          putc(c, rbuf);
  384 #else
  385       p = minfo.st_size - mailsize;
  386       while (p-- > 0) {
  387          c = getc(fbuf);
  388          if (c == EOF)
  389             goto jnewmail;
  390          putc(c, rbuf);
  391       }
  392 #endif
  393       fflush_rewind(rbuf);
  394    }
  395 
  396    anystat = holdbits();
  397    modify = 0;
  398    for (c = 0, p = 0, mp = message; PTRCMP(mp, <, message + msgCount); ++mp) {
  399       if (mp->m_flag & MBOX)
  400          c++;
  401       if (mp->m_flag & MPRESERVE)
  402          p++;
  403       if (mp->m_flag & MODIFY)
  404          modify++;
  405    }
  406    if (p == msgCount && !modify && !anystat) {
  407       rv = TRU1;
  408       if (p == 1)
  409          fprintf(n_stdout, _("Held 1 message in %s\n"), displayname);
  410       else if (p > 1)
  411          fprintf(n_stdout, _("Held %d messages in %s\n"), p, displayname);
  412       goto jleave;
  413    }
  414 
  415    if (c == 0) {
  416       if (p != 0) {
  417          if (writeback(rbuf, fbuf) >= 0)
  418             rv = TRU1;
  419          else
  420             rv = getapproval(_("Continue, possibly loosing changes"), TRU1);
  421          goto jleave;
  422       }
  423       goto jcream;
  424    }
  425 
  426    if (makembox() == STOP) {
  427       rv = getapproval(_("Continue, possibly loosing changes"), TRU1);
  428       goto jleave;
  429    }
  430 
  431    /* Now we are ready to copy back preserved files to the system mailbox, if
  432     * any were requested */
  433    if (p != 0) {
  434       if (writeback(rbuf, fbuf) < 0)
  435          rv = getapproval(_("Continue, possibly loosing changes"), TRU1);
  436       goto jleave;
  437    }
  438 
  439    /* Finally, remove his file.  If new mail has arrived, copy it back */
  440 jcream:
  441    if (rbuf != NULL) {
  442       abuf = fbuf;
  443       fseek(abuf, 0L, SEEK_SET);
  444       while ((c = getc(rbuf)) != EOF)
  445          putc(c, abuf);
  446       ftrunc(abuf);
  447       _alter(mailname);
  448       rv = TRU1;
  449    } else {
  450 #ifdef HAVE_FTRUNCATE
  451       ftruncate(fileno(fbuf), 0);
  452 #else
  453       int fd;
  454 
  455       if((fd = open(mailname, (O_WRONLY | O_CREAT | n_O_NOXY_BITS | O_TRUNC),
  456             0600)) != -1)
  457          close(fd);
  458 #endif
  459       if(!ok_blook(keep))
  460          n_path_rm(mailname);
  461       rv = TRU1;
  462    }
  463 jleave:
  464    if(rbuf != NULL)
  465       Fclose(rbuf);
  466    if (fbuf != NULL) {
  467       Fclose(fbuf);
  468       if (lckfp != NULL && lckfp != (FILE*)-1)
  469          Pclose(lckfp, FAL0);
  470    }
  471 
  472    if(!hold_sigs_on)
  473       rele_sigs();
  474    NYD_LEAVE;
  475    return rv;
  476 }
  477 
  478 FL int
  479 holdbits(void)
  480 {
  481    struct message *mp;
  482    int anystat, autohold, holdbit, nohold;
  483    NYD_ENTER;
  484 
  485    anystat = 0;
  486    autohold = ok_blook(hold);
  487    holdbit = autohold ? MPRESERVE : MBOX;
  488    nohold = MBOX | MSAVED | MDELETED | MPRESERVE;
  489    if (ok_blook(keepsave))
  490       nohold &= ~MSAVED;
  491    for (mp = message; PTRCMP(mp, <, message + msgCount); ++mp) {
  492       if (mp->m_flag & MNEW) {
  493          mp->m_flag &= ~MNEW;
  494          mp->m_flag |= MSTATUS;
  495       }
  496       if (mp->m_flag & (MSTATUS | MFLAG | MUNFLAG | MANSWER | MUNANSWER |
  497             MDRAFT | MUNDRAFT))
  498          ++anystat;
  499       if (!(mp->m_flag & MTOUCH))
  500          mp->m_flag |= MPRESERVE;
  501       if (!(mp->m_flag & nohold))
  502          mp->m_flag |= holdbit;
  503    }
  504    NYD_LEAVE;
  505    return anystat;
  506 }
  507 
  508 FL enum okay
  509 makembox(void) /* TODO oh my god */
  510 {
  511    struct message *mp;
  512    char *mbox, *tempQuit;
  513    int mcount, c;
  514    FILE *ibuf = NULL, *obuf, *abuf;
  515    enum n_fopen_state fs;
  516    enum okay rv = STOP;
  517    NYD_ENTER;
  518 
  519    mbox = _mboxname;
  520    mcount = 0;
  521    if (!ok_blook(append)) {
  522       if ((obuf = Ftmp(&tempQuit, "makembox",
  523             OF_WRONLY | OF_HOLDSIGS | OF_REGISTER)) == NULL) {
  524          n_perr(_("temporary mail quit file"), 0);
  525          goto jleave;
  526       }
  527       if ((ibuf = Fopen(tempQuit, "r")) == NULL)
  528          n_perr(tempQuit, 0);
  529       Ftmp_release(&tempQuit);
  530       if (ibuf == NULL) {
  531          Fclose(obuf);
  532          goto jleave;
  533       }
  534 
  535       if ((abuf = n_fopen_any(mbox, "r", NULL)) != NULL) {
  536          while ((c = getc(abuf)) != EOF)
  537             putc(c, obuf);
  538          Fclose(abuf);
  539       }
  540       if (ferror(obuf)) {
  541          n_perr(_("temporary mail quit file"), 0);
  542          Fclose(ibuf);
  543          Fclose(obuf);
  544          goto jleave;
  545       }
  546       Fclose(obuf);
  547 
  548       if ((c = open(mbox, (O_WRONLY | O_CREAT | n_O_NOXY_BITS | O_TRUNC),
  549             0666)) != -1)
  550          close(c);
  551       if ((obuf = n_fopen_any(mbox, "r+", &fs)) == NULL) {
  552          n_perr(mbox, 0);
  553          Fclose(ibuf);
  554          goto jleave;
  555       }
  556    } else {
  557       if ((obuf = n_fopen_any(mbox, "a", &fs)) == NULL) {
  558          n_perr(mbox, 0);
  559          goto jleave;
  560       }
  561    }
  562 
  563    srelax_hold();
  564    for (mp = message; PTRCMP(mp, <, message + msgCount); ++mp) {
  565       if (mp->m_flag & MBOX) {
  566          ++mcount;
  567 #ifdef HAVE_IMAP
  568          if((fs & n_PROTO_MASK) == n_PROTO_IMAP &&
  569                !n_ignore_is_any(n_IGNORE_SAVE) && imap_thisaccount(mbox)){
  570             if(imap_copy(mp, PTR2SIZE(mp - message + 1), mbox) == STOP)
  571                goto jcopyerr;
  572          }else
  573 #endif
  574          if (sendmp(mp, obuf, n_IGNORE_SAVE, NULL, SEND_MBOX, NULL) < 0) {
  575 #ifdef HAVE_IMAP
  576 jcopyerr:
  577 #endif
  578             n_perr(mbox, 0);
  579             srelax_rele();
  580             if (ibuf != NULL)
  581                Fclose(ibuf);
  582             Fclose(obuf);
  583             goto jleave;
  584          }
  585          mp->m_flag |= MBOXED;
  586          srelax();
  587       }
  588    }
  589    srelax_rele();
  590 
  591    /* Copy the user's old mbox contents back to the end of the stuff we just
  592     * saved.  If we are appending, this is unnecessary */
  593    if (!ok_blook(append)) {
  594       rewind(ibuf);
  595       c = getc(ibuf);
  596       while (c != EOF) {
  597          putc(c, obuf);
  598          if (ferror(obuf))
  599             break;
  600          c = getc(ibuf);
  601       }
  602       Fclose(ibuf);
  603       fflush(obuf);
  604    }
  605    ftrunc(obuf);
  606    if (ferror(obuf)) {
  607       n_perr(mbox, 0);
  608       Fclose(obuf);
  609       goto jleave;
  610    }
  611    if (Fclose(obuf) != 0) {
  612 #ifdef HAVE_IMAP
  613       if((fs & n_PROTO_MASK) != n_PROTO_IMAP)
  614 #endif
  615          n_perr(mbox, 0);
  616       goto jleave;
  617    }
  618    if (mcount == 1)
  619       fprintf(n_stdout, _("Saved 1 message in mbox\n"));
  620    else
  621       fprintf(n_stdout, _("Saved %d messages in mbox\n"), mcount);
  622    rv = OKAY;
  623 jleave:
  624    NYD_LEAVE;
  625    return rv;
  626 }
  627 
  628 FL void
  629 save_mbox_for_possible_quitstuff(void){ /* TODO try to get rid of that */
  630    char const *cp;
  631    NYD2_ENTER;
  632 
  633    if((cp = fexpand("&", FEXP_NVAR)) == NULL)
  634       cp = n_empty;
  635    n_strscpy(_mboxname, cp, sizeof _mboxname);
  636    NYD2_LEAVE;
  637 }
  638 
  639 FL int
  640 savequitflags(void)
  641 {
  642    enum quitflags qf = 0;
  643    size_t i;
  644    NYD_ENTER;
  645 
  646    for (i = 0; i < n_NELEM(_quitnames); ++i)
  647       if (n_var_oklook(_quitnames[i].okey) != NULL)
  648          qf |= _quitnames[i].flag;
  649    NYD_LEAVE;
  650    return qf;
  651 }
  652 
  653 FL void
  654 restorequitflags(int qf)
  655 {
  656    size_t i;
  657    NYD_ENTER;
  658 
  659    for (i = 0;  i < n_NELEM(_quitnames); ++i) {
  660       char *x = n_var_oklook(_quitnames[i].okey);
  661       if (qf & _quitnames[i].flag) {
  662          if (x == NULL)
  663             n_var_okset(_quitnames[i].okey, TRU1);
  664       } else if (x != NULL)
  665          n_var_okclear(_quitnames[i].okey);
  666    }
  667    NYD_LEAVE;
  668 }
  669 
  670 /* s-it-mode */