*
* $Id$
*/
+#include "config.h"
+
#include "client.h"
+#include "channel.h"
#include "ircd_snprintf.h"
#include "struct.h"
+#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#define FLAG_SPACE 0x00000004 /* found a ' ' flag */
#define FLAG_ALT 0x00000008 /* found a '#' flag */
#define FLAG_ZERO 0x00000010 /* found a '0' flag */
+#define FLAG_COLON 0x00000020 /* found a ':' flag */
-#define FLAG_RESERVED2 0x00000020 /* reserved for future expansion */
-#define FLAG_RESERVED1 0x00000040
+#define FLAG_RESERVED1 0x00000040 /* reserved for future expansion */
#define FLAG_RESERVED0 0x00000080
/* integer types */
#define CONV_STRING 0x04000000 /* convert strings */
#define CONV_VARARGS 0x05000000 /* convert a %v */
#define CONV_CLIENT 0x06000000 /* convert a struct Client */
+#define CONV_CHANNEL 0x07000000 /* convert a struct Channel */
-#define CONV_RESERVED8 0x07000000 /* reserved for future expansion */
-#define CONV_RESERVED7 0x08000000
+#define CONV_RESERVED7 0x08000000 /* reserved for future expansion */
#define CONV_RESERVED6 0x09000000
#define CONV_RESERVED5 0x0a000000
#define CONV_RESERVED4 0x0b000000
{
int overflow = 0;
- while (*s && s_len) { /* while the string exists and has non-zero length */
+ /* while the string exists and has non-zero length */
+ while (s_len && *s)
+ {
/* poor man's inlining; see addc(), above */
if (buf_p->limit == 0) { /* We've gone past the limit... */
buf_p->overflow++;
fld_s.flags |= FLAG_ALT;
continue;
+ case ':': /* Deal with the colon flag */
+ if (state == FLAG)
+ fld_s.flags |= FLAG_COLON;
+ continue;
+
case '0': /* Deal with a zero flag */
if (state == FLAG) {
fld_s.flags |= FLAG_ZERO;
case 's': /* convert a string */
fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
- TYPE_MASK);
+ FLAG_COLON | TYPE_MASK);
fld_s.flags |= ARG_PTR | CONV_STRING;
break;
case 'd': case 'i':
+ fld_s.flags &= ~(FLAG_COLON);
fld_s.flags |= ARG_INT | CONV_INT;
break;
fld_s.base = BASE_HEX;
/*FALLTHROUGH*/
case 'u': /* Unsigned int */
- fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE);
+ fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_COLON);
fld_s.flags |= INFO_UNSIGNED | ARG_INT | CONV_INT;
break;
case 'c': /* character */
fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
- TYPE_MASK);
+ FLAG_COLON | TYPE_MASK);
fld_s.flags |= INFO_UNSIGNED | ARG_INT | TYPE_CHAR | CONV_CHAR;
fld_s.prec = -1;
break;
case 'p': /* display a pointer */
- fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | TYPE_MASK);
+ fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_COLON | TYPE_MASK);
fld_s.flags |= (FLAG_ALT | FLAG_ZERO | TYPE_POINTER | ARG_PTR |
CONV_INT | INFO_UNSIGNED);
fld_s.prec = (SIZEOF_VOID_P * 2); /* number of characters */
case 'm': /* write out a string describing an errno error */
fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
- TYPE_MASK);
+ FLAG_COLON | TYPE_MASK);
fld_s.flags |= CONV_STRING;
fld_s.value.v_ptr = (void *)strerror(errno);
break;
case 'v': /* here's the infamous %v... */
fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
- TYPE_MASK);
+ FLAG_COLON | TYPE_MASK);
fld_s.flags |= ARG_PTR | CONV_VARARGS;
break;
case 'C': /* convert a client name... */
- fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
- TYPE_MASK);
+ fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ZERO | TYPE_MASK);
fld_s.flags |= ARG_PTR | CONV_CLIENT;
break;
+ case 'H': /* convert a channel name... */
+ fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
+ FLAG_COLON | TYPE_MASK);
+ fld_s.flags |= ARG_PTR | CONV_CHANNEL;
+ break;
+
default: /* Unsupported, display a message and the entire format */
adds(buf_p, -1, "(Unsupported: %");
adds(buf_p, fmt - fstart + 1, fstart);
vdata->vd_overflow = SNP_MAX(buf_s.buf_overflow, buf_s.overflow);
} else if ((fld_s.flags & CONV_MASK) == CONV_CLIENT) {
struct Client *cptr = (struct Client*) fld_s.value.v_ptr;
- char *str1 = 0, *str2 = 0;
- int slen1 = 0, slen2 = 0, plen = 0;
+ const char *str1 = 0, *str2 = 0, *str3 = 0;
+ int slen1 = 0, slen2 = 0, slen3 = 0, elen = 0, plen = 0;
/* &me is used if it's not a definite server */
if (dest && (IsServer(dest) || IsMe(dest))) {
if (IsServer(cptr) || IsMe(cptr))
- str1 = cptr->yxx;
+ str1 = cli_yxx(cptr);
else {
- str1 = cptr->user->server->yxx;
- str2 = cptr->yxx;
+ str1 = cli_yxx(cli_user(cptr)->server);
+ str2 = cli_yxx(cptr);
}
- } else
- str1 = cptr->name;
+ fld_s.flags &= ~(FLAG_ALT | FLAG_COLON);
+ } else {
+ str1 = *cli_name(cptr) ? cli_name(cptr) : "*";
+ if (!IsServer(cptr) && !IsMe(cptr) && fld_s.flags & FLAG_ALT) {
+ assert(0 != cli_user(cptr));
+ assert(0 != *(cli_name(cptr)));
+ str2 = cli_user(cptr)->username;
+ str3 = cli_user(cptr)->host;
+ } else
+ fld_s.flags &= ~FLAG_ALT;
+ }
- slen1 = my_strnlen(str1, fld_s.prec);
- if (str2 && (fld_s.prec < 0 || fld_s.prec - slen1 > 0))
- slen2 = my_strnlen(str2, fld_s.prec < 0 ? -1 : fld_s.prec - slen1);
- plen = (fld_s.width - (slen1 + slen2) <= 0 ? 0 :
- fld_s.width - (slen1 + slen2));
+ if (fld_s.flags & FLAG_COLON)
+ elen++; /* account for : */
+
+ slen1 = my_strnlen(str1, fld_s.prec < 0 ? -1 : fld_s.prec - elen);
+ if (fld_s.flags & FLAG_ALT)
+ elen++; /* account for ! */
+ if (str2 && (fld_s.prec < 0 || fld_s.prec - (slen1 + elen) > 0))
+ slen2 = my_strnlen(str2, fld_s.prec < 0 ? -1 : fld_s.prec -
+ (slen1 + elen));
+ if (fld_s.flags & FLAG_ALT)
+ elen++; /* account for @ */
+ if (str3 && (fld_s.prec < 0 || fld_s.prec - (slen1 + slen2 + elen) > 0))
+ slen3 = my_strnlen(str3, fld_s.prec < 0 ? -1 : fld_s.prec -
+ (slen1 + slen2 + elen));
+ plen = (fld_s.width - (slen1 + slen2 + slen3 + elen) <= 0 ? 0 :
+ fld_s.width - (slen1 + slen2 + slen3 + elen));
if (plen > 0 && !(fld_s.flags & FLAG_MINUS))
do_pad(buf_p, plen, spaces); /* pre-padding */
+ if (fld_s.flags & FLAG_COLON)
+ addc(buf_p, ':');
adds(buf_p, slen1, str1);
+ if (fld_s.flags & FLAG_ALT)
+ addc(buf_p, '!');
if (str2)
adds(buf_p, slen2, str2);
+ if (fld_s.flags & FLAG_ALT)
+ addc(buf_p, '@');
+ if (str3)
+ adds(buf_p, slen3, str3);
+
+ if (plen > 0 && (fld_s.flags & FLAG_MINUS))
+ do_pad(buf_p, plen, spaces); /* post-padding */
+ } else if ((fld_s.flags & CONV_MASK) == CONV_CHANNEL) {
+ struct Channel *chan = (struct Channel *)fld_s.value.v_ptr;
+ char *str = chan->chname;
+ int slen, plen;
+
+ slen = my_strnlen(str, fld_s.prec); /* str lengths and pad lengths */
+ plen = (fld_s.width - slen <= 0 ? 0 : fld_s.width - slen);
+
+ if (plen > 0 && !(fld_s.flags & FLAG_MINUS))
+ do_pad(buf_p, plen, spaces); /* pre-padding */
+
+ adds(buf_p, slen, str); /* add the string */
if (plen > 0 && (fld_s.flags & FLAG_MINUS))
do_pad(buf_p, plen, spaces); /* post-padding */