X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/789f8a4f4046120b7ae2aafa45f7f45c3ae4c8f5..65de12cc1acfeeacf85c3fd77d244b9dc7e79bdc:/src/src/queue.c diff --git a/src/src/queue.c b/src/src/queue.c index cc8d36b23..7648f47ca 100644 --- a/src/src/queue.c +++ b/src/src/queue.c @@ -12,6 +12,42 @@ +/* Routines with knowlege of spool layout */ + +static void +spool_pname_buf(uschar * buf, int len) +{ +snprintf(CS buf, len, "%s/%s/input", spool_directory, queue_name); +} + +static uschar * +spool_dname(const uschar * purpose, uschar * subdir) +{ +return string_sprintf("%s/%s/%s/%s", + spool_directory, queue_name, purpose, subdir); +} + +uschar * +spool_sname(const uschar * purpose, uschar * subdir) +{ +return string_sprintf("%s%s%s%s%s", + queue_name, *queue_name ? "/" : "", + purpose, + *subdir ? "/" : "", subdir); +} + +uschar * +spool_fname(const uschar * purpose, uschar * subdir, uschar * fname, uschar * suffix) +{ +return string_sprintf("%s/%s/%s/%s/%s%s", + spool_directory, queue_name, purpose, subdir, fname, suffix); +} + + + + +#ifndef COMPILE_UTILITY + /* The number of nodes to use for the bottom-up merge sort when a list of queue items is to be ordered. The code for this sort was contributed as a patch by Michael Haardt. */ @@ -142,7 +178,8 @@ else i = subdiroffset; /* Set up prototype for the directory name. */ -sprintf(CS buffer, "%s/input", spool_directory); +spool_pname_buf(buffer, sizeof(buffer)); +buffer[sizeof(buffer) - 3] = 0; subptr = Ustrlen(buffer); buffer[subptr+2] = 0; /* terminator for lengthened name */ @@ -161,8 +198,9 @@ for (; i <= *subcount; i++) buffer[subptr+1] = subdirchar; } - dd = opendir(CS buffer); - if (dd == NULL) continue; + DEBUG(D_queue_run) debug_printf("looking in %s\n", buffer); + if (!(dd = opendir(CS buffer))) + continue; /* Now scan the directory. */ @@ -264,9 +302,11 @@ for (; i <= *subcount; i++) { if (!split_spool_directory && count <= 2) { + uschar subdir[2]; + rmdir(CS buffer); - sprintf(CS big_buffer, "%s/msglog/%c", spool_directory, subdirchar); - rmdir(CS big_buffer); + subdir[0] = subdirchar; subdir[1] = 0; + rmdir(CS spool_dname(US"msglog", subdir)); } if (subdiroffset > 0) break; /* Single sub-directory */ } @@ -389,7 +429,11 @@ if (!recurse) } log_detail = string_copy(big_buffer); - log_write(L_queue_run, LOG_MAIN, "Start queue run: %s", log_detail); + if (*queue_name) + log_write(L_queue_run, LOG_MAIN, "Start '%s' queue run: %s", + queue_name, log_detail); + else + log_write(L_queue_run, LOG_MAIN, "Start queue run: %s", log_detail); } /* If deliver_selectstring is a regex, compile it. */ @@ -476,9 +520,8 @@ for (i = (queue_run_in_order? -1 : 0); /* Check that the message still exists */ message_subdir[0] = f->dir_uschar; - sprintf(CS buffer, "%s/input/%s/%s", spool_directory, message_subdir, - f->text); - if (Ustat(buffer, &statbuf) < 0) continue; + if (Ustat(spool_fname(US"input", message_subdir, f->text, US""), &statbuf) < 0) + continue; /* There are some tests that require the reading of the header file. Ensure the store used is scavenged afterwards so that this process doesn't keep @@ -698,7 +741,12 @@ if (queue_2stage) /* At top level, log the end of the run. */ -if (!recurse) log_write(L_queue_run, LOG_MAIN, "End queue run: %s", log_detail); +if (!recurse) + if (*queue_name) + log_write(L_queue_run, LOG_MAIN, "End '%s' queue run: %s", + queue_name, log_detail); + else + log_write(L_queue_run, LOG_MAIN, "End queue run: %s", log_detail); } @@ -841,17 +889,16 @@ for (; f != NULL; f = f->next) int ptr; FILE *jread; struct stat statbuf; + uschar * fname = spool_fname(US"input", message_subdir, f->text, US""); - sprintf(CS big_buffer, "%s/input/%s/%s", spool_directory, message_subdir, - f->text); - ptr = Ustrlen(big_buffer)-1; - big_buffer[ptr] = 'D'; + ptr = Ustrlen(fname)-1; + fname[ptr] = 'D'; /* Add the data size to the header size; don't count the file name at the start of the data file, but add one for the notional blank line that precedes the data. */ - if (Ustat(big_buffer, &statbuf) == 0) + if (Ustat(fname, &statbuf) == 0) size = message_size + statbuf.st_size - SPOOL_DATA_START_OFFSET + 1; i = (now - received_time)/60; /* minutes on queue */ if (i > 90) @@ -863,8 +910,8 @@ for (; f != NULL; f = f->next) /* Collect delivered addresses from any J file */ - big_buffer[ptr] = 'J'; - jread = Ufopen(big_buffer, "rb"); + fname[ptr] = 'J'; + jread = Ufopen(fname, "rb"); if (jread != NULL) { while (Ufgets(big_buffer, big_buffer_size, jread) != NULL) @@ -892,9 +939,9 @@ for (; f != NULL; f = f->next) if (save_errno == ERRNO_SPOOLFORMAT) { struct stat statbuf; - sprintf(CS big_buffer, "%s/input/%s/%s", spool_directory, message_subdir, - f->text); - if (Ustat(big_buffer, &statbuf) == 0) + uschar * fname = spool_fname(US"input", message_subdir, f->text, US""); + + if (Ustat(fname, &statbuf) == 0) printf("*** spool format error: size=" OFF_T_FMT " ***", statbuf.st_size); else printf("*** spool format error ***"); @@ -959,7 +1006,7 @@ struct passwd *pw; uschar *doing = NULL; uschar *username; uschar *errmsg; -uschar spoolname[256]; +uschar spoolname[32]; /* Set the global message_id variable, used when re-writing spool files. This also causes message ids to be added to log messages. */ @@ -1004,12 +1051,13 @@ if (action >= MSG_SHOW_BODY) for (i = 0; i < 2; i++) { - message_subdir[0] = (split_spool_directory == (i == 0))? id[5] : 0; - sprintf(CS spoolname, "%s/%s/%s/%s%s", spool_directory, subdirectory, - message_subdir, id, suffix); - fd = Uopen(spoolname, O_RDONLY, 0); - if (fd >= 0) break; - if (i == 0) continue; + message_subdir[0] = split_spool_directory == (i == 0) ? id[5] : 0; + if ((fd = Uopen(spool_fname(subdirectory, message_subdir, id, suffix), + O_RDONLY, 0)) >= 0) + break; + if (i == 0) + continue; + printf("Failed to open %s file for %s%s: %s\n", subdirectory, id, suffix, strerror(errno)); if (action == MSG_SHOW_LOG && !message_logs) @@ -1031,7 +1079,6 @@ only if the action is remove and the user is an admin user, to allow for tidying up broken states. */ if ((deliver_datafile = spool_open_datafile(id)) < 0) - { if (errno == ENOENT) { yield = FALSE; @@ -1046,7 +1093,6 @@ if ((deliver_datafile = spool_open_datafile(id)) < 0) strerror(errno)); return FALSE; } - } /* Read the spool header file for the message. Again, continue after an error only in the case of deleting by an administrator. Setting the third @@ -1099,7 +1145,7 @@ switch(action) case MSG_SHOW_COPY: deliver_in_buffer = store_malloc(DELIVER_IN_BUFFER_SIZE); deliver_out_buffer = store_malloc(DELIVER_OUT_BUFFER_SIZE); - transport_write_message(NULL, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, 0); + transport_write_message(1, NULL, 0); break; @@ -1159,49 +1205,70 @@ switch(action) operation, just run everything twice. */ case MSG_REMOVE: - message_subdir[0] = id[5]; - for (j = 0; j < 2; message_subdir[0] = 0, j++) { - sprintf(CS spoolname, "%s/msglog/%s/%s", spool_directory, message_subdir, id); - if (Uunlink(spoolname) < 0) - { - if (errno != ENOENT) - { - yield = FALSE; - printf("Error while removing %s: %s\n", spoolname, - strerror(errno)); - } - } - else removed = TRUE; + uschar suffix[3]; + + suffix[0] = '-'; + suffix[2] = 0; + message_subdir[0] = id[5]; - for (i = 0; i < 3; i++) + for (j = 0; j < 2; message_subdir[0] = 0, j++) { - sprintf(CS spoolname, "%s/input/%s/%s-%c", spool_directory, message_subdir, - id, "DHJ"[i]); - if (Uunlink(spoolname) < 0) - { - if (errno != ENOENT) - { - yield = FALSE; - printf("Error while removing %s: %s\n", spoolname, - strerror(errno)); - } - } - else removed = TRUE; + uschar * fname = spool_fname(US"msglog", message_subdir, id, US""); + + DEBUG(D_any) debug_printf(" removing %s", fname); + if (Uunlink(fname) < 0) + { + if (errno != ENOENT) + { + yield = FALSE; + printf("Error while removing %s: %s\n", fname, strerror(errno)); + } + else DEBUG(D_any) debug_printf(" (no file)\n"); + } + else + { + removed = TRUE; + DEBUG(D_any) debug_printf(" (ok)\n"); + } + + for (i = 0; i < 3; i++) + { + uschar * fname; + + suffix[1] = (US"DHJ")[i]; + fname = spool_fname(US"input", message_subdir, id, suffix); + + DEBUG(D_any) debug_printf(" removing %s", fname); + if (Uunlink(fname) < 0) + { + if (errno != ENOENT) + { + yield = FALSE; + printf("Error while removing %s: %s\n", fname, strerror(errno)); + } + else DEBUG(D_any) debug_printf(" (no file)\n"); + } + else + { + removed = TRUE; + DEBUG(D_any) debug_printf(" (done)\n"); + } + } } - } - /* In the common case, the datafile is open (and locked), so give the - obvious message. Otherwise be more specific. */ + /* In the common case, the datafile is open (and locked), so give the + obvious message. Otherwise be more specific. */ - if (deliver_datafile >= 0) printf("has been removed\n"); - else printf("has been removed or did not exist\n"); - if (removed) - { - log_write(0, LOG_MAIN, "removed by %s", username); - log_write(0, LOG_MAIN, "Completed"); + if (deliver_datafile >= 0) printf("has been removed\n"); + else printf("has been removed or did not exist\n"); + if (removed) + { + log_write(0, LOG_MAIN, "removed by %s", username); + log_write(0, LOG_MAIN, "Completed"); + } + break; } - break; case MSG_MARK_ALL_DELIVERED: @@ -1311,7 +1378,6 @@ switch(action) } if (yield) - { if (spool_write_header(id, SW_MODIFYING, &errmsg) >= 0) printf("has been modified\n"); else @@ -1319,7 +1385,6 @@ switch(action) yield = FALSE; printf("- while %s: %s\n", doing, errmsg); } - } break; } @@ -1327,8 +1392,11 @@ switch(action) /* Closing the datafile releases the lock and permits other processes to operate on the message (if it still exists). */ -(void)close(deliver_datafile); -deliver_datafile = -1; +if (deliver_datafile >= 0) + { + (void)close(deliver_datafile); + deliver_datafile = -1; + } return yield; } @@ -1380,4 +1448,6 @@ while ((ss = string_nextinlist(&s, &sep, buffer, sizeof(buffer))) != NULL) } } +#endif /*!COMPILE_UTILITY*/ + /* End of queue.c */