/[imapfilter]/imapfilter/request.c
ViewVC logotype

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.24 - (hide annotations)
Tue Jul 9 20:17:45 2002 UTC (21 years, 8 months ago) by lefcha
Branch: MAIN
Changes since 1.23: +6 -5 lines
File MIME type: text/plain
Fixed messed up rcopy.

1 lefcha 1.1 #include <stdio.h>
2     #include <stdlib.h>
3     #include <string.h>
4 lefcha 1.3 #include <errno.h>
5 lefcha 1.1
6     #include "config.h"
7     #include "imapfilter.h"
8     #include "data.h"
9    
10    
11 lefcha 1.21 extern int sockpri, sockaux;
12 lefcha 1.1 extern unsigned int options;
13 lefcha 1.18 extern unsigned int capabilities;
14    
15 lefcha 1.21 namesp_t nsppri, nspaux; /* Primary and auxiliary namespace. */
16 lefcha 1.1
17 lefcha 1.3
18 lefcha 1.2 #ifdef DEBUG
19 lefcha 1.1 /*
20     * Test/ping server.
21     */
22 lefcha 1.21 int test(int *sock)
23 lefcha 1.1 {
24 lefcha 1.21 return server_response(sock, imap_noop(sock));
25 lefcha 1.1 }
26 lefcha 1.2 #endif
27 lefcha 1.1
28 lefcha 1.10
29 lefcha 1.1 /*
30 lefcha 1.10 * Check server's capabilities.
31 lefcha 1.1 */
32 lefcha 1.21 int check_capabilities(int *sock)
33 lefcha 1.1 {
34 lefcha 1.18 capabilities = CAPABILITY_NONE;
35    
36 lefcha 1.21 return capability_response(sock, imap_capability(sock));
37 lefcha 1.1 }
38    
39    
40     /*
41 lefcha 1.18 * Get namespace of mail server's mailboxes.
42     */
43 lefcha 1.21 int check_namespace(int *sock, namesp_t *nsp)
44 lefcha 1.18 {
45 lefcha 1.21 nsp->prefix[0] = nsp->delim = 0;
46 lefcha 1.18
47     if (!(options & OPTION_NAMESPACE) ||
48     !(capabilities & CAPABILITY_NAMESPACE))
49     return 0;
50     else
51 lefcha 1.21 return namespace_response(sock, imap_namespace(sock), nsp);
52 lefcha 1.18 }
53    
54    
55     /*
56 lefcha 1.10 * Login to server.
57 lefcha 1.8 */
58 lefcha 1.21 int login(int *sock, char *user, char *pass)
59 lefcha 1.8 {
60 lefcha 1.10 log_info(LOG_USERNAME, user);
61 lefcha 1.8
62 lefcha 1.21 return server_response(sock, imap_login(sock, user, pass));
63     }
64    
65    
66    
67     /*
68     * Check if a mailbox exists.
69     */
70     int check_mailbox(int *sock, char *mbox, namesp_t *nsp)
71     {
72     return server_response(sock, imap_examine(sock,
73     apply_namespace(mbox,
74     nsp->prefix,
75     nsp->delim)));
76 lefcha 1.8 }
77    
78 lefcha 1.18
79 lefcha 1.8 /*
80 lefcha 1.3 * Open mailbox in read-write mode.
81 lefcha 1.1 */
82 lefcha 1.21 int select_mailbox(int *sock, char *mbox, namesp_t *nsp)
83 lefcha 1.1 {
84     int r;
85 lefcha 1.5
86 lefcha 1.21 if (mailbox_status(sock, mbox, nsp) == -2)
87 lefcha 1.10 return -2; /* No messages exist. No filters need to
88     be applied. */
89 lefcha 1.5
90 lefcha 1.21 r = select_response(sock, imap_select(sock,
91     apply_namespace(mbox, nsp->prefix,
92     nsp->delim)));
93 lefcha 1.5
94 lefcha 1.4 log_info(LOG_MAILBOX, mbox);
95 lefcha 1.5
96 lefcha 1.1 return r;
97     }
98    
99    
100     /*
101 lefcha 1.3 * Get mailbox's status.
102 lefcha 1.1 */
103 lefcha 1.21 int mailbox_status(int *sock, char *mbox, namesp_t *nsp)
104 lefcha 1.1 {
105 lefcha 1.21 return status_response(sock, imap_status(sock,
106     apply_namespace(mbox, nsp->prefix,
107     nsp->delim),
108     "MESSAGES RECENT UNSEEN"), mbox);
109 lefcha 1.16 }
110 lefcha 1.5
111 lefcha 1.9
112 lefcha 1.1 /*
113     * Close examined/selected mailbox.
114     */
115 lefcha 1.21 int close_mailbox(int *sock)
116 lefcha 1.1 {
117 lefcha 1.21 return server_response(sock, imap_close(sock));
118 lefcha 1.1 }
119    
120    
121     /*
122     * Logout from server.
123     */
124 lefcha 1.21 int logout(int *sock)
125 lefcha 1.1 {
126 lefcha 1.21 return server_response(sock, imap_logout(sock));
127 lefcha 1.1 }
128    
129    
130     /*
131     * Match and apply filters assigned to a mailbox.
132     */
133 lefcha 1.10 int apply_filters(filter_t ** filters)
134 lefcha 1.1 {
135 lefcha 1.3 int i;
136 lefcha 1.12 char *mesgs;
137 lefcha 1.1
138     for (i = 0; filters[i]; i++) {
139 lefcha 1.16 mesgs = NULL;
140 lefcha 1.1
141 lefcha 1.12 if (match_filter(filters[i], &mesgs))
142 lefcha 1.1 continue;
143 lefcha 1.5
144 lefcha 1.4 log_info(LOG_FILTER, filters[i]->key);
145 lefcha 1.1
146 lefcha 1.3 apply_action(mesgs, &(filters[i]->action.type),
147 lefcha 1.21 filters[i]->action.raccount, filters[i]->action.destmbox,
148     filters[i]->action.args);
149 lefcha 1.12
150 lefcha 1.19 xfree(mesgs);
151 lefcha 1.1 }
152    
153     return 0;
154     }
155    
156    
157     /*
158     * Generate the search request by the masks of the filter and try to
159     * match the generated filter.
160     */
161 lefcha 1.12 int match_filter(filter_t * filter, char **mesgs)
162 lefcha 1.1 {
163 lefcha 1.3 char *search;
164 lefcha 1.5
165 lefcha 1.1 if (filter->mode == FILTER_MODE_OR)
166 lefcha 1.5 search = generate_filter_or(filter->masks, filter->masknum,
167     filter->masklen);
168 lefcha 1.1 else
169 lefcha 1.5 search = generate_filter_and(filter->masks, filter->masknum,
170     filter->masklen);
171 lefcha 1.1
172 lefcha 1.21 search_response(&sockpri, imap_search(&sockpri, search), mesgs);
173 lefcha 1.5
174 lefcha 1.19 xfree(search);
175 lefcha 1.5
176 lefcha 1.16 if (!*mesgs)
177 lefcha 1.1 return 1;
178 lefcha 1.5
179 lefcha 1.1 return 0;
180     }
181    
182    
183     /*
184     * Empty the FIFO inventory.
185     */
186     void empty_fifo(mask_t ** mfifo)
187     {
188     mfifo[0] = NULL;
189    
190 lefcha 1.3 queue_fifo(NULL, NULL);
191     dequeue_fifo(NULL);
192 lefcha 1.1 }
193    
194    
195     /*
196     * Add item to FIFO inventory.
197     */
198 lefcha 1.3 void queue_fifo(mask_t ** mfifo, mask_t * mask)
199 lefcha 1.1 {
200 lefcha 1.15 static unsigned int i;
201 lefcha 1.1
202     if (!mfifo) {
203     i = 0;
204     return;
205     }
206     mfifo[i++] = mask;
207     mfifo[i] = NULL;
208     }
209    
210    
211     /*
212     * Get next item from FIFO inventory.
213     */
214 lefcha 1.3 mask_t *dequeue_fifo(mask_t ** mfifo)
215 lefcha 1.1 {
216 lefcha 1.15 static unsigned int j;
217 lefcha 1.1
218     if (!mfifo) {
219     j = 0;
220     return NULL;
221     }
222     return mfifo[j++];
223     }
224    
225    
226     /*
227     * Generate the filter search command from the masks, assuming that
228     * masks are AND-ed.
229     */
230 lefcha 1.9 char *generate_filter_and(mask_t * mask, unsigned int masknum,
231 lefcha 1.10 unsigned int masklen)
232 lefcha 1.1 {
233 lefcha 1.3 const unsigned int searchbuf = masklen + masknum * 6 + 8;
234 lefcha 1.15 unsigned int len = 0;
235 lefcha 1.3 char *search;
236 lefcha 1.9 mask_t *tmp;
237 lefcha 1.5
238     search = (char *) xmalloc(sizeof(char) * searchbuf);
239    
240 lefcha 1.3 search[0] = 0;
241 lefcha 1.1
242 lefcha 1.9 tmp = mask;
243 lefcha 1.10 if (!tmp) {
244     strncat(search, "ALL ", searchbuf - len - 1);
245     len += 4;
246     } else
247     while ((tmp = tmp->next)) {
248 lefcha 1.12 if (tmp->type != MASK_TYPE_OR) {
249     strncat(search, "ALL ", searchbuf - len - 1);
250     len += 4;
251     break;
252     }
253 lefcha 1.9 }
254 lefcha 1.1
255 lefcha 1.9 tmp = NULL;
256 lefcha 1.1 while (mask) {
257 lefcha 1.9 tmp = mask;
258     mask = mask->next;
259 lefcha 1.1
260 lefcha 1.9 if (mask && mask->type == MASK_TYPE_OR) {
261 lefcha 1.3 strncat(search, "OR (", searchbuf - len - 1);
262 lefcha 1.1 len += 4;
263    
264 lefcha 1.9 strncat(search, tmp->body, searchbuf - len - 1);
265     len = strlen(search);
266     search[len] = ' ';
267     search[++len] = 0;
268    
269     search[len - 1] = ')';
270     search[len] = ' ';
271     search[++len] = 0;
272    
273     if (!mask->next || mask->next->type != MASK_TYPE_OR) {
274     search[len] = '(';
275     search[++len] = 0;
276     strncat(search, mask->body, searchbuf - len - 1);
277 lefcha 1.1 len = strlen(search);
278 lefcha 1.9 search[len] = ')';
279     search[++len] = ' ';
280 lefcha 1.3 search[++len] = 0;
281 lefcha 1.9 mask = mask->next;
282 lefcha 1.1 }
283 lefcha 1.9 } else {
284     strncat(search, tmp->body, searchbuf - len - 1);
285     len = strlen(search);
286 lefcha 1.3 search[len] = ' ';
287     search[++len] = 0;
288 lefcha 1.1 }
289     }
290 lefcha 1.10
291 lefcha 1.9 search[len - 1] = 0;
292 lefcha 1.5
293 lefcha 1.3 return search;
294 lefcha 1.1 }
295    
296    
297     /*
298     * Generate the filter search command from the masks, assuming that
299 lefcha 1.22 * masks are OR-ed.
300 lefcha 1.1 */
301 lefcha 1.9 char *generate_filter_or(mask_t * mask, unsigned int masknum,
302 lefcha 1.10 unsigned int masklen)
303 lefcha 1.1 {
304 lefcha 1.3 const unsigned int searchbuf = masklen + masknum * 6 + 8;
305 lefcha 1.15 unsigned int len = 0;
306 lefcha 1.3 char *search;
307     mask_t **mfifo; /* Mailbox FIFO queue. */
308 lefcha 1.1 mask_t *mf; /* Mask returned from FIFO. */
309 lefcha 1.5
310     search = (char *) xmalloc(sizeof(char) * searchbuf);
311     mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));
312 lefcha 1.1
313 lefcha 1.3 search[0] = 0;
314 lefcha 1.1 empty_fifo(mfifo);
315    
316 lefcha 1.3 strncat(search, "ALL ", searchbuf - len - 1);
317 lefcha 1.1 len += 4;
318    
319     while (mask) {
320 lefcha 1.3 queue_fifo(mfifo, mask);
321 lefcha 1.1 mask = mask->next;
322    
323     while (mask && mask->type == MASK_TYPE_AND) {
324 lefcha 1.3 queue_fifo(mfifo, mask);
325 lefcha 1.1 mask = mask->next;
326     }
327    
328     if (mask) {
329 lefcha 1.3 if (len == 4 && search[0] == 'A')
330     search[0] = len = 0;
331 lefcha 1.5
332 lefcha 1.3 strncat(search, "OR ", searchbuf - len - 1);
333 lefcha 1.1 len += 3;
334     }
335 lefcha 1.3 if (search[0] != 'A') {
336     search[len] = '(';
337     search[++len] = 0;
338     }
339     while ((mf = dequeue_fifo(mfifo))) {
340     strncat(search, mf->body, searchbuf - len - 1);
341 lefcha 1.1 len = strlen(search);
342 lefcha 1.3 search[len] = ' ';
343     search[++len] = 0;
344 lefcha 1.1 }
345    
346 lefcha 1.3 if (strchr(search, '(')) {
347     search[len - 1] = ')';
348     search[len] = ' ';
349     search[++len] = 0;
350     }
351 lefcha 1.1 empty_fifo(mfifo);
352     }
353    
354     search[len - 1] = 0;
355 lefcha 1.10
356 lefcha 1.19 xfree(mfifo);
357 lefcha 1.3
358     return search;
359 lefcha 1.1 }
360    
361    
362     /*
363     * Apply the appropriate action.
364     */
365 lefcha 1.21 int apply_action(char *mesgs, unsigned int *type, account_t *raccount,
366     char *destmbox, char *args)
367 lefcha 1.1 {
368 lefcha 1.3 unsigned int cnt;
369 lefcha 1.5
370 lefcha 1.3 if (!*mesgs)
371 lefcha 1.1 return 0;
372 lefcha 1.21
373 lefcha 1.4 log_info(LOG_ACTION, type);
374     log_info(LOG_DESTINATION_MAILBOX, destmbox);
375 lefcha 1.21
376     cnt = count_messages(mesgs);
377    
378 lefcha 1.3 switch (*type) {
379 lefcha 1.1 case FILTER_ACTION_DELETE:
380 lefcha 1.8 info("%d message%s deleted.\n", cnt, plural(cnt));
381 lefcha 1.1 action_delete(mesgs, args);
382     break;
383     case FILTER_ACTION_COPY:
384 lefcha 1.20 info("%d message%s copied to mailbox \"%s\".\n", cnt, plural(cnt),
385 lefcha 1.8 destmbox);
386 lefcha 1.21 action_copy(mesgs, apply_namespace(destmbox, nsppri.prefix,
387     nsppri.delim), args);
388 lefcha 1.1 break;
389     case FILTER_ACTION_MOVE:
390 lefcha 1.20 info("%d message%s moved to mailbox \"%s\".\n", cnt, plural(cnt),
391 lefcha 1.8 destmbox);
392 lefcha 1.21 action_move(mesgs, apply_namespace(destmbox, nsppri.prefix,
393     nsppri.delim), args);
394     break;
395     case FILTER_ACTION_RCOPY:
396     info("%d message%s copied to mailbox \"%s\" at account %s\n", cnt,
397     plural(cnt), destmbox, raccount->key);
398     action_rcopy(mesgs, raccount, destmbox, args);
399     break;
400     case FILTER_ACTION_RMOVE:
401     info("%d messages%s moved to mailbox \"%s\" at account %s\n", cnt,
402     plural(cnt), destmbox, raccount->key);
403     action_rmove(mesgs, raccount, destmbox, args);
404 lefcha 1.1 break;
405     case FILTER_ACTION_LIST:
406 lefcha 1.8 info("%d message%s listed.\n", cnt, plural(cnt));
407 lefcha 1.1 action_list(mesgs, args);
408     break;
409     }
410 lefcha 1.5
411     if (!*args)
412 lefcha 1.4 log_info(LOG_WRITE, NULL);
413 lefcha 1.5
414 lefcha 1.1 return 0;
415     }
416    
417    
418     /*
419     * Delete messages and optionally list some of their headers.
420     */
421     int action_delete(char *mesgs, char *args)
422     {
423 lefcha 1.23 char *tok, *mcp, *m, *cm;
424    
425     action_list(mesgs, args);
426 lefcha 1.21
427 lefcha 1.23 cm = convert_messages(mesgs);
428 lefcha 1.1
429 lefcha 1.23 m = mcp = xstrdup(cm);
430 lefcha 1.21
431     while ((tok = strsep(&m, " ")))
432     server_response(&sockpri, imap_store(&sockpri, tok, "\\Deleted"));
433 lefcha 1.5
434 lefcha 1.23 xfree(cm);
435 lefcha 1.19 xfree(mcp);
436 lefcha 1.10
437 lefcha 1.23
438 lefcha 1.1 return 0;
439     }
440    
441    
442     /*
443     * Copy messages to specified mailbox.
444     */
445 lefcha 1.3 int action_copy(char *mesgs, char *destmbox, char *args)
446 lefcha 1.1 {
447 lefcha 1.20 int r = 0;
448 lefcha 1.23 char *tok = NULL, *mcp, *m, *cm;
449 lefcha 1.21
450     action_list(mesgs, args);
451    
452 lefcha 1.23 cm = convert_messages(mesgs);
453    
454     m = mcp = xstrdup(cm);
455    
456 lefcha 1.22 while ((tok = strsep(&m, " "))) {
457     if ((r = copy_response(&sockpri,
458     imap_copy(&sockpri, tok, destmbox))) ==
459     RESPONSE_TRYCREATE)
460     if (!server_response(&sockpri, imap_create(&sockpri, destmbox))) {
461     server_response(&sockpri, imap_subscribe(&sockpri, destmbox));
462     r = copy_response(&sockpri, imap_copy(&sockpri, tok, destmbox));
463     }
464     }
465 lefcha 1.23
466     xfree(cm);
467 lefcha 1.19 xfree(mcp);
468 lefcha 1.8
469 lefcha 1.20 return r;
470 lefcha 1.1 }
471    
472    
473     /*
474     * Move messages to specified mailbox.
475     */
476 lefcha 1.3 int action_move(char *mesgs, char *destmbox, char *args)
477 lefcha 1.1 {
478 lefcha 1.20 if (!action_copy(mesgs, destmbox, args))
479     action_delete(mesgs, "\0");
480 lefcha 1.16
481 lefcha 1.17 /* CLOSE -> SELECT much faster than EXPUNGE -> SELECT */
482 lefcha 1.16 /* server_response(imap_expunge()); */
483 lefcha 1.1
484     return 0;
485     }
486    
487    
488     /*
489 lefcha 1.21 * Copy messages to the specified mailbox of another mail server.
490     */
491     int action_rcopy(char *mesgs, account_t *destacc, char *destmbox, char *args)
492     {
493     int r;
494     char *tok, *m, *mcp, *ndm;
495     unsigned int n, t = 0;
496     char buf[RESPONSE_BUF];
497    
498     if (init_connection(&sockaux, destacc->server, destacc->port,
499     destacc->ssl))
500     return ERROR_NETWORK;
501    
502     r = greeting_response(&sockaux);
503    
504     if (r == RESPONSE_BYE || check_capabilities(&sockaux))
505     return ERROR_NETWORK;
506    
507     #ifdef DEBUG
508     test(&sockaux);
509     #endif
510    
511     if (r != RESPONSE_PREAUTH) {
512     if (destacc->passwdattr == PASSWORD_NONE) {
513     printf("Enter password for %s@%s: ", destacc->username,
514     destacc->server);
515     get_password(destacc->password, PASSWORD_LEN);
516     destacc->passwdattr = PASSWORD_PLAIN;
517     }
518     if (login(&sockaux, destacc->username,
519     destacc->password) == RESPONSE_NO) {
520     error("imapfilter: username %s or password rejected at %s\n",
521     destacc->username, destacc->server);
522     return ERROR_NETWORK;
523     }
524     }
525     check_namespace(&sockaux, &nspaux);
526    
527     /* apply_namespace() returns a pointer to a static buffer. */
528     ndm = apply_namespace(destmbox, nspaux.prefix, nspaux.delim);
529    
530     r = check_mailbox(&sockaux, ndm, &nspaux);
531    
532     if (r == RESPONSE_OK)
533     close_mailbox(&sockaux);
534     else if (r == RESPONSE_NO) {
535     server_response(&sockaux, imap_create(&sockaux, ndm));
536     server_response(&sockaux, imap_subscribe(&sockaux, ndm));
537     }
538    
539     m = mcp = xstrdup(mesgs);
540    
541     while ((tok = strsep(&m, " "))) {
542     fetchsize_response(&sockpri, &n,
543     imap_fetch(&sockpri, tok, "RFC822.SIZE"));
544    
545     t = imap_append(&sockaux, ndm, n);
546    
547 lefcha 1.24 fetch_response(&sockpri, 1, NULL, 0);
548 lefcha 1.21 do {
549     r = fetch_response(&sockpri, 0, buf, imap_fetch(&sockpri, tok,
550     "RFC822.HEADER"));
551 lefcha 1.24
552 lefcha 1.21 socket_write(&sockaux, buf);
553     } while (r == RESPONSE_NONE);
554    
555     socket_write(&sockaux, "\r\n");
556    
557     fetch_response(&sockpri, 1, NULL, 0);
558     do {
559     r = fetch_response(&sockpri, 0, buf, imap_fetch(&sockpri, tok,
560     "BODY[TEXT]"));
561    
562     socket_write(&sockaux, buf);
563     } while (r == RESPONSE_NONE);
564 lefcha 1.24
565     socket_write(&sockaux, "\r\n\r\n");
566    
567     append_response(&sockaux, t);
568 lefcha 1.21 }
569    
570     logout(&sockaux);
571    
572     action_list(mesgs, args);
573    
574     xfree(mcp);
575    
576     return 0;
577     }
578    
579    
580     /*
581     * Move messages to the specified mailbox of another mail server.
582     */
583     int action_rmove(char *mesgs, account_t *destacc, char *destmbox, char *args)
584     {
585     if (!action_rcopy(mesgs, destacc, destmbox, args))
586     action_delete(mesgs, "\0");
587    
588     return 0;
589     }
590    
591    
592     /*
593 lefcha 1.1 * List user selected headers of messages.
594     */
595     int action_list(char *mesgs, char *args)
596     {
597 lefcha 1.21 int r;
598     char *tok, *mcp, *m;
599     char s[ARGS_LEN + 27];
600     char hdrs[RESPONSE_BUF];
601 lefcha 1.5
602 lefcha 1.2 if (!*args)
603     return 0;
604 lefcha 1.1
605 lefcha 1.5 m = mcp = xstrdup(mesgs);
606 lefcha 1.6
607 lefcha 1.21 snprintf(s, ARGS_LEN + 27 - 1, "BODY.PEEK[HEADER.FIELDS (%s)]", args);
608 lefcha 1.1
609 lefcha 1.21 while ((tok = strsep(&m, " "))) {
610     /* Reset internal fetch counter. */
611     fetch_response(&sockpri, 1, NULL, 0);
612    
613     do {
614     r = fetch_response(&sockpri, 0, hdrs, imap_fetch(&sockpri, tok, s));
615    
616     if (*hdrs) {
617     if (options & OPTION_HEADERS)
618     info("%s\n", hdrs);
619     log_info(LOG_WRITE, hdrs);
620     } else {
621     log_info(LOG_WRITE, NULL);
622     }
623     } while (r == RESPONSE_NONE);
624     }
625 lefcha 1.1
626 lefcha 1.19 xfree(mcp);
627 lefcha 1.1
628     return 0;
629     }
630    
631    
632     /*
633 lefcha 1.21 * Count how many messages matched the filter.
634     */
635     unsigned int count_messages(char *mesgs)
636     {
637     unsigned int cnt = 0;
638     char *c = mesgs;
639    
640     while ((c = strchr(c, ' '))) {
641     cnt++;
642     c++;
643     }
644    
645     return ++cnt;
646     }
647    
648    
649     /*
650 lefcha 1.11 * Convert messages with contiguous sequence number to the corresponding
651 lefcha 1.5 * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8
652 lefcha 1.1 */
653 lefcha 1.23 char *convert_messages(char *mesgs)
654 lefcha 1.1 {
655 lefcha 1.21 unsigned int maxlen;
656 lefcha 1.1 unsigned int start, end, tmp;
657 lefcha 1.23 char *c, *cp, *tail;
658 lefcha 1.21
659     start = end = tmp = 0;
660 lefcha 1.13 maxlen = strlen(mesgs) + 1;
661     tail = NULL;
662 lefcha 1.1
663 lefcha 1.23 c = cp = xstrdup(mesgs);
664 lefcha 1.1
665 lefcha 1.23 start = (unsigned int) strtoul(mesgs, &tail, 10);
666 lefcha 1.1 end = start;
667    
668     do {
669     if (tail) {
670 lefcha 1.10 tmp = (unsigned int) strtoul(tail, &tail, 10);
671 lefcha 1.21 if (!tmp)
672 lefcha 1.15 tail = NULL;
673 lefcha 1.1 }
674     if (tmp == end + 1)
675     end++;
676     else {
677 lefcha 1.13 if (start == end) {
678 lefcha 1.23 xstrncpy(c, ultostr(start, 10), maxlen);
679     c += strlen(c);
680 lefcha 1.13 } else {
681 lefcha 1.23 xstrncpy(c, ultostr(start, 10), maxlen - 1);
682     c += strlen(c);
683     *c = ':';
684     *++c = 0;
685     xstrncpy(c, ultostr(end, 10), maxlen);
686     c += strlen(c);
687 lefcha 1.13 }
688 lefcha 1.1
689 lefcha 1.23 if (tail && c - cp < maxlen) {
690     *c = ' ';
691     *++c = 0;
692 lefcha 1.13 }
693 lefcha 1.1 start = end = tmp;
694     }
695     } while (tmp);
696    
697 lefcha 1.23 return cp;
698 lefcha 1.1 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26