/*++
/* NAME
/* showq_compat 8
/* SUMMARY
/* Sendmail mailq compatibility adapter
/* SYNOPSIS
/* void showq_compat(
/* VSTREAM *showq)
/* DESCRIPTION
/* This function converts a record stream from the showq(8)
/* daemon to of an approximation of Sendmail mailq command
/* output.
/* DIAGNOSTICS
/* Fatal errors: out of memory, malformed showq(8) daemon output.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <sysexits.h>
#include <errno.h>
/* Utility library. */
#include <vstring.h>
#include <vstream.h>
#include <stringops.h>
#include <mymalloc.h>
#include <msg.h>
/* Global library. */
#include <mail_proto.h>
#include <mail_queue.h>
#include <mail_date.h>
#include <mail_params.h>
/* Application-specific. */
#include <postqueue.h>
/*
* The enable_long_queue_ids parameter determines the output format .
*
* The historical output format for short queue IDs ( inode number and time in
* microseconds modulo 1 ) is not suitable for large inode numbers , but we
* won ' t change it to avoid breaking compatibility with programs that parse
* this output .
*/
#define S_STRING_FORMAT "%-11s %7s %-20s %s\n"
#define S_SENDER_FORMAT "%-11s %7ld %20.20s %s\n"
#define S_HEADINGS "-Queue ID-" , "--Size--" , \
"----Arrival Time----" , "-Sender/Recipient-------"
#define L_STRING_FORMAT "%-17s %8s %-19s %s\n"
#define L_SENDER_FORMAT "%-17s %8ld %19.19s %s\n"
#define L_HEADINGS "----Queue ID-----" , "--Size--" , \
"---Arrival Time----" , "--Sender/Recipient------"
#define STR(x) vstring_str(x)
/* showq_message - report status for one message */
static unsigned long showq_message(VSTREAM *showq_stream)
{
static VSTRING *queue_name = 0 ;
static VSTRING *queue_id = 0 ;
static VSTRING *id_status = 0 ;
static VSTRING *oaddr = 0 ;
static VSTRING *addr = 0 ;
static VSTRING *log_class = 0 ;
static VSTRING *why = 0 ;
long arrival_time;
long message_size;
char *saved_reason = mystrdup("" );
const char *show_reason;
int padding;
int showq_status;
time_t time_t_arrival_time;
int forced_expire;
/*
* One - time initialization .
*/
if (queue_name == 0 ) {
queue_name = vstring_alloc(100 );
queue_id = vstring_alloc(100 );
id_status = vstring_alloc(100 );
oaddr = vstring_alloc(100 );
addr = vstring_alloc(100 );
log_class = vstring_alloc(100 );
why = vstring_alloc(100 );
}
/*
* Read the message properties and sender address .
*/
if (attr_scan(showq_stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT
| ATTR_FLAG_PRINTABLE,
RECV_ATTR_STR(MAIL_ATTR_QUEUE, queue_name),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
RECV_ATTR_LONG(MAIL_ATTR_TIME, &arrival_time),
RECV_ATTR_LONG(MAIL_ATTR_SIZE, &message_size),
RECV_ATTR_INT(MAIL_ATTR_FORCED_EXPIRE, &forced_expire),
RECV_ATTR_STR(MAIL_ATTR_SENDER, addr),
ATTR_TYPE_END) != 6 )
msg_fatal_status(EX_SOFTWARE, "malformed showq server response" );
/*
* Decorate queue file names in specific states , then print the result
* left - aligned , followed by other status info and the sender address
* which is already in externalized RFC 5321 form .
*/
vstring_strcpy(id_status, STR(queue_id));
if (strcmp(STR(queue_name), MAIL_QUEUE_ACTIVE) == 0 )
vstring_strcat(id_status, "*" );
else if (strcmp(STR(queue_name), MAIL_QUEUE_HOLD) == 0 )
vstring_strcat(id_status, "!" );
if (forced_expire)
vstring_strcat(id_status, "#" );
time_t_arrival_time = arrival_time;
vstream_printf(var_long_queue_ids ?
L_SENDER_FORMAT : S_SENDER_FORMAT, STR(id_status),
message_size, asctime(localtime(&time_t_arrival_time)),
STR(addr));
/*
* Read zero or more ( recipient , reason ) pair ( s ) until attr_scan_more ( )
* consumes a terminator . If the showq daemon messes up , don ' t try to
* resynchronize .
*/
while ((showq_status = attr_scan_more(showq_stream)) > 0 ) {
if (attr_scan(showq_stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT
| ATTR_FLAG_PRINTABLE,
RECV_ATTR_STR(MAIL_ATTR_ORCPT, oaddr),
RECV_ATTR_STR(MAIL_ATTR_RECIP, addr),
RECV_ATTR_STR(MAIL_ATTR_LOG_CLASS, log_class),
RECV_ATTR_STR(MAIL_ATTR_WHY, why),
ATTR_TYPE_END) != 4 )
msg_fatal_status(EX_SOFTWARE, "malformed showq server response" );
/*
* Don ' t output a " ( reason ) " line when no recipient has a reason , or
* when the previous recipient has the same ( non ) reason as the
* current recipient . Do output a " ( reason unavailable ) " when the
* previous recipient has a reason , and the current recipient has
* none .
*/
if (strcmp(saved_reason, STR(why)) != 0 ) {
myfree(saved_reason);
saved_reason = mystrdup(STR(why));
show_reason = *saved_reason ? saved_reason : "reason unavailable" ;
if ((padding = 76 - (int ) strlen(show_reason)) < 0 )
padding = 0 ;
vstream_printf("%*s(%s)\n" , padding, "" , show_reason);
}
vstream_printf(var_long_queue_ids ?
L_STRING_FORMAT : S_STRING_FORMAT,
"" , "" , "" , STR(addr));
}
if (showq_status < 0 )
msg_fatal_status(EX_SOFTWARE, "malformed showq server response" );
myfree(saved_reason);
return (message_size);
}
/* showq_compat - legacy mailq-style output adapter */
void showq_compat(VSTREAM *showq_stream)
{
unsigned long file_count = 0 ;
unsigned long queue_size = 0 ;
int showq_status;
/*
* Process zero or more queue file objects until attr_scan_more ( )
* consumes a terminator .
*/
while ((showq_status = attr_scan_more(showq_stream)) > 0 ) {
if (file_count > 0 ) {
vstream_printf("\n" );
} else if (var_long_queue_ids) {
vstream_printf(L_STRING_FORMAT, L_HEADINGS);
} else {
vstream_printf(S_STRING_FORMAT, S_HEADINGS);
}
queue_size += showq_message(showq_stream);
file_count++;
if (vstream_fflush(VSTREAM_OUT)) {
if (errno != EPIPE)
msg_fatal_status(EX_IOERR, "output write error: %m" );
return ;
}
}
if (showq_status < 0 )
msg_fatal_status(EX_SOFTWARE, "malformed showq server response" );
/*
* Print the queue summary .
*/
if (file_count == 0 )
vstream_printf("Mail queue is empty\n" );
else {
vstream_printf("\n-- %lu Kbytes in %lu Request%s.\n" ,
queue_size / 1024 , file_count,
file_count == 1 ? "" : "s" );
}
if (vstream_fflush(VSTREAM_OUT) && errno != EPIPE)
msg_fatal_status(EX_IOERR, "output write error: %m" );
}
Messung V0.5 in Prozent C=87 H=98 G=92
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland