source: EcnlProtoTool/trunk/asp3_dcre/sample/sample1n.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 16.2 KB
RevLine 
[270]1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
[331]4 * Copyright (C) 2001-2012 by Dep. of Computer Science and Engineering
[270]5 * Tomakomai National College of Technology, JAPAN
6 *
7 * 上記著作権者は,以下の (1)~(4) の条件か,Free Software Foundation
8 * によって公表されている GNU General Public License の Version 2 に記
9 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
10 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
11 * 利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14 * スコード中に含まれていること.
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18 * の無保証規定を掲載すること.
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次の条件を満たすこと.
21 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
22 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 *
26 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
27 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
28 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
29 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
30 *
31 * @(#) $Id$
32 */
33
34/*
35 * ネットワーク化サンプルプログラム(1)の本体
36 */
37
38#include <stdarg.h>
39
40#include <kernel.h>
[331]41#include "syssvc/syslog.h"
[270]42#include "syssvc/serial.h"
43#include "kernel_cfg.h"
44#include "tinet_cfg.h"
45
46#include <netinet/in.h>
47#include <netinet/in_itron.h>
48
49#include "sample1n.h"
50
51/*
52 * マクロ定義
53 */
54
55/* リネームの解除 */
56
57#undef syslog
58#undef serial_rea_dat
59#undef serial_ctl_por
60
61#define EOF (-1)
62
63/* TELNET オプション */
64
65#define TELNET_OPT_SE (240)
66#define TELNET_OPT_NOP (241)
67#define TELNET_OPT_DM (242)
68#define TELNET_OPT_BRK (243)
69#define TELNET_OPT_IP (244)
70#define TELNET_OPT_AO (245)
71#define TELNET_OPT_AYT (246)
72#define TELNET_OPT_EC (247)
73#define TELNET_OPT_EL (248)
74#define TELNET_OPT_GA (249)
75#define TELNET_OPT_SB (250)
76#define TELNET_OPT_WILL (251)
77#define TELNET_OPT_WONT (252)
78#define TELNET_OPT_DO (253)
79#define TELNET_OPT_DONT (254)
80#define TELNET_OPT_IAC (255)
81
82/*
83 * 変数
84 */
85
86/* TCP 送受信ウィンドバッファ */
87
88uint8_t tcp_swbuf[TCP_SWBUF_SIZE];
89uint8_t tcp_rwbuf[TCP_RWBUF_SIZE];
90
91bool_t connected = false; /* コネクションの状態 */
92bool_t wait_accept = false; /* 接続要求待ち中 */
93
[331]94#ifdef SUPPORT_INET6
95
96T_IPV6EP dst;
97
98#else /* of #ifdef SUPPORT_INET6 */
99
[270]100#ifdef SUPPORT_INET4
101
102T_IPV4EP dst;
103
104#endif /* of #ifdef SUPPORT_INET4 */
105
106#endif /* of #ifdef SUPPORT_INET6 */
107
108uint8_t *snd_buff = NULL;
109uint8_t *rcv_buff = NULL;
110uint_t snd_off = 0;
111uint_t rcv_off = 0;
112ER_UINT snd_len = 0;
113ER_UINT rcv_len = 0;
114uint_t net_ioctl = IOCTL_NULL;
115uint8_t addr[sizeof("0123:4567:89ab:cdef:0123:4567:89ab:cdef")];
116
117/*
118 * ネットワーク層の選択
119 */
120
[331]121#ifdef SUPPORT_INET6
122
123#define TCP_ACP_CEP(c,r,d,t) tcp6_acp_cep(c,r,d,t)
124#define IP2STR(s,a) ipv62str(s,a)
125
126#else /* of #ifdef SUPPORT_INET6 */
127
[270]128#ifdef SUPPORT_INET4
129
130#define TCP_ACP_CEP(c,r,d,t) tcp_acp_cep(c,r,d,t)
131#define IP2STR(s,a) ip2str(s,a)
132
133#endif /* of #ifdef SUPPORT_INET4 */
134
135#endif /* of #ifdef SUPPORT_INET6 */
136
137/*
138 * ノンブロッキングコールのコールバック関数
139 */
140
141ER
142callback_nblk_tcp (ID cepid, FN fncd, void *p_parblk)
143{
144 ER error = E_OK;
145
146 switch (fncd) {
147
148 case TFN_TCP_ACP_CEP:
[331]149 IP2STR((char *)addr, &dst.ipaddr);
[270]150 syslog(LOG_NOTICE, "connected: %s.%d", addr, dst.portno);
151 if (*(ER*)p_parblk == E_OK)
152 connected = true;
153 snd_len = snd_off = rcv_len = rcv_off = 0;
154 wait_accept = false;
155 break;
156
157 case TFN_TCP_CLS_CEP:
158 case TFN_TCP_RCV_BUF:
159 case TFN_TCP_GET_BUF:
160 case TFN_TCP_RCV_DAT:
161 case TFN_TCP_SND_DAT:
162 case TFN_TCP_CON_CEP:
163 case TFN_TCP_SND_OOB:
164 default:
165 error = E_PAR;
166 break;
167 }
168 return error;
169 }
170
171/*
172 * コネクションを切断
173 */
174
175ER
176disconnecting (void)
177{
178 ER error = E_OK;
179
180 if (connected) {
181 syscall(wai_sem(SEM_NET_SEND));
182 if (snd_off > 0)
183 tcp_snd_buf(TCP_CEPID, snd_off);
184 tcp_sht_cep(TCP_CEPID);
185 tcp_cls_cep(TCP_CEPID, TMO_FEVR);
186 connected = false;
187 syscall(sig_sem(SEM_NET_SEND));
[331]188 IP2STR((char *)addr, &dst.ipaddr);
[270]189 syslog(LOG_NOTICE, "disconnected: %s.%d", addr, dst.portno);
190 }
191 return error;
192 }
193
194/*
195 * 送信バッファのフラッシュ
196 */
197
198void
199flush_snd_buff (ID cepid)
200{
201 if (connected) {
202 syscall(wai_sem(SEM_NET_SEND));
203 if (snd_off > 0) {
204 tcp_snd_buf(cepid, snd_off);
205 snd_len = snd_off = 0;
206 }
207 syscall(sig_sem(SEM_NET_SEND));
208 }
209 return;
210 }
211
212/*
213 * 文字送信
214 */
215
216void
217put_char (ID cepid, char ch)
218{
219 if (connected) {
220 if (ch == '\n' && (net_ioctl & IOCTL_CRLF) != 0)
221 put_char(cepid, '\r');
222 syscall(wai_sem(SEM_NET_SEND));
223 if (snd_off >= snd_len) {
224 if (tcp_snd_buf(cepid, snd_off) != E_OK) {
225 syscall(sig_sem(SEM_NET_SEND));
226 return;
227 }
228 snd_off = 0;
229 if ((snd_len = tcp_get_buf(cepid, (void**)&snd_buff, TMO_FEVR)) <= 0) {
230 syscall(sig_sem(SEM_NET_SEND));
231 return;
232 }
233 }
234 snd_buff[snd_off ++] = ch;
235 syscall(sig_sem(SEM_NET_SEND));
236 }
237 }
238
239/*
240 * 文字受信(変換なし)
241 */
242
243int_t
244get_char_raw (ID cepid)
245{
246 if (connected) {
247 if (rcv_off >= rcv_len) {
248 rcv_off = 0;
249 if (tcp_rel_buf(TCP_CEPID, rcv_len) != E_OK) {
250 disconnecting();
251 return EOF;
252 }
253 if ((rcv_len = tcp_rcv_buf(TCP_CEPID, (void**)&rcv_buff, TMO_FEVR)) == 0) {
254 disconnecting();
255 return EOF;
256 }
257 else if (rcv_len < 0) {
258 disconnecting();
259 return EOF;
260 }
261 }
262 return rcv_buff[rcv_off ++];
263 }
264 else
265 return EOF;
266 }
267
268/*
269 * 文字受信(TELNET オプションをスキップ)
270 */
271
272int_t
273get_char (ID cepid)
274{
275 int_t ch, req;
276
277 while ((ch = get_char_raw(cepid)) == TELNET_OPT_IAC || ch == '\0') {
278 if (ch != '\0') {
279 switch (ch = get_char_raw(cepid)) {
280 case TELNET_OPT_WILL:
281 case TELNET_OPT_WONT:
282 case TELNET_OPT_DO:
283 case TELNET_OPT_DONT:
284 req = get_char_raw(cepid);
285 break;
286 case TELNET_OPT_SB:
287 while ((ch = get_char_raw(cepid)) != EOF && ch != TELNET_OPT_IAC) {
288 if ((ch = get_char_raw(cepid)) == EOF || ch == TELNET_OPT_SE)
289 break;
290 }
291 break;
292 default:
293 break;
294 }
295 }
296 }
297 return ch;
298 }
299
300/*
301 * シリアルポートからの読出し
302 */
303
304ER_UINT
305net_serial_rea_dat (ID portid, char *buf, uint_t len)
306{
307 T_SERIAL_RPOR rpor;
308 uint_t off;
309 int_t ch;
310
311 if (!wait_accept && !connected) {
312 wait_accept = true;
313 if (TCP_ACP_CEP(TCP_CEPID, TCP_REPID, &dst, TMO_NBLK) != E_WBLK)
314 return 0;
315 }
316
317 while (true) {
318 if (connected) {
319 off = 0;
320 while (off < len && (ch = get_char(TCP_CEPID)) != EOF) {
321 *(buf + off ++) = ch;
322 if ((net_ioctl & IOCTL_ECHO) != 0) {
323 put_char(TCP_CEPID, ch);
324 flush_snd_buff(TCP_CEPID);
325 }
326 }
327 return off;
328 }
329 else if (serial_ref_por(portid, &rpor) == E_OK && rpor.reacnt > 0) {
330 return serial_rea_dat(portid, buf, len);
331 }
[331]332 dly_tsk(500000);
[270]333 }
334 return off;
335 }
336
337/*
338 * シリアルポートの制御
339 */
340
341ER
342net_serial_ctl_por (ID portid, uint_t ioctl)
343{
344 net_ioctl = ioctl;
345 return serial_ctl_por(portid, ioctl);
346 }
347
348/*
349 * もっとも長い整数型 (LONGEST) と符号なし整数型 (ULONGEST)
350 */
351
352#ifdef LONGLONG_TYPE
353
354typedef LONGLONG_TYPE LONGEST;
355typedef unsigned LONGLONG_TYPE ULONGEST;
356
357#else /* of #ifdef LONGLONG_TYPE */
358
359#ifdef LONG_TYPE
360
361typedef LONG_TYPE LONGEST;
362typedef unsigned LONG_TYPE ULONGEST;
363
364#else /* of #ifdef LONG_TYPE */
365
366typedef int_t LONGEST;
367typedef uint_t ULONGEST;
368
369#endif /* of #ifdef LONG_TYPE */
370
371#endif /* of #ifdef LONGLONG_TYPE */
372
373/*
374 * ログのシミュレーション
375 */
376
377/* 数値変換のための変換表 */
378
379static const char radhex[] = "0123456789abcdef";
380static const char radHEX[] = "0123456789ABCDEF";
381
382/*
383 * put_num -- printf の数値変換
384 */
385
386int_t
387put_num(ID cepid, ULONGEST val, int_t radix, const char *radchar, int_t width, bool_t minus, char padchar)
388{
389 char digits[24];
390 int_t ix, pad, pchars;
391 bool_t left;
392
393 if (width < 0) {
394 width = -width;
395 left = true;
396 }
397 else
398 left = false;
399
400 ix = 0;
401 do {
402 digits[ix ++] = radchar[val % radix];
403 val /= radix;
404 } while (val != 0);
405
406 if (minus)
407 digits[ix ++] = '-';
408
409 if (width > ix)
410 pchars = width;
411 else
412 pchars = ix;
413
414 pad = ix;
415 if (!left) /* 右詰め */
416 for ( ; pad < width; pad ++)
417 put_char(cepid, padchar);
418
419 while (ix -- > 0)
420 put_char(cepid, digits[ix]);
421
422 if (left) /* 左詰め */
423 for ( ; pad < width; pad ++)
424 put_char(cepid, padchar);
425
426 return pchars;
427 }
428
429/*
430 * ipv6addr -- IPv6 アドレス出力
431 */
432
[331]433int_t
[270]434put_ipv6addr (ID cepid, const T_IN6_ADDR *addr, int_t width)
435{
436 int_t len = 0, ix;
437 bool_t omit = false, zero = false;
438
439 if (addr == NULL) {
440 put_char(cepid, '0');
441 put_char(cepid, ':');
442 put_char(cepid, ':');
443 put_char(cepid, '0');
444 len = 4;
445 }
446 else {
447 for (ix = 0; ix < sizeof(T_IN6_ADDR) / 2; ix ++) {
448 if (omit) {
449 len += put_num(cepid, addr->s6_addr16[ix], 16, radhex, 0, false, ' ');
450 if (ix < 7) {
451 put_char(cepid, ':');
452 len ++;
453 }
454 }
455 else if (ix > 0 && ix < 7 && addr->s6_addr16[ix] == 0)
456 zero = true;
457 else {
458 if (zero) {
459 omit = true;
460 put_char(cepid, ':');
461 len ++;
462 }
463 len += put_num(cepid, addr->s6_addr16[ix], 16, radhex, 0, false, ' ');
464 if (ix < 7) {
465 put_char(cepid, ':');
466 len ++;
467 }
468 }
469 }
470
471 for ( ; len < width; len ++)
472 put_char(cepid, ' ');
473 }
474 return len;
475 }
476
[331]477/*
478 * put_ipv4addr -- IPv4 アドレス出力
479 */
[270]480
[331]481int_t
482put_ipv4addr (ID cepid, ULONGEST *addr, int_t width)
483{
484 int_t len = 3; /* 3 は '.' の文字数 */
[270]485
[331]486#if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN
487
488 len += put_num(cepid, (*addr >> 24) & 0xff, 10, radhex, 0, false, ' ');
489 put_char(cepid, '.');
490 len += put_num(cepid, (*addr >> 16) & 0xff, 10, radhex, 0, false, ' ');
491 put_char(cepid, '.');
492 len += put_num(cepid, (*addr >> 8) & 0xff, 10, radhex, 0, false, ' ');
493 put_char(cepid, '.');
494 len += put_num(cepid, *addr & 0xff, 10, radhex, 0, false, ' ');
495
496#else /* of #if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN */
497
498 len += put_num(cepid, *addr & 0xff, 10, radhex, 0, false, ' ');
499 put_char(cepid, '.');
500 len += put_num(cepid, (*addr >> 8) & 0xff, 10, radhex, 0, false, ' ');
501 put_char(cepid, '.');
502 len += put_num(cepid, (*addr >> 16) & 0xff, 10, radhex, 0, false, ' ');
503 put_char(cepid, '.');
504 len += put_num(cepid, (*addr >> 24) & 0xff, 10, radhex, 0, false, ' ');
505
506#endif /* of #if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN */
507
508 for ( ; len < width; len ++)
509 put_char(cepid, ' ');
510
511 return len;
512 }
513
[270]514/*
515 * put_macaddr -- MAC アドレス出力
516 */
517
518static int_t
519put_macaddr (ID cepid, char *mac, int_t width)
520{
521 int_t oct, len;
522
523 for (oct = 5; oct -- > 0; ) {
524 put_num(cepid, *mac ++, 16, radhex, 2, false, '0');
525 put_char(cepid, ':');
526 }
527 put_num(cepid, *mac, 16, radhex, 2, false, '0');
528
529 for (len = 17; len < width; len ++)
530 put_char(cepid, ' ');
531
532 return len;
533 }
534
535/*
536 * 引数を取り出すためのマクロ
537 */
538
539#ifdef LONGLONG_TYPE
540
541#ifdef LONG_TYPE
542
543#define GET_ARG(ap,lf) ((lf > 1) ? va_arg(ap, LONGLONG_TYPE) \
544 (lf ? va_arg(ap, LONG_TYPE) \
545 : va_arg(ap, int_t)))
546
547#else /* of #ifdef LONG_TYPE */
548
549#define GET_ARG(ap,lf) ((lf > 1) ? va_arg(ap, LONGLONG_TYPE) \
550 : va_arg(ap, int_t))
551
552#endif /* of #ifdef LONG_TYPE */
553
554#else /* of #ifdef LONGLONG_TYPE */
555
556#ifdef LONG_TYPE
557
558#define GET_ARG(ap,lf) (lf ? va_arg(ap, LONG_TYPE) \
559 : va_arg(ap, int_t))
560
561#else /* of #ifdef LONG_TYPE */
562
563#define GET_ARG(ap,lf) (va_arg(ap, int_t))
564
565#endif /* of #ifdef LONG_TYPE */
566
567#endif /* of #ifdef LONGLONG_TYPE */
568
569/*
570 * ログ出力
571 */
572
573void
574net_syslog (uint_t prio, const char *format, ...)
575{
576 LONGEST val;
577 SYSLOG log;
578 va_list ap;
579 char padchar, *str;
[331]580 int_t ch, width, longflag, shortflag, left, i, c;
[270]581
582 if (connected) {
583 syscall(wai_sem(SEM_TCP_SYSLOG));
584 va_start(ap, format);
585 while ((ch = *format ++) != '\0') {
586 if (ch != '%') { /* 書式指定以外 */
587 put_char(TCP_CEPID, (char)ch);
588 continue;
589 }
590
[331]591 width = longflag = shortflag = 0;
[270]592 padchar = ' ';
593
594 if (ch == '-') { /* 左詰め */
595 format ++;
596 left = -1;
597 }
598 else
599 left = 1;
600
601 if ((ch = *format ++) == '0') { /* 上位桁の 0 */
602 padchar = '0';
603 ch = *format ++;
604 }
605
606 while ('0' <= ch && ch <= '9') { /* 出力幅 */
607 width = width * 10 + ch - '0';
608 ch = *format ++;
609 }
610
611 while (ch == 'l') { /* long (long) の指定 */
612 longflag ++;
613 ch = *format ++;
614 }
615
[331]616 while (ch == 'h') { /* short の指定 */
617 shortflag ++;
618 ch = *format ++;
619 }
620
[270]621 switch (ch) {
622 case 'd':
623 val = GET_ARG(ap, longflag);
624 if (val >= 0)
625 put_num(TCP_CEPID, val, 10, radhex, width * left, false, padchar);
626 else
627 put_num(TCP_CEPID, -val, 10, radhex, width * left, true, padchar);
628 break;
629
630 case 'u':
631 val = GET_ARG(ap, longflag);
632 put_num(TCP_CEPID, val, 10, radhex, width * left, false, padchar);
633 break;
634
635 case 'x':
636 val = GET_ARG(ap, longflag);
637 put_num(TCP_CEPID, val, 16, radhex, width * left, false, padchar);
638 break;
639
640 case 'X':
641 val = GET_ARG(ap, longflag);
642 put_num(TCP_CEPID, val, 16, radHEX, width * left, false, padchar);
643 break;
644
645 case 'c':
646 ch = va_arg(ap, int_t);
647 put_char(TCP_CEPID, (char)ch);
648 break;
649
650 case 's':
651 str = va_arg(ap, char*);
652 while ((ch = *str ++) != '\0') {
653 put_char(TCP_CEPID, (char)ch);
654 width --;
655 }
656 while (width -- > 0)
657 put_char(TCP_CEPID, ' ');
658 break;
659
660 case 'I':
661
[331]662 if (longflag) {
663 str = va_arg(ap, char*);
664 put_ipv6addr(TCP_CEPID, (T_IN6_ADDR *)str, width);
665 }
666 else if (shortflag) {
667 val = GET_ARG(ap, longflag);
668 put_ipv4addr(TCP_CEPID, (ULONGEST *)val, width);
669 }
670 else {
671
672#ifdef SUPPORT_INET6
673
674 str = va_arg(ap, char*);
675 put_ipv6addr(TCP_CEPID, (T_IN6_ADDR *)str, width);
676
677#else /* of #ifdef SUPPORT_INET6 */
678
[270]679#ifdef SUPPORT_INET4
680
[331]681 val = GET_ARG(ap, longflag);
682 put_ipv4addr(TCP_CEPID, (ULONGEST *)val, width);
[270]683
684#endif /* of #ifdef SUPPORT_INET4 */
685
[331]686#endif /* of #ifdef SUPPORT_INET6 */
[270]687
[331]688 }
[270]689
690 break;
691
692 case 'M':
693 str = va_arg(ap, char*);
694 put_macaddr(TCP_CEPID, str, width);
695 break;
696
697 case '%':
698 put_char(TCP_CEPID, '%');
699 break;
700
701 case '0':
702 format --;
703 break;
704
705 default:
706 break;
707 }
708
709 }
710 va_end(ap);
711 put_char(TCP_CEPID, '\n');
712 flush_snd_buff(TCP_CEPID);
713 syscall(sig_sem(SEM_TCP_SYSLOG));
[331]714 return;
[270]715 }
716 else {
717 log.logtype = LOG_TYPE_COMMENT;
718 log.logpar[0] = (intptr_t)format;
719 i = 1;
720 va_start(ap, format);
721
722 while ((c = *format++) != '\0' && i < TNUM_LOGPAR) {
723 if (c != '%') {
724 continue;
725 }
726
[331]727 longflag = 0;
[270]728 c = *format++;
729 while ('0' <= c && c <= '9') {
730 c = *format++;
731 }
[331]732
733 while (c == 'l') {
734 longflag = 1;
735 c = *format++;
736 }
737
[270]738 switch (c) {
739 case 'd':
[331]740 if(longflag == 1) {
741 log.logpar[i++] = (intptr_t)va_arg(ap, long_t);
742 }
743 else {
744 log.logpar[i++] = (intptr_t)va_arg(ap, int_t);
745 }
[270]746 break;
747 case 'u':
748 case 'x':
749 case 'X':
750 log.logpar[i++] = (intptr_t)va_arg(ap, uint_t);
751 break;
752 case 'p':
753 log.logpar[i++] = (intptr_t)va_arg(ap, void *);
754 break;
755 case 'c':
756 log.logpar[i++] = (intptr_t)va_arg(ap, int_t);
757 break;
758 case 's':
759 log.logpar[i++] = (intptr_t)va_arg(ap, const char *);
760 break;
761 case '\0':
762 format--;
763 break;
764 default:
765 break;
766 }
767 }
768 va_end(ap);
769 syslog_wri_log(prio, &log);
770 return;
771 }
772 }
Note: See TracBrowser for help on using the repository browser.