On Fri, Mar 14, 2025 at 08:29:15AM +0300, Michael Tokarev via Postfix-users 
wrote:

> I'm sure I've seen this issue before here on postfix-users.
> But can't find it.
> 
> When main.cf does not have a trailing newline, using `postconf -e foo=bar'
> to add new parameter makes bad main.cf.  For example:
> 
> $ head -c-1 /etc/postfix/main.cf > main.cf
> $ tail -n1 main.cf
> default_destination_concurrency_limit = 1$ MAIL_CONFIG=$(pwd) 
> /usr/sbin/postconf -e foo=bar
> $ tail -n1 main.cf
> default_destination_concurrency_limit = 1foo=bar
> $ _
> 
> (note the command in 3rd line is in the same line as `tail` output)
> 
> I wonder if I should add a wrapper around postconf to check for the
> missing trailing newline.  This is kinda strange provided all other
> parts of postfix cope with this situation just fine.

Why not fix the problem, rather than put a bandaid on the symptom?

-- 
    Viktor.
--- a/src/postconf/postconf_edit.c
+++ b/src/postconf/postconf_edit.c
@@ -110,11 +110,16 @@ static char *pcf_find_cf_info(VSTRING *buf, VSTREAM *dst)
 
 /* pcf_next_cf_line - return next content line, pass non-content */
 
-static char *pcf_next_cf_line(VSTRING *buf, VSTREAM *src, VSTREAM *dst, int 
*lineno)
+static char *pcf_next_cf_line(VSTRING *buf, VSTREAM *src, VSTREAM *dst,
+                                  int *lineno, int *neednl)
 {
     char   *cp;
 
     while (vstring_get(buf, src) != VSTREAM_EOF) {
+       if (neednl) {
+           cp = STR(buf);
+           *neednl = *cp && cp[strlen(cp) - 1] != '\n';
+       }
        if (lineno)
            *lineno += 1;
        if ((cp = pcf_find_cf_info(buf, dst)) != 0)
@@ -126,7 +131,7 @@ static char *pcf_next_cf_line(VSTRING *buf, VSTREAM *src, 
VSTREAM *dst, int *lin
 /* pcf_gobble_cf_line - accumulate multi-line content, pass non-content */
 
 static void pcf_gobble_cf_line(VSTRING *full_entry_buf, VSTRING *line_buf,
-                                   VSTREAM *src, VSTREAM *dst, int *lineno)
+                                   VSTREAM *src, VSTREAM *dst, int *lineno)
 {
     int     ch;
 
@@ -165,6 +170,7 @@ void    pcf_edit_main(int mode, int argc, char **argv)
     HTABLE_INFO **ht_info;
     HTABLE_INFO **ht;
     int     interesting;
+    int     neednl;
     const char *err;
 
     /*
@@ -228,7 +234,8 @@ void    pcf_edit_main(int mode, int argc, char **argv)
 #define STR(x) vstring_str(x)
 
     interesting = 0;
-    while ((cp = pcf_next_cf_line(buf, src, dst, (int *) 0)) != 0) {
+    neednl = 0;
+    while ((cp = pcf_next_cf_line(buf, src, dst, (int *) 0, &neednl)) != 0) {
        /* Copy, skip or replace continued text. */
        if (cp > STR(buf)) {
            if (interesting == 0)
@@ -243,15 +250,18 @@ void    pcf_edit_main(int mode, int argc, char **argv)
            if ((interesting = !!cvalue) != 0) {
                if (cvalue->found++ == 1)
                    msg_warn("%s: multiple entries for \"%s\"", path, STR(key));
-               if (mode & PCF_EDIT_CONF)
+               if (mode & PCF_EDIT_CONF) {
                    vstream_fprintf(dst, "%s = %s\n", STR(key), cvalue->value);
-               else if (mode & PCF_COMMENT_OUT)
+                   neednl = 0;
+               } else if (mode & PCF_COMMENT_OUT)
                    vstream_fprintf(dst, "#%s", cp);
            } else {
                vstream_fputs(STR(buf), dst);
            }
        }
     }
+    if (neednl)
+       VSTREAM_PUTC('\n', dst);
 
     /*
      * Generate new entries for parameters that were not found.
@@ -315,6 +325,7 @@ void    pcf_edit_master(int mode, int argc, char **argv)
     PCF_MASTER_EDIT_REQ *edit_reqs;
     PCF_MASTER_EDIT_REQ *req;
     int     num_reqs = argc;
+    int     neednl;
     const char *edit_opts = "-Me, -Fe, -Pe, -X, or -#";
     char   *service_name;
     char   *service_type;
@@ -424,7 +435,9 @@ void    pcf_edit_master(int mode, int argc, char **argv)
     service_name_type_matched = 0;
     new_entry = 0;
     lineno = 0;
-    while ((cp = pcf_next_cf_line(parse_buf, src, dst, &lineno)) != 0) {
+    neednl = 0;
+    while ((cp = pcf_next_cf_line(parse_buf, src, dst, &lineno,
+                                 &neednl)) != 0) {
        vstring_strcpy(line_buf, STR(parse_buf));
 
        /*
@@ -572,6 +585,7 @@ void    pcf_edit_master(int mode, int argc, char **argv)
                pcf_print_master_entry(dst, PCF_FOLD_LINE, new_entry);
                pcf_free_master_entry(new_entry);
                new_entry = 0;
+               neednl = 0;
            } else if (service_name_type_matched == 0) {
                vstream_fputs(STR(line_buf), dst);
            } else if (mode & PCF_COMMENT_OUT) {
@@ -579,6 +593,8 @@ void    pcf_edit_master(int mode, int argc, char **argv)
            }
        }
     }
+    if (neednl)
+       VSTREAM_PUTC('\n', dst);
 
     /*
      * Postprocessing: when editing entire service entries, generate new
_______________________________________________
Postfix-users mailing list -- postfix-users@postfix.org
To unsubscribe send an email to postfix-users-le...@postfix.org

Reply via email to