00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: output.c,v 1.13 2004-06-07 23:14:48 stdarg Exp $";
00022 #endif
00023
00024 #include "server.h"
00025
00026 char *global_output_string = NULL;
00027
00028
00029 static queue_t output_queues[6] = {{0}, {0}, {0}, {0}, {0}, {0}};
00030
00031
00032 static queue_t unused_queue = {0};
00033
00034 static void queue_server(int priority, char *text, int len);
00035
00036 static void do_output(const char *text, int len)
00037 {
00038 int r;
00039
00040 if (global_output_string) {
00041 free(global_output_string);
00042 global_output_string = NULL;
00043 }
00044 r = bind_check(BT_server_output, NULL, text, text);
00045 if (r & BIND_RET_BREAK) return;
00046
00047 if (global_output_string) {
00048 len = strlen(global_output_string);
00049 if (len > 0) sockbuf_write(current_server.idx, global_output_string, len);
00050 }
00051 else sockbuf_write(current_server.idx, text, len);
00052 }
00053
00054
00055 int printserv(int priority, const char *format, ...)
00056 {
00057 char buf[1024], *ptr;
00058 int len;
00059 va_list args;
00060
00061 va_start(args, format);
00062 ptr = egg_mvsprintf(buf, sizeof(buf), &len, format, args);
00063 va_end(args);
00064
00065 if (server_config.max_line_len != -1 && len > server_config.max_line_len) len = server_config.max_line_len;
00066
00067 if (len < 2 || ptr[len-1] != '\n') {
00068 ptr[len++] = '\r';
00069 ptr[len++] = '\n';
00070 }
00071 ptr[len] = 0;
00072
00073 if ((priority & (~SERVER_NEXT)) == SERVER_NOQUEUE) {
00074 do_output(ptr, len);
00075 }
00076 else {
00077 queue_server(priority, ptr, len);
00078 }
00079
00080 if (ptr != buf) free(ptr);
00081 return(len);
00082 }
00083
00084 queue_entry_t *queue_new(char *text)
00085 {
00086 queue_entry_t *q;
00087
00088
00089 if (unused_queue.queue_head) {
00090 q = unused_queue.queue_head;
00091 queue_unlink(&unused_queue, q);
00092 }
00093 else {
00094 q = calloc(1, sizeof(*q));
00095 }
00096
00097
00098 queue_entry_from_text(q, text);
00099
00100 return(q);
00101 }
00102
00103 void queue_append(queue_t *queue, queue_entry_t *q)
00104 {
00105 q->next = NULL;
00106 q->prev = queue->queue_tail;
00107 if (queue->queue_tail) queue->queue_tail->next = q;
00108 else queue->queue_head = q;
00109 queue->queue_tail = q;
00110
00111 queue->len++;
00112 }
00113
00114 void queue_unlink(queue_t *queue, queue_entry_t *q)
00115 {
00116 if (q->next) q->next->prev = q->prev;
00117 else queue->queue_tail = q->prev;
00118
00119 if (q->prev) q->prev->next = q->next;
00120 else queue->queue_head = q->next;
00121
00122 queue->len--;
00123 }
00124
00125 void queue_entry_from_text(queue_entry_t *q, char *text)
00126 {
00127 irc_msg_t *msg;
00128 int i;
00129
00130
00131 msg = &q->msg;
00132 irc_msg_parse(text, msg);
00133
00134
00135 if (msg->prefix) msg->prefix = strdup(msg->prefix);
00136 if (msg->cmd) msg->cmd = strdup(msg->cmd);
00137 for (i = 0; i < msg->nargs; i++) {
00138 msg->args[i] = strdup(msg->args[i]);
00139 }
00140 }
00141
00142 void queue_entry_cleanup(queue_entry_t *q)
00143 {
00144 irc_msg_t *msg;
00145 int i;
00146
00147 msg = &q->msg;
00148 if (msg->prefix) free(msg->prefix);
00149 if (msg->cmd) free(msg->cmd);
00150
00151 for (i = 0; i < msg->nargs; i++) {
00152 free(msg->args[i]);
00153 }
00154 memset(msg, 0, sizeof(*msg));
00155 }
00156
00157 void queue_entry_to_text(queue_entry_t *q, char *text, int *remaining)
00158 {
00159 irc_msg_t *msg;
00160 int i;
00161
00162 msg = &q->msg;
00163 if (msg->prefix) {
00164 egg_append_static_str(&text, remaining, msg->prefix);
00165 egg_append_static_str(&text, remaining, " ");
00166 }
00167 if (msg->cmd) {
00168 egg_append_static_str(&text, remaining, msg->cmd);
00169 }
00170
00171
00172 msg->nargs--;
00173 for (i = 0; i < msg->nargs; i++) {
00174 egg_append_static_str(&text, remaining, " ");
00175 egg_append_static_str(&text, remaining, msg->args[i]);
00176 }
00177 msg->nargs++;
00178
00179
00180 if (i < msg->nargs) {
00181 if (strchr(msg->args[i], ' ')) egg_append_static_str(&text, remaining, " :");
00182 else egg_append_static_str(&text, remaining, " ");
00183 egg_append_static_str(&text, remaining, msg->args[i]);
00184 }
00185 }
00186
00187 queue_t *queue_get_by_priority(int priority)
00188 {
00189 int qnum;
00190
00191 qnum = priority & (~SERVER_NEXT);
00192 if (qnum < SERVER_QUICK || qnum > SERVER_SLOW) qnum = SERVER_SLOW;
00193 qnum -= SERVER_QUICK;
00194 if (priority & SERVER_NEXT) qnum += 3;
00195
00196 return output_queues+qnum;
00197 }
00198
00199 static void queue_server(int priority, char *text, int len)
00200 {
00201 queue_t *queue;
00202 queue_entry_t *q;
00203
00204 queue = queue_get_by_priority(priority);
00205
00206 q = queue_new(text);
00207
00208
00209 q->id = queue->next_id++;
00210 queue_append(queue, q);
00211 }
00212
00213 void dequeue_messages()
00214 {
00215 queue_entry_t *q;
00216 queue_t *queue = NULL;
00217 int i, remaining, len;
00218 char *text, buf[1024];
00219
00220
00221 for (i = 0; i < 3; i++) {
00222 if (output_queues[i+3].queue_head) {
00223 queue = output_queues+i+3;
00224 break;
00225 }
00226 if (output_queues[i].queue_head) {
00227 queue = output_queues+i;
00228 break;
00229 }
00230 }
00231
00232
00233 if (!queue) return;
00234
00235 q = queue->queue_head;
00236
00237
00238 queue_unlink(queue, q);
00239
00240
00241 text = buf;
00242 remaining = sizeof(buf);
00243 queue_entry_to_text(q, text, &remaining);
00244
00245
00246
00247 queue_entry_cleanup(q);
00248 queue_append(&unused_queue, q);
00249
00250
00251 if (remaining < 3) remaining = 3;
00252 len = sizeof(buf) - remaining;
00253 buf[len++] = '\r';
00254 buf[len++] = '\n';
00255 buf[len] = 0;
00256
00257 do_output(buf, len);
00258 }