Mercurial > masqmail-0.2
diff src/local.c @ 10:26e34ae9a3e3
changed indention and line wrapping to a more consistent style
author | meillo@marmaro.de |
---|---|
date | Mon, 27 Oct 2008 16:23:10 +0100 |
parents | 08114f7dcc23 |
children | f671821d8222 |
line wrap: on
line diff
--- a/src/local.c Mon Oct 27 16:21:27 2008 +0100 +++ b/src/local.c Mon Oct 27 16:23:10 2008 +0100 @@ -20,347 +20,333 @@ #include "peopen.h" #include <sys/wait.h> -static -void message_stream(FILE *out, message *msg, GList *hdr_list, guint flags) +static void +message_stream(FILE * out, message * msg, GList * hdr_list, guint flags) { - time_t now = time(NULL); - GList *node; - - if(flags & MSGSTR_FROMLINE){ - fprintf(out, "From <%s@%s> %s", msg->return_path->local_part, - msg->return_path->domain, ctime(&now)); - } - - foreach(hdr_list, node){ - header *hdr = (header *)(node->data); - fputs(hdr->header, out); - } - putc('\n', out); - foreach(msg->data_list, node){ - /* From hack: */ - if(flags & MSGSTR_FROMHACK){ - if(strncmp(node->data, "From ", 5) == 0) - putc('>', out); - } - fputs(node->data, out); - } - putc('\n', out); + time_t now = time(NULL); + GList *node; + + if (flags & MSGSTR_FROMLINE) { + fprintf(out, "From <%s@%s> %s", msg->return_path->local_part, msg->return_path->domain, ctime(&now)); + } + + foreach(hdr_list, node) { + header *hdr = (header *) (node->data); + fputs(hdr->header, out); + } + putc('\n', out); + foreach(msg->data_list, node) { + /* From hack: */ + if (flags & MSGSTR_FROMHACK) { + if (strncmp(node->data, "From ", 5) == 0) + putc('>', out); + } + fputs(node->data, out); + } + putc('\n', out); } -gboolean append_file(message *msg, GList *hdr_list, gchar *user) +gboolean +append_file(message * msg, GList * hdr_list, gchar * user) { - struct passwd *pw; - gboolean ok = FALSE; - - /* headers may be special for a local delivery */ - if(hdr_list == NULL) - hdr_list = msg->hdr_list; + struct passwd *pw; + gboolean ok = FALSE; + + /* headers may be special for a local delivery */ + if (hdr_list == NULL) + hdr_list = msg->hdr_list; - if((pw = getpwnam(user))){ - uid_t saved_uid = geteuid(); - gid_t saved_gid = getegid(); - gboolean uid_ok = TRUE, gid_ok = TRUE; + if ((pw = getpwnam(user))) { + uid_t saved_uid = geteuid(); + gid_t saved_gid = getegid(); + gboolean uid_ok = TRUE, gid_ok = TRUE; - if(!conf.run_as_user){ - uid_ok = (seteuid(0) == 0); - if(uid_ok){ - gid_ok = (setegid(conf.mail_gid) == 0); - uid_ok = (seteuid(pw->pw_uid) == 0); - } - } + if (!conf.run_as_user) { + uid_ok = (seteuid(0) == 0); + if (uid_ok) { + gid_ok = (setegid(conf.mail_gid) == 0); + uid_ok = (seteuid(pw->pw_uid) == 0); + } + } - DEBUG(5) debugf("running as euid %d\n", geteuid()); - DEBUG(5) debugf("running as egid %d\n", getegid()); + DEBUG(5) debugf("running as euid %d\n", geteuid()); + DEBUG(5) debugf("running as egid %d\n", getegid()); - if(uid_ok && gid_ok){ - gchar *filename; - FILE *out; + if (uid_ok && gid_ok) { + gchar *filename; + FILE *out; - filename = g_strdup_printf("%s/%s", conf.mail_dir, user); - if((out = fopen(filename, "a"))){ + filename = g_strdup_printf("%s/%s", conf.mail_dir, user); + if ((out = fopen(filename, "a"))) { #ifdef USE_LIBLOCKFILE - gint err; - /* lock file using liblockfile */ - err = maillock(user,3); - if(err == 0){ + gint err; + /* lock file using liblockfile */ + err = maillock(user, 3); + if (err == 0) { #else - /* lock file: */ - struct flock lock; - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_END; - lock.l_start = lock.l_len = 0; - if(fcntl(fileno(out), F_SETLK, &lock) != -1){ + /* lock file: */ + struct flock lock; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_END; + lock.l_start = lock.l_len = 0; + if (fcntl(fileno(out), F_SETLK, &lock) != -1) { #endif - fchmod(fileno(out), 0600); - - message_stream(out, msg, hdr_list, MSGSTR_FROMLINE|MSGSTR_FROMHACK); + fchmod(fileno(out), 0600); + + message_stream(out, msg, hdr_list, MSGSTR_FROMLINE | MSGSTR_FROMHACK); - ok = TRUE; - - /* close when still user */ - fclose(out); + ok = TRUE; + + /* close when still user */ + fclose(out); #ifdef USE_LIBLOCKFILE - mailunlock(); + mailunlock(); #endif - }else{ - fclose(out); + } else { + fclose(out); #ifdef USE_LIBLOCKFILE - DEBUG(3) debugf("could not lock file %s: error %d\n", - filename, err); - } /* XEmacs indenting convenience... */ + DEBUG(3) debugf("could not lock file %s: error %d\n", filename, err); + } /* XEmacs indenting convenience... */ #else - DEBUG(3) debugf("could not lock file %s: %s\n", - filename, strerror(errno)); - } + DEBUG(3) debugf("could not lock file %s: %s\n", filename, strerror(errno)); + } #endif - }else{ - logwrite(LOG_ALERT, "could not open file %s: %s\n", - filename, strerror(errno)); - } - g_free(filename); + } else { + logwrite(LOG_ALERT, "could not open file %s: %s\n", filename, strerror(errno)); + } + g_free(filename); - if(!conf.run_as_user){ - uid_ok = (seteuid(0) == 0); - if(uid_ok){ - gid_ok = (setegid(saved_gid) == 0); - uid_ok = (seteuid(saved_uid) == 0); + if (!conf.run_as_user) { + uid_ok = (seteuid(0) == 0); + if (uid_ok) { + gid_ok = (setegid(saved_gid) == 0); + uid_ok = (seteuid(saved_uid) == 0); + } + } + + if (!uid_ok || !gid_ok) { + /* FIXME: if this fails we HAVE to exit, because we shall not run + with some users id. But we do not return, and so this message + will not be finished, so the user will get the message again + next time a delivery is attempted... */ + logwrite(LOG_ALERT, "could not set back uid or gid after local delivery: %s\n", strerror(errno)); + logwrite(LOG_ALERT, "uid=%d, gid=%d, euid=%d, egid=%d, want = %d, %d\n", + getuid(), getgid(), geteuid(), getegid(), saved_uid, saved_gid); + exit(EXIT_FAILURE); + } + } else { + logwrite(LOG_ALERT, "could not set uid or gid for local delivery, uid = %d: %s\n", pw->pw_uid, strerror(errno)); + } + } else { + logwrite(LOG_ALERT, "could not find password entry for user %s\n", user); + errno = ENOENT; /* getpwnam does not set errno correctly */ } - } - - if(!uid_ok || !gid_ok){ - /* FIXME: if this fails we HAVE to exit, because we shall not run - with some users id. But we do not return, and so this message - will not be finished, so the user will get the message again - next time a delivery is attempted... */ - logwrite(LOG_ALERT, - "could not set back uid or gid after local delivery: %s\n", - strerror(errno)); - logwrite(LOG_ALERT, - "uid=%d, gid=%d, euid=%d, egid=%d, want = %d, %d\n", - getuid(), getgid(), geteuid(), getegid(), saved_uid, saved_gid); - exit(EXIT_FAILURE); - } - }else{ - logwrite(LOG_ALERT, - "could not set uid or gid for local delivery, uid = %d: %s\n", - pw->pw_uid, strerror(errno)); - } - }else{ - logwrite(LOG_ALERT, "could not find password entry for user %s\n", user); - errno = ENOENT; /* getpwnam does not set errno correctly */ - } - return ok; + return ok; } #ifdef ENABLE_MAILDIR -gboolean maildir_out(message *msg, GList *hdr_list, gchar *user, guint flags) +gboolean +maildir_out(message * msg, GList * hdr_list, gchar * user, guint flags) { - struct passwd *pw; - gboolean ok = FALSE; - - /* headers may be special for a local delivery */ - if(hdr_list == NULL) - hdr_list = msg->hdr_list; + struct passwd *pw; + gboolean ok = FALSE; - if((pw = getpwnam(user))){ - uid_t saved_uid = geteuid(); - gid_t saved_gid = getegid(); - gboolean uid_ok = TRUE, gid_ok = TRUE; + /* headers may be special for a local delivery */ + if (hdr_list == NULL) + hdr_list = msg->hdr_list; + + if ((pw = getpwnam(user))) { + uid_t saved_uid = geteuid(); + gid_t saved_gid = getegid(); + gboolean uid_ok = TRUE, gid_ok = TRUE; - if(!conf.run_as_user){ - uid_ok = (seteuid(0) == 0); - if(uid_ok){ - gid_ok = (setegid(conf.mail_gid) == 0); - uid_ok = (seteuid(pw->pw_uid) == 0); - } - } + if (!conf.run_as_user) { + uid_ok = (seteuid(0) == 0); + if (uid_ok) { + gid_ok = (setegid(conf.mail_gid) == 0); + uid_ok = (seteuid(pw->pw_uid) == 0); + } + } - DEBUG(5) debugf("running as euid %d\n", geteuid()); - DEBUG(5) debugf("running as egid %d\n", getegid()); - - if(uid_ok && gid_ok){ - char *path = g_strdup_printf("%s/Maildir", pw->pw_dir); - struct stat statbuf; - int ret; + DEBUG(5) debugf("running as euid %d\n", geteuid()); + DEBUG(5) debugf("running as egid %d\n", getegid()); - DEBUG(5) debugf("path = %s\n", path); + if (uid_ok && gid_ok) { + char *path = g_strdup_printf("%s/Maildir", pw->pw_dir); + struct stat statbuf; + int ret; + + DEBUG(5) debugf("path = %s\n", path); - ok = TRUE; - ret = stat(path, &statbuf); - if(ret != 0){ - ok = FALSE; - if(errno == ENOENT){ - logwrite(LOG_NOTICE, "directory %s does not exist, creating\n", path); - if(mkdir(path, 0700) == 0) - ok = TRUE; - }else - logwrite(LOG_ALERT, "stat of %s failed: %s\n", path, strerror(errno)); - } - if(ok){ - ok = FALSE; - ret = stat(path, &statbuf); - if(S_ISDIR(statbuf.st_mode)){ - gchar *subdirs[] = {"tmp", "new", "cur"}; - int i; - for(i = 0; i < 3; i++){ - char *path1 = g_strdup_printf("%s/%s", path, subdirs[i]); - ret = stat(path1, &statbuf); - if(ret != 0){ - if(errno == ENOENT){ - logwrite(LOG_NOTICE, "directory %s does not exist, creating\n", path1); - if(mkdir(path1, 0700) != 0) break; - } - } - g_free(path1); - } - if(i == 3){ - FILE *out; - mode_t saved_mode = umask(066); - /* the qmail style unique works only if delivering - with different process. We do not fork for each delivery, - so our uid is more unique. Hope it is compatible with all - MUAs. - */ - gchar *filename = g_strdup_printf("%s/tmp/%s.%s", path, msg->uid, conf.host_name); + ok = TRUE; + ret = stat(path, &statbuf); + if (ret != 0) { + ok = FALSE; + if (errno == ENOENT) { + logwrite(LOG_NOTICE, "directory %s does not exist, creating\n", path); + if (mkdir(path, 0700) == 0) + ok = TRUE; + } else + logwrite(LOG_ALERT, "stat of %s failed: %s\n", path, strerror(errno)); + } + if (ok) { + ok = FALSE; + ret = stat(path, &statbuf); + if (S_ISDIR(statbuf.st_mode)) { + gchar *subdirs[] = { "tmp", "new", "cur" }; + int i; + for (i = 0; i < 3; i++) { + char *path1 = g_strdup_printf("%s/%s", path, subdirs[i]); + ret = stat(path1, &statbuf); + if (ret != 0) { + if (errno == ENOENT) { + logwrite(LOG_NOTICE, "directory %s does not exist, creating\n", path1); + if (mkdir(path1, 0700) != 0) + break; + } + } + g_free(path1); + } + if (i == 3) { + FILE *out; + mode_t saved_mode = umask(066); + /* the qmail style unique works only if delivering + with different process. We do not fork for each delivery, + so our uid is more unique. Hope it is compatible with all + MUAs. + */ + gchar *filename = g_strdup_printf("%s/tmp/%s.%s", path, msg->uid, conf.host_name); + + DEBUG(5) debugf("filename = %s\n", filename); - DEBUG(5) debugf("filename = %s\n", filename); - - if((out = fopen(filename, "w"))){ - gchar *newname = - g_strdup_printf("%s/new/%s.%s", path, msg->uid, conf.host_name); - message_stream(out, msg, hdr_list, flags); - ok = TRUE; - if(fflush(out) == EOF) ok = FALSE; - else if(fdatasync(fileno(out)) != 0){ - if(errno != EINVAL) /* some fs do not support this.. - I hope this also means that it is not necessary */ - ok = FALSE; - } - fclose(out); - if(rename(filename, newname) != 0){ - ok = FALSE; - logwrite(LOG_ALERT, "moving %s to %s failed: %s", - filename, newname, strerror(errno)); - } - g_free(newname); - } - umask(saved_mode); - g_free(filename); - } - }else{ - logwrite(LOG_ALERT, "%s is not a directory\n", path); - errno = ENOTDIR; + if ((out = fopen(filename, "w"))) { + gchar *newname = g_strdup_printf("%s/new/%s.%s", path, msg->uid, conf.host_name); + message_stream(out, msg, hdr_list, flags); + ok = TRUE; + if (fflush(out) == EOF) + ok = FALSE; + else if (fdatasync(fileno(out)) != 0) { + if (errno != EINVAL) /* some fs do not support this.. I hope this also means that it is not necessary */ + ok = FALSE; + } + fclose(out); + if (rename(filename, newname) != 0) { + ok = FALSE; + logwrite(LOG_ALERT, "moving %s to %s failed: %s", filename, newname, strerror(errno)); + } + g_free(newname); + } + umask(saved_mode); + g_free(filename); + } + } else { + logwrite(LOG_ALERT, "%s is not a directory\n", path); + errno = ENOTDIR; + } + } + if (!conf.run_as_user) { + uid_ok = (seteuid(0) == 0); + if (uid_ok) { + gid_ok = (setegid(saved_gid) == 0); + uid_ok = (seteuid(saved_uid) == 0); + } + } + if (!uid_ok || !gid_ok) { + /* FIXME: if this fails we HAVE to exit, because we shall not run + with some users id. But we do not return, and so this message + will not be finished, so the user will get the message again + next time a delivery is attempted... */ + logwrite(LOG_ALERT, "could not set back uid or gid after local delivery: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + g_free(path); + } else { + logwrite(LOG_ALERT, "could not set uid or gid for local delivery, uid = %d: %s\n", pw->pw_uid, strerror(errno)); + } + } else { + logwrite(LOG_ALERT, "could not find password entry for user %s\n", user); + errno = ENOENT; /* getpwnam does not set errno correctly */ } - } - if(!conf.run_as_user){ - uid_ok = (seteuid(0) == 0); - if(uid_ok){ - gid_ok = (setegid(saved_gid) == 0); - uid_ok = (seteuid(saved_uid) == 0); - } - } - if(!uid_ok || !gid_ok){ - /* FIXME: if this fails we HAVE to exit, because we shall not run - with some users id. But we do not return, and so this message - will not be finished, so the user will get the message again - next time a delivery is attempted... */ - logwrite(LOG_ALERT, - "could not set back uid or gid after local delivery: %s\n", - strerror(errno)); - exit(EXIT_FAILURE); - } - g_free(path); - }else{ - logwrite(LOG_ALERT, - "could not set uid or gid for local delivery, uid = %d: %s\n", - pw->pw_uid, strerror(errno)); - } - }else{ - logwrite(LOG_ALERT, "could not find password entry for user %s\n", user); - errno = ENOENT; /* getpwnam does not set errno correctly */ - } - return ok; + return ok; } #endif gboolean -pipe_out(message *msg, GList *hdr_list, address *rcpt, gchar *cmd, guint flags) +pipe_out(message * msg, GList * hdr_list, address * rcpt, gchar * cmd, guint flags) { - gchar *envp[40]; - FILE *out; - uid_t saved_uid = geteuid(); - gid_t saved_gid = getegid(); - gboolean ok = FALSE; - gint i, n; - pid_t pid; - void (*old_signal)(int); - int status; + gchar *envp[40]; + FILE *out; + uid_t saved_uid = geteuid(); + gid_t saved_gid = getegid(); + gboolean ok = FALSE; + gint i, n; + pid_t pid; + void (*old_signal) (int); + int status; - /* set uid and gid to the mail ids */ - if(!conf.run_as_user){ - set_euidgid(conf.mail_uid, conf.mail_gid, &saved_uid, &saved_gid); - } + /* set uid and gid to the mail ids */ + if (!conf.run_as_user) { + set_euidgid(conf.mail_uid, conf.mail_gid, &saved_uid, &saved_gid); + } - /* set environment */ - { - gint i = 0; - address *ancestor = addr_find_ancestor(rcpt); + /* set environment */ + { + gint i = 0; + address *ancestor = addr_find_ancestor(rcpt); - envp[i++] = g_strdup_printf("SENDER=%s@%s", msg->return_path->local_part, msg->return_path->domain); - envp[i++] = g_strdup_printf("SENDER_DOMAIN=%s", msg->return_path->domain); - envp[i++] = g_strdup_printf("SENDER_LOCAL=%s", msg->return_path->local_part); - envp[i++] = g_strdup_printf("RECEIVED_HOST=%s", msg->received_host ? msg->received_host : ""); + envp[i++] = g_strdup_printf("SENDER=%s@%s", msg->return_path->local_part, msg->return_path->domain); + envp[i++] = g_strdup_printf("SENDER_DOMAIN=%s", msg->return_path->domain); + envp[i++] = g_strdup_printf("SENDER_LOCAL=%s", msg->return_path->local_part); + envp[i++] = g_strdup_printf("RECEIVED_HOST=%s", msg->received_host ? msg->received_host : ""); - envp[i++] = g_strdup_printf("RETURN_PATH=%s@%s", - msg->return_path->local_part, msg->return_path->domain); - envp[i++] = g_strdup_printf("DOMAIN=%s", ancestor->domain); + envp[i++] = g_strdup_printf("RETURN_PATH=%s@%s", msg->return_path->local_part, msg->return_path->domain); + envp[i++] = g_strdup_printf("DOMAIN=%s", ancestor->domain); - envp[i++] = g_strdup_printf("LOCAL_PART=%s", ancestor->local_part); - envp[i++] = g_strdup_printf("USER=%s", ancestor->local_part); - envp[i++] = g_strdup_printf("LOGNAME=%s", ancestor->local_part); + envp[i++] = g_strdup_printf("LOCAL_PART=%s", ancestor->local_part); + envp[i++] = g_strdup_printf("USER=%s", ancestor->local_part); + envp[i++] = g_strdup_printf("LOGNAME=%s", ancestor->local_part); - envp[i++] = g_strdup_printf("MESSAGE_ID=%s", msg->uid); - envp[i++] = g_strdup_printf("QUALIFY_DOMAIN=%s", conf.host_name); + envp[i++] = g_strdup_printf("MESSAGE_ID=%s", msg->uid); + envp[i++] = g_strdup_printf("QUALIFY_DOMAIN=%s", conf.host_name); - envp[i] = NULL; - n = i; - } + envp[i] = NULL; + n = i; + } - old_signal = signal(SIGCHLD, SIG_DFL); + old_signal = signal(SIGCHLD, SIG_DFL); - out = peidopen(cmd, "w", envp, &pid, conf.mail_uid, conf.mail_gid); - if(out != NULL){ - message_stream(out, msg, hdr_list, flags); + out = peidopen(cmd, "w", envp, &pid, conf.mail_uid, conf.mail_gid); + if (out != NULL) { + message_stream(out, msg, hdr_list, flags); - fclose(out); + fclose(out); - waitpid(pid, &status, 0); + waitpid(pid, &status, 0); - if(WEXITSTATUS(status) != 0){ - int exstat = WEXITSTATUS(status); - logwrite(LOG_ALERT, "process returned %d (%s)\n", exstat, ext_strerror(1024 + exstat)); - errno = 1024 + exstat; - }else if(WIFSIGNALED(status)){ - logwrite(LOG_ALERT, "process got signal %d\n", WTERMSIG(status)); - }else - ok = TRUE; + if (WEXITSTATUS(status) != 0) { + int exstat = WEXITSTATUS(status); + logwrite(LOG_ALERT, "process returned %d (%s)\n", exstat, ext_strerror(1024 + exstat)); + errno = 1024 + exstat; + } else if (WIFSIGNALED(status)) { + logwrite(LOG_ALERT, "process got signal %d\n", WTERMSIG(status)); + } else + ok = TRUE; - }else - logwrite(LOG_ALERT, "could not open pipe '%s': %s\n", cmd, strerror(errno)); - - signal(SIGCHLD, old_signal); + } else + logwrite(LOG_ALERT, "could not open pipe '%s': %s\n", cmd, strerror(errno)); - /* free environment */ - for(i = 0; i < n; i++){ - g_free(envp[i]); - } + signal(SIGCHLD, old_signal); + + /* free environment */ + for (i = 0; i < n; i++) { + g_free(envp[i]); + } - /* set uid and gid back */ - if(!conf.run_as_user){ - set_euidgid(saved_uid, saved_gid, NULL, NULL); - } + /* set uid and gid back */ + if (!conf.run_as_user) { + set_euidgid(saved_uid, saved_gid, NULL, NULL); + } - return ok; + return ok; } -