source: roaraudio/libroar/error.c @ 5393:f50243718494

Last change on this file since 5393:f50243718494 was 5381:430b1d26e12d, checked in by phi, 12 years ago

updated copyright years

File size: 32.2 KB
Line 
1//error.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2012
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38// 'no error' value for errno.
39// zero is true for GNU/Linux.
40// don't know about other systems.
41// IEEE Std 1003.1-2008 (POSIX 7) requires:
42// 'distinct positive values'.
43#define CLEAN_ERRNO 0
44
45static int roar_errno = ROAR_ERROR_NONE;
46
47struct roar_error_frame * roar_err_errorframe(void) {
48 static struct roar_error_frame frame = {
49  .version     =  0,
50  .cmd         = -1,
51  .ra_errno    = ROAR_ERROR_UNKNOWN,
52  .ra_suberrno = -1,
53  .p_errno     = -1,
54  .flags       =  0,
55  .datalen     =  0,
56  .data        = NULL
57 };
58
59 return &frame;
60}
61
62int    roar_err_init(struct roar_error_frame * frame) {
63 if ( frame == NULL ) {
64  roar_err_set(ROAR_ERROR_FAULT);
65  return -1;
66 }
67
68 memset(frame, 0, sizeof(struct roar_error_frame));
69
70 frame->cmd         = -1;
71 frame->ra_errno    = ROAR_ERROR_UNKNOWN;
72 frame->ra_suberrno = -1;
73 frame->p_errno     = -1;
74 frame->datalen     =  0;
75 frame->data        = NULL;
76
77 return 0;
78}
79
80
81void * roar_err_buildmsg(struct roar_message * mes, void ** data, struct roar_error_frame * frame) {
82 char * databuf = NULL;
83 int16_t * d;
84 size_t datalen;
85
86 if ( mes == NULL || frame == NULL ) {
87  roar_err_set(ROAR_ERROR_FAULT);
88  return NULL;
89 }
90
91 if ( data != NULL )
92  *data = NULL;
93
94 datalen = 8 + frame->datalen;
95 if ( datalen > LIBROAR_BUFFER_MSGDATA ) {
96  if ( data == NULL ) {
97   roar_err_set(ROAR_ERROR_FAULT);
98   return NULL;
99  }
100
101  roar_err_clear_errno();
102  *data = roar_mm_malloc(datalen);
103  roar_err_from_errno();
104  if ( *data == NULL )
105   return NULL;
106
107  databuf = *data;
108 } else {
109  databuf = mes->data;
110 }
111
112 memset(mes,  0, sizeof(struct roar_message));
113 memset(databuf, 0, mes->datalen);
114
115 mes->datalen = datalen;
116
117 d = (int16_t*)databuf;
118
119 frame->data  = &(databuf[8]);
120
121 databuf[0]    = 0; // version.
122 databuf[1]    = frame->cmd;
123 databuf[2]    = frame->ra_errno;
124 databuf[3]    = frame->ra_suberrno;
125 d[2]            = ROAR_HOST2NET16(frame->p_errno);
126 d[3]            = ROAR_HOST2NET16(frame->flags);
127
128 return frame->data;
129}
130
131int    roar_err_parsemsg(struct roar_message * mes, void *  data, struct roar_error_frame * frame) {
132 char * databuf = (char *)data;
133 int16_t * d;
134
135 ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = ?",
136          mes, (int)mes->datalen, mes->data, data, frame);
137
138 if ( mes == NULL || frame == NULL ) {
139  roar_err_set(ROAR_ERROR_FAULT);
140  ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = -1 // error=FAULT",
141           mes, (int)mes->datalen, mes->data, data, frame);
142  return -1;
143 }
144
145 ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = ?",
146          mes, (int)mes->datalen, mes->data, data, frame);
147
148 if ( databuf == NULL )
149  databuf = mes->data;
150
151 d = (int16_t*)databuf;
152
153 ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = ?",
154          mes, (int)mes->datalen, mes->data, data, frame);
155
156 if ( mes->datalen < 8 ) {
157  roar_err_set(ROAR_ERROR_MSGSIZE);
158  ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = -1 // error=MSGSIZE",
159           mes, (int)mes->datalen, mes->data, data, frame);
160  return -1;
161 }
162
163 ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = ?",
164          mes, (int)mes->datalen, mes->data, data, frame);
165
166 if ( databuf[0] != 0 ) {
167  roar_err_set(ROAR_ERROR_NSVERSION);
168  ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = -1 // error=NSVERSION",
169           mes, (int)mes->datalen, mes->data, data, frame);
170  return -1;
171 }
172
173 ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = ?",
174          mes, (int)mes->datalen, mes->data, data, frame);
175
176 frame->cmd         = databuf[1];
177 frame->ra_errno    = databuf[2];
178 frame->ra_suberrno = databuf[3];
179 frame->p_errno     = ROAR_NET2HOST16(d[2]);
180 frame->flags       = ROAR_NET2HOST16(d[3]);
181
182 frame->datalen     = mes->datalen - 8;
183 frame->data        = &(databuf[8]);
184
185 ROAR_DBG("roar_err_parsemsg2(mes=%p{.datalen=%i, .data=%p}, data=%p, frame=%p) = 0",
186          mes, (int)mes->datalen, mes->data, data, frame);
187 return 0;
188}
189
190int *  roar_errno2(void) {
191 return &roar_errno;
192}
193
194void   roar_err_clear(void) {
195 *roar_errno2() = ROAR_ERROR_NONE;
196}
197
198void   roar_err_clear_errno(void) {
199 errno = CLEAN_ERRNO;
200}
201
202void   roar_err_clear_all(void) {
203 roar_err_clear();
204 roar_err_clear_errno();
205}
206
207void   roar_err_update(void) {
208 int * err = roar_errno2();
209
210 // NOTE: _NEVER_ call ROAR_{DBG,INFO,WARN,ERR}() in here! (will result in endless loop)
211 //printf("*err=%i, errno=%i\n", *err, (int)errno);
212
213 if ( *err != ROAR_ERROR_NONE ) {
214  roar_err_to_errno();
215 } else if ( !roar_err_is_errno_clear() ) {
216  roar_err_from_errno();
217 }
218}
219
220int    roar_err_is_errno_clear(void) {
221 return errno == CLEAN_ERRNO ? 1 : 0;
222}
223
224void   roar_err_set(const int error) {
225 *roar_errno2() = error;
226}
227
228void   roar_err_from_errno(void) {
229 int _roar_errno = ROAR_ERROR_NONE;
230
231 switch (errno) {
232#ifdef EACCES
233  case EACCES:       _roar_errno = ROAR_ERROR_PERM; break;
234#endif
235#ifdef EPERM
236  case EPERM:        _roar_errno = ROAR_ERROR_PERM; break;
237#endif
238#ifdef ENOENT
239  case ENOENT:       _roar_errno = ROAR_ERROR_NOENT; break;
240#endif
241#ifdef EBADMSG
242  case EBADMSG:      _roar_errno = ROAR_ERROR_BADMSG; break;
243#endif
244#ifdef EBUSY
245  case EBUSY:        _roar_errno = ROAR_ERROR_BUSY; break;
246#endif
247#ifdef ECONNREFUSED
248  case ECONNREFUSED: _roar_errno = ROAR_ERROR_CONNREFUSED; break;
249#endif
250#ifdef ENOSYS
251  case ENOSYS:       _roar_errno = ROAR_ERROR_NOSYS; break;
252#endif
253#ifdef ENOTSUP
254  case ENOTSUP:      _roar_errno = ROAR_ERROR_NOTSUP; break;
255#endif
256#ifdef EPIPE
257  case EPIPE:        _roar_errno = ROAR_ERROR_PIPE; break;
258#endif
259#ifdef EPROTO
260  case EPROTO:       _roar_errno = ROAR_ERROR_PROTO; break;
261#endif
262#ifdef ERANGE
263  case ERANGE:       _roar_errno = ROAR_ERROR_RANGE; break;
264#endif
265#ifdef EMSGSIZE
266  case EMSGSIZE:     _roar_errno = ROAR_ERROR_MSGSIZE; break;
267#endif
268#ifdef ENOMEM
269  case ENOMEM:       _roar_errno = ROAR_ERROR_NOMEM; break;
270#endif
271#ifdef EINVAL
272  case EINVAL:       _roar_errno = ROAR_ERROR_INVAL; break;
273#endif
274#ifdef EALREADY
275  case EALREADY:     _roar_errno = ROAR_ERROR_ALREADY; break;
276#endif
277#ifdef EBADRQC
278  case EBADRQC:      _roar_errno = ROAR_ERROR_BADRQC; break;
279#endif
280#ifdef EDOM
281  case EDOM:         _roar_errno = ROAR_ERROR_DOM; break;
282#endif
283#ifdef EEXIST
284  case EEXIST:       _roar_errno = ROAR_ERROR_EXIST; break;
285#endif
286#ifdef EFAULT
287  case EFAULT:       _roar_errno = ROAR_ERROR_FAULT; break;
288#endif
289#ifdef EIO
290  case EIO:          _roar_errno = ROAR_ERROR_IO; break;
291#endif
292#ifdef EREMOTEIO
293  case EREMOTEIO:    _roar_errno = ROAR_ERROR_RIO; break;
294#endif
295#ifdef EKEYEXPIRED
296  case EKEYEXPIRED:  _roar_errno = ROAR_ERROR_KEYEXPIRED; break;
297#endif
298#ifdef EKEYREJECTED
299  case EKEYREJECTED: _roar_errno = ROAR_ERROR_KEYREJECTED; break;
300#endif
301#ifdef ELOOP
302  case ELOOP:        _roar_errno = ROAR_ERROR_LOOP; break;
303#endif
304#ifdef EMFILE
305  case EMFILE:       _roar_errno = ROAR_ERROR_MFILE; break;
306#endif
307#ifdef ENAMETOOLONG
308  case ENAMETOOLONG: _roar_errno = ROAR_ERROR_NAMETOOLONG; break;
309#endif
310#ifdef ENODATA
311  case ENODATA:      _roar_errno = ROAR_ERROR_NODATA; break;
312#endif
313#ifdef ENODEV
314  case ENODEV:       _roar_errno = ROAR_ERROR_NODEV; break;
315#endif
316#ifdef ENOSPC
317  case ENOSPC:       _roar_errno = ROAR_ERROR_NOSPC; break;
318#endif
319#ifdef ENOTCONN
320  case ENOTCONN:     _roar_errno = ROAR_ERROR_NOTCONN; break;
321#endif
322#ifdef EPROTONOSUPPORT
323  case EPROTONOSUPPORT: _roar_errno = ROAR_ERROR_PROTONOSUP; break;
324#endif
325#ifdef EROFS
326  case EROFS:        _roar_errno = ROAR_ERROR_RO; break;
327#endif
328#ifdef ETIMEDOUT
329  case ETIMEDOUT:    _roar_errno = ROAR_ERROR_TIMEDOUT; break;
330#endif
331#ifdef EAGAIN
332  case EAGAIN:       _roar_errno = ROAR_ERROR_AGAIN; break;
333#endif
334#ifdef ENETDOWN
335  case ENETDOWN:     _roar_errno = ROAR_ERROR_LINKDOWN; break;
336#endif
337#ifdef EINTR
338  case EINTR:        _roar_errno = ROAR_ERROR_INTERRUPTED; break;
339#endif
340#ifdef EDQUOT
341  case EDQUOT:       _roar_errno = ROAR_ERROR_QUOTA; break;
342#endif
343#ifdef ELIBBAD
344  case ELIBBAD:      _roar_errno = ROAR_ERROR_BADLIB; break;
345#endif
346#ifdef ENOMEDIUM
347  case ENOMEDIUM:    _roar_errno = ROAR_ERROR_NOMEDIUM; break;
348#endif
349#ifdef ENOTUNIQ
350  case ENOTUNIQ:     _roar_errno = ROAR_ERROR_NOTUNIQ; break;
351#endif
352#ifdef EILSEQ
353  case EILSEQ:       _roar_errno = ROAR_ERROR_ILLSEQ; break;
354#endif
355#ifdef EADDRINUSE
356  case EADDRINUSE:   _roar_errno = ROAR_ERROR_ADDRINUSE; break;
357#endif
358#ifdef ESPIPE
359  case ESPIPE:       _roar_errno = ROAR_ERROR_BADSEEK; break;
360#endif
361#ifdef ECHERNOBYL
362  case ECHERNOBYL:   _roar_errno = ROAR_ERROR_CHERNOBYL; break;
363#endif
364#ifdef ECRAY
365  case ECRAY:        _roar_errno = ROAR_ERROR_CAUSALITY; break;
366#endif
367#ifdef ENOHORSE
368  case ENOHORSE:     _roar_errno = ROAR_ERROR_NOHORSE; break;
369#endif
370#ifdef ETXTBSY
371  case ETXTBSY:      _roar_errno = ROAR_ERROR_TEXTBUSY; break;
372#endif
373#ifdef ENOTEMPTY
374  case ENOTEMPTY:    _roar_errno = ROAR_ERROR_NOTEMPTY; break;
375#endif
376#ifdef EHOSTUNREACH
377  case EHOSTUNREACH: _roar_errno = ROAR_ERROR_NODEUNREACH; break;
378#endif
379#ifdef EIDRM
380  case EIDRM:        _roar_errno = ROAR_ERROR_IDREMOVED; break;
381#endif
382#ifdef EINPROGRESS
383  case EINPROGRESS:  _roar_errno = ROAR_ERROR_INPROGRESS; break;
384#endif
385#ifdef ECHILD
386  case ECHILD:       _roar_errno = ROAR_ERROR_NOCHILD; break;
387#endif
388#ifdef ENETUNREACH
389  case ENETUNREACH:  _roar_errno = ROAR_ERROR_NETUNREACH; break;
390#endif
391#ifdef ECANCELED
392  case ECANCELED:    _roar_errno = ROAR_ERROR_CANCELED; break;
393#endif
394#ifdef EISDIR
395  case EISDIR:       _roar_errno = ROAR_ERROR_ISDIR; break;
396#endif
397#ifdef ENOTDIR
398  case ENOTDIR:      _roar_errno = ROAR_ERROR_NOTDIR; break;
399#endif
400#ifdef ENOEXEC
401  case ENOEXEC:      _roar_errno = ROAR_ERROR_BADEXEC; break;
402#endif
403#ifdef EISCONN
404  case EISCONN:      _roar_errno = ROAR_ERROR_ISCONN; break;
405#endif
406#ifdef EDEADLK
407  case EDEADLK:      _roar_errno = ROAR_ERROR_DEADLOCK; break;
408#endif
409#ifdef ECONNRESET
410  case ECONNRESET:   _roar_errno = ROAR_ERROR_CONNRST; break;
411#endif
412#ifdef EBADF
413  case EBADF:        _roar_errno = ROAR_ERROR_BADFH; break;
414#endif
415#ifdef ENOTSOCK
416  case ENOTSOCK:     _roar_errno = ROAR_ERROR_NOTSOCK; break;
417#endif
418#ifdef E2BIG
419  case E2BIG:        _roar_errno = ROAR_ERROR_TOOMANYARGS; break;
420#endif
421#ifdef EFBIG
422  case EFBIG:        _roar_errno = ROAR_ERROR_TOOLARGE; break;
423#endif
424#ifdef EDESTADDRREQ
425  case EDESTADDRREQ: _roar_errno = ROAR_ERROR_DESTADDRREQ; break;
426#endif
427#ifdef EAFNOSUPPORT
428  case EAFNOSUPPORT: _roar_errno = ROAR_ERROR_AFNOTSUP; break;
429#endif
430#ifdef ENFILE
431  case ENFILE:       _roar_errno = ROAR_ERROR_NFILE; break;
432#endif
433#ifdef ESTALE
434  case ESTALE:       _roar_errno = ROAR_ERROR_STALE; break;
435#endif
436#ifdef EXDEV
437  case EXDEV:        _roar_errno = ROAR_ERROR_XDEVLINK; break;
438#endif
439#ifdef EMLINK
440  case EMLINK:       _roar_errno = ROAR_ERROR_MLINK; break;
441#endif
442#ifdef ENONET
443  case ENONET:       _roar_errno = ROAR_ERROR_NONET; break;
444#endif
445#ifdef ENETRESET
446  case ENETRESET:    _roar_errno = ROAR_ERROR_CONNRSTNET; break;
447#endif
448#ifdef ECONNABORTED
449  case ECONNABORTED: _roar_errno = ROAR_ERROR_CONNABORTED; break;
450#endif
451  default:
452    _roar_errno = ROAR_ERROR_UNKNOWN;
453   break;
454 }
455
456 roar_err_set(_roar_errno);
457}
458
459void   roar_err_to_errno(void) {
460 int * err = roar_errno2();
461 switch (*err) {
462  case ROAR_ERROR_NONE:
463    roar_err_clear_errno();
464   break;
465#ifdef EPERM
466  case ROAR_ERROR_PERM:
467    errno = EPERM;
468   break;
469#endif
470#ifdef ENOENT
471  case ROAR_ERROR_NOENT:
472    errno = ENOENT;
473   break;
474#endif
475#ifdef EBADMSG
476  case ROAR_ERROR_BADMSG:
477    errno = EBADMSG;
478   break;
479#endif
480#ifdef EBUSY
481  case ROAR_ERROR_BUSY:
482    errno = EBUSY;
483   break;
484#endif
485#ifdef ECONNREFUSED
486  case ROAR_ERROR_CONNREFUSED:
487    errno = ECONNREFUSED;
488   break;
489#endif
490#ifdef ENOSYS
491  case ROAR_ERROR_NOSYS:
492    errno = ENOSYS;
493   break;
494#endif
495#ifdef ENOTSUP
496  case ROAR_ERROR_NOTSUP:
497    errno = ENOTSUP;
498   break;
499#endif
500#ifdef EPIPE
501  case ROAR_ERROR_PIPE:
502    errno = EPIPE;
503   break;
504#endif
505#ifdef EPROTO
506  case ROAR_ERROR_PROTO:
507    errno = EPROTO;
508   break;
509#endif
510#ifdef ERANGE
511  case ROAR_ERROR_RANGE:
512    errno = ERANGE;
513   break;
514#endif
515#ifdef EMSGSIZE
516  case ROAR_ERROR_MSGSIZE:
517    errno = EMSGSIZE;
518   break;
519#endif
520#ifdef ENOMEM
521  case ROAR_ERROR_NOMEM:
522    errno = ENOMEM;
523   break;
524#endif
525#ifdef EINVAL
526  case ROAR_ERROR_INVAL:
527    errno = EINVAL;
528   break;
529#endif
530#ifdef EALREADY
531  case ROAR_ERROR_ALREADY:
532    errno = EALREADY;
533   break;
534#endif
535#ifdef EBADRQC
536  case ROAR_ERROR_BADRQC:
537    errno = EBADRQC;
538   break;
539#endif
540#ifdef EDOM
541  case ROAR_ERROR_DOM:
542    errno = EDOM;
543   break;
544#endif
545#ifdef EEXIST
546  case ROAR_ERROR_EXIST:
547    errno = EEXIST;
548   break;
549#endif
550#ifdef EFAULT
551  case ROAR_ERROR_FAULT:
552    errno = EFAULT;
553   break;
554#endif
555#if defined(EREMOTEIO) || defined(EIO)
556  case ROAR_ERROR_RIO:
557#ifdef EREMOTEIO
558    errno = EREMOTEIO;
559#else
560    errno = EIO;
561#endif
562   break;
563#endif
564#ifdef EIO
565  case ROAR_ERROR_IO:
566  case ROAR_ERROR_HOLE:
567  case ROAR_ERROR_BADCKSUM:
568  case ROAR_ERROR_LOSTSYNC:
569  case ROAR_ERROR_NOHORSE:
570    errno = EIO;
571   break;
572#endif
573#ifdef EKEYEXPIRED
574  case ROAR_ERROR_KEYEXPIRED:
575    errno = EKEYEXPIRED;
576   break;
577#endif
578#ifdef EKEYREJECTED
579  case ROAR_ERROR_KEYREJECTED:
580    errno = EKEYREJECTED;
581   break;
582#endif
583#ifdef ELOOP
584  case ROAR_ERROR_LOOP:
585    errno = ELOOP;
586   break;
587#endif
588#ifdef EMFILE
589  case ROAR_ERROR_MFILE:
590    errno = EMFILE;
591   break;
592#endif
593#ifdef ENAMETOOLONG
594  case ROAR_ERROR_NAMETOOLONG:
595    errno = ENAMETOOLONG;
596   break;
597#endif
598#ifdef ENODATA
599  case ROAR_ERROR_NODATA:
600    errno = ENODATA;
601   break;
602#endif
603#ifdef ENODEV
604  case ROAR_ERROR_NODEV:
605  case ROAR_ERROR_NODRV:
606    errno = ENODEV;
607   break;
608#endif
609#ifdef ENOSPC
610  case ROAR_ERROR_NOSPC:
611    errno = ENOSPC;
612   break;
613#endif
614#ifdef EINVAL
615  case ROAR_ERROR_TYPEMM:
616    errno = EINVAL;
617   break;
618#endif
619#ifdef ENOSYS
620  case ROAR_ERROR_NORSYS:
621    errno = ENOSYS;
622   break;
623#endif
624#ifdef ENOTCONN
625  case ROAR_ERROR_NOTCONN:
626    errno = ENOTCONN;
627   break;
628#endif
629#ifdef EPROTONOSUPPORT
630  case ROAR_ERROR_PROTONOSUP:
631    errno = EPROTONOSUPPORT;
632   break;
633#endif
634#ifdef EROFS
635  case ROAR_ERROR_RO:
636    errno = EROFS;
637   break;
638#endif
639#ifdef ETIMEDOUT
640  case ROAR_ERROR_TIMEDOUT:
641    errno = ETIMEDOUT;
642   break;
643#endif
644#ifdef EAGAIN
645  case ROAR_ERROR_AGAIN:
646    errno = EAGAIN;
647   break;
648#endif
649#ifdef ENETDOWN
650  case ROAR_ERROR_LINKDOWN:
651    errno = ENETDOWN;
652   break;
653#endif
654#ifdef EINTR
655  case ROAR_ERROR_INTERRUPTED:
656    errno = EINTR;
657   break;
658#endif
659#ifdef EDQUOT
660  case ROAR_ERROR_QUOTA:
661    errno = EDQUOT;
662   break;
663#endif
664#ifdef ELIBBAD
665  case ROAR_ERROR_BADLIB:
666    errno = ELIBBAD;
667   break;
668#endif
669#ifdef ENOMEDIUM
670  case ROAR_ERROR_NOMEDIUM:
671    errno = ENOMEDIUM;
672   break;
673#endif
674#ifdef ENOTUNIQ
675  case ROAR_ERROR_NOTUNIQ:
676    errno = ENOTUNIQ;
677   break;
678#endif
679#ifdef EILSEQ
680  case ROAR_ERROR_ILLSEQ:
681    errno = EILSEQ;
682   break;
683#endif
684#ifdef EADDRINUSE
685  case ROAR_ERROR_ADDRINUSE:
686    errno = EADDRINUSE;
687   break;
688#endif
689#ifdef ESPIPE
690  case ROAR_ERROR_BADSEEK:
691  case ROAR_ERROR_NOSEEK:
692    errno = ESPIPE;
693   break;
694#endif
695#ifdef ECHERNOBYL
696  case ROAR_ERROR_CHERNOBYL:
697    errno = ECHERNOBYL;
698   break;
699#endif
700#ifdef ECRAY
701  case ROAR_ERROR_CAUSALITY:
702    errno = ECRAY;
703   break;
704#endif
705#ifdef ENOHORSE
706  case ROAR_ERROR_NOHORSE:
707    errno = ENOHORSE;
708   break;
709#endif
710#ifdef ETXTBSY
711  case ROAR_ERROR_TEXTBUSY:
712    errno = ETXTBSY;
713   break;
714#endif
715#ifdef ENOTEMPTY
716  case ROAR_ERROR_NOTEMPTY:
717    errno = ENOTEMPTY;
718   break;
719#endif
720#ifdef EHOSTUNREACH
721  case ROAR_ERROR_NODEUNREACH:
722    errno = EHOSTUNREACH;
723   break;
724#endif
725#ifdef EIDRM
726  case ROAR_ERROR_IDREMOVED:
727    errno = EIDRM;
728   break;
729#endif
730#ifdef EINPROGRESS
731  case ROAR_ERROR_INPROGRESS:
732    errno = EINPROGRESS;
733   break;
734#endif
735#ifdef ECHILD
736  case ROAR_ERROR_NOCHILD:
737    errno = ECHILD;
738   break;
739#endif
740#ifdef ENETUNREACH
741  case ROAR_ERROR_NETUNREACH:
742    errno = ENETUNREACH;
743   break;
744#endif
745#ifdef ECANCELED
746  case ROAR_ERROR_CANCELED:
747    errno = ECANCELED;
748   break;
749#endif
750#ifdef EISDIR
751  case ROAR_ERROR_ISDIR:
752    errno = EISDIR;
753   break;
754#endif
755#ifdef ENOTDOR
756  case ROAR_ERROR_NOTDIR:
757    errno = ENOTDIR;
758   break;
759#endif
760#ifdef ENOEXEC
761  case ROAR_ERROR_BADEXEC:
762    errno = ENOEXEC;
763   break;
764#endif
765#ifdef EISCONN
766  case ROAR_ERROR_ISCONN:
767    errno = EISCONN;
768   break;
769#endif
770#ifdef EDEADLK
771  case ROAR_ERROR_DEADLOCK:
772    errno = EDEADLK;
773   break;
774#endif
775#ifdef ECONNRESET
776  case ROAR_ERROR_CONNRST:
777    errno = ECONNRESET;
778   break;
779#endif
780#ifdef EBADF
781  case ROAR_ERROR_BADFH:
782    errno = EBADF;
783   break;
784#endif
785#ifdef ENOTSOCK
786  case ROAR_ERROR_NOTSOCK:
787    errno = ENOTSOCK;
788   break;
789#endif
790#ifdef E2BIG
791  case ROAR_ERROR_TOOMANYARGS:
792    errno = E2BIG;
793   break;
794#endif
795#ifdef EFBIG
796  case ROAR_ERROR_TOOLARGE:
797    errno = EFBIG;
798   break;
799#endif
800#ifdef EDESTADDRREQ
801  case ROAR_ERROR_DESTADDRREQ:
802    errno = EDESTADDRREQ;
803   break;
804#endif
805#ifdef EAFNOSUPPORT
806  case ROAR_ERROR_AFNOTSUP:
807    errno = EAFNOSUPPORT;
808   break;
809#endif
810// FIXME....
811#ifdef ENOPOWER
812  case ROAR_ERROR_NOPOWER:
813    errno = ENOPOWER;
814   break;
815#endif
816#ifdef EUSER
817  case ROAR_ERROR_USER:
818    errno = EUSER;
819   break;
820#endif
821
822#ifdef ENFILE
823  case ROAR_ERROR_NFILE:
824    errno = ENFILE;
825   break;
826#endif
827#ifdef ESTALE
828  case ROAR_ERROR_STALE:
829    errno = ESTALE;
830   break;
831#endif
832#ifdef EXDEV
833  case ROAR_ERROR_XDEVLINK:
834    errno = EXDEV;
835   break;
836#endif
837#ifdef EMLINK
838  case ROAR_ERROR_MLINK:
839    errno = EMLINK;
840   break;
841#endif
842#ifdef ENONET
843  case ROAR_ERROR_NONET:
844    errno = ENONET;
845   break;
846#endif
847#ifdef ENETRESET
848  case ROAR_ERROR_CONNRSTNET:
849    errno = ENETRESET;
850   break;
851#endif
852#ifdef ECONNABORTED
853  case ROAR_ERROR_CONNABORTED:
854    errno = ECONNABORTED;
855   break;
856#endif
857
858  default:
859#ifdef EINVAL
860    errno = EINVAL;
861#else
862    errno = -1; // just guess
863#endif
864   break;
865 }
866}
867
868// Resets the stored state to 'no error' state. This can be used
869// to init the state.
870int    roar_err_initstore(struct roar_error_state * state) {
871 struct roar_error_state curstate;
872
873 if ( state == NULL ) {
874  roar_err_set(ROAR_ERROR_FAULT);
875  return -1;
876 }
877
878 roar_err_store(&curstate);
879 roar_err_clear_all();
880 roar_err_store(state);
881 roar_err_restore(&curstate);
882
883 return -1;
884}
885
886// store a error state (both libroar and system)
887int    roar_err_store(struct roar_error_state * state) {
888 if ( state == NULL )
889  return ROAR_ERROR_FAULT;
890
891 memset(state, 0, sizeof(struct roar_error_state));
892
893 state->refc          = 0;
894 state->libroar_error = roar_error;
895 state->system_error  = errno;
896
897#ifdef ROAR_TARGET_WIN32
898 state->winsock_error = WSAGetLastError();
899#endif
900#ifdef ROAR_HAVE_VAR_H_ERRNO
901 state->syssock_herror = h_errno;
902#endif
903
904#ifdef __YIFF__
905 state->yiffc_error = yiffc_error;
906#endif
907
908 return ROAR_ERROR_NONE;
909}
910
911// restore error state to values at time of call to roar_err_store()
912int    roar_err_restore(struct roar_error_state * state) {
913 if ( state == NULL )
914  return ROAR_ERROR_FAULT;
915
916 roar_err_set(state->libroar_error);
917 errno = state->system_error;
918
919#ifdef ROAR_TARGET_WIN32
920 WSASetLastError(state->winsock_error);
921#endif
922#ifdef ROAR_HAVE_VAR_H_ERRNO
923 h_errno = state->syssock_herror;
924#endif
925
926#ifdef __YIFF__
927 yiffc_error = state->yiffc_error;
928#endif
929
930 return ROAR_ERROR_NONE;
931}
932
933
934// phi@ph7:roaraudio $ grep '^#define ROAR_ERROR_' error.h  | tr -d /\* | while read d c d t; do printf "  {%-23s \"%s\"},\n" $c, "$t"; done
935
936static const char * roar_error2str_ms(const int error, const char * msg) {
937 static char buf[1024] = "";
938 int num[8];
939 size_t i;
940 int _ra_err = roar_error;
941 int _sys_err = errno;
942
943 for (i = 0; i < (sizeof(num)/sizeof(*num)); i++)
944  num[i] = roar_random_uint32();
945
946 snprintf(buf, sizeof(buf), "\e[44;39;1m\e[2J\e[H"
947                            "                                   RoarAudio\n"
948                            "\n\n"
949                            "Fatal error %.4x: %s\n"
950                            "RA Error: %.4i, Sys Error: %.4i (%s)\n"
951                            "Random numbers:\n"
952                            " A: 0x%.8X B: 0x%.8X\n"
953                            " C: 0x%.8X D: 0x%.8X\n"
954                            " E: 0x%.8X F: 0x%.8X\n"
955                            " G: 0x%.8X H: 0x%.8X\n"
956                            "\n\n"
957                            "\e[0m",
958                            error, msg,
959                            _ra_err, _sys_err, strerror(_sys_err),
960                            num[0], num[1], num[2], num[3], num[4], num[5], num[6], num[7]);
961
962 return buf;
963}
964
965const char * roar_error2str(const int error) {
966 struct roar_libroar_config * config = roar_libroar_get_config();
967 const struct {
968  const int    err;
969  const char * msg;
970 } msgs[] = {
971  {ROAR_ERROR_NONE,        "No error"},
972  {ROAR_ERROR_PERM,        "Operation not permitted"},
973  {ROAR_ERROR_NOENT,       "No such object, file, directory or node"},
974  {ROAR_ERROR_BADMSG,      "Bad message"},
975  {ROAR_ERROR_BUSY,        "Device or resource busy"},
976  {ROAR_ERROR_CONNREFUSED, "Connection refused"},
977  {ROAR_ERROR_NOSYS,       "Function not implemented"},
978  {ROAR_ERROR_NOTSUP,      "Operation not supported"},
979  {ROAR_ERROR_PIPE,        "Broken pipe"},
980  {ROAR_ERROR_PROTO,       "Protocol error"},
981  {ROAR_ERROR_RANGE,       "Result too large or parameter out of range"},
982  {ROAR_ERROR_MSGSIZE,     "Message too long"},
983  {ROAR_ERROR_NOMEM,       "Not enough space"},
984  {ROAR_ERROR_INVAL,       "Invalid argument"},
985  {ROAR_ERROR_ALREADY,     "Connection already in progress"},
986  {ROAR_ERROR_BADRQC,      "Invalid request code"},
987  {ROAR_ERROR_DOM,         "Mathematics argument out of domain of function"},
988  {ROAR_ERROR_EXIST,       "File or object exists"},
989  {ROAR_ERROR_FAULT,       "Bad address"},
990  {ROAR_ERROR_IO,          "I/O-Error"},
991  {ROAR_ERROR_KEYEXPIRED,  "Key has expired"},
992  {ROAR_ERROR_KEYREJECTED, "Key was rejected by service"},
993  {ROAR_ERROR_LOOP,        "Too many recursions"},
994  {ROAR_ERROR_MFILE,       "Too many open files or objects"},
995  {ROAR_ERROR_NAMETOOLONG, "File or object name too long"},
996  {ROAR_ERROR_NODATA,      "No message is available on the read queue"},
997  {ROAR_ERROR_NODEV,       "No such device"},
998  {ROAR_ERROR_NODRV,       "No such driver"},
999  {ROAR_ERROR_NOSPC,       "No space left on device"},
1000  {ROAR_ERROR_TYPEMM,      "Type missmatch. Object of diffrent type required"},
1001  {ROAR_ERROR_NORSYS,      "Feature not implemented by remote end"},
1002  {ROAR_ERROR_NOTCONN,     "Socket or object not connected"},
1003  {ROAR_ERROR_PROTONOSUP,  "Protocol not supported"},
1004  {ROAR_ERROR_RIO,         "Remote I/O Error"},
1005  {ROAR_ERROR_RO,          "File or object is read only"},
1006  {ROAR_ERROR_TIMEDOUT,    "Connection timed out"},
1007  {ROAR_ERROR_AGAIN,       "Resource temporarily unavailable"},
1008  {ROAR_ERROR_NOISE,       "Line too noisy"},
1009  {ROAR_ERROR_LINKDOWN,    "Physical or logical link down"},
1010  {ROAR_ERROR_INTERRUPTED, "Operation was interruped"},
1011  {ROAR_ERROR_CAUSALITY,   "Causality error"},
1012  {ROAR_ERROR_QUOTA,       "Quota exceeded"},
1013  {ROAR_ERROR_BADLIB,      "Accessing a corrupted shared library"},
1014  {ROAR_ERROR_NOMEDIUM,    "No medium found"},
1015  {ROAR_ERROR_NOTUNIQ,     "Name not unique"},
1016  {ROAR_ERROR_ILLSEQ,      "Illegal byte sequence"},
1017  {ROAR_ERROR_ADDRINUSE,   "Address in use"},
1018  {ROAR_ERROR_HOLE,        "Hole in data"},
1019  {ROAR_ERROR_BADVERSION,  "Bad version"},
1020  {ROAR_ERROR_NSVERSION,   "Not supported version"},
1021  {ROAR_ERROR_BADMAGIC,    "Bad magic number"},
1022  {ROAR_ERROR_LOSTSYNC,    "Lost synchronization"},
1023  {ROAR_ERROR_BADSEEK,     "Can not seek to destination position"},
1024  {ROAR_ERROR_NOSEEK,      "Seeking not supported on resource"},
1025  {ROAR_ERROR_BADCKSUM,    "Data integrity error"},
1026  {ROAR_ERROR_NOHORSE,     "Mount failed"},
1027  {ROAR_ERROR_CHERNOBYL,   "Fatal device error"},
1028  {ROAR_ERROR_NOHUG,       "Device needs love"},
1029  {ROAR_ERROR_TEXTBUSY,    "Text file busy"},
1030  {ROAR_ERROR_NOTEMPTY,    "Directory not empty"},
1031  {ROAR_ERROR_NODEUNREACH, "Node is unreachable"},
1032  {ROAR_ERROR_IDREMOVED,   "Identifier removed"},
1033  {ROAR_ERROR_INPROGRESS,  "Operation in progress"},
1034  {ROAR_ERROR_NOCHILD,     "No child processes or object"},
1035  {ROAR_ERROR_NETUNREACH,  "Network unreachable"},
1036  {ROAR_ERROR_CANCELED,    "Operation canceled"},
1037  {ROAR_ERROR_ISDIR,       "Is a directory"},
1038  {ROAR_ERROR_NOTDIR,      "Not a directory"},
1039  {ROAR_ERROR_BADEXEC,     "Executable file format error"},
1040  {ROAR_ERROR_ISCONN,      "Socket or Object is connected"},
1041  {ROAR_ERROR_DEADLOCK,    "Resource deadlock would occur"},
1042  {ROAR_ERROR_CONNRST,     "Connection reset"},
1043  {ROAR_ERROR_BADFH,       "Bad file handle"},
1044  {ROAR_ERROR_NOTSOCK,     "Not a socket"},
1045  {ROAR_ERROR_TOOMANYARGS, "Argument list too long"},
1046  {ROAR_ERROR_TOOLARGE,    "File or Object too large"},
1047  {ROAR_ERROR_DESTADDRREQ, "Destination address required"},
1048  {ROAR_ERROR_AFNOTSUP,    "Address family not supported"},
1049  {ROAR_ERROR_NOPOWER,     "Operation can not be completed because we are low on power"},
1050  {ROAR_ERROR_USER,        "Error in front of screen"},
1051  {ROAR_ERROR_NFILE,       "Too many filesobjects open in system"},
1052  {ROAR_ERROR_STALE,       "Stale file handle or object"},
1053  {ROAR_ERROR_XDEVLINK,    "Cross-device link"},
1054  {ROAR_ERROR_MLINK,       "Too many links to file or object"},
1055  {ROAR_ERROR_NONET,       "Not connected to any network"},
1056  {ROAR_ERROR_CONNRSTNET,  "Connection reset by network"},
1057  {ROAR_ERROR_CONNABORTED, "Connection aborted"},
1058  {ROAR_ERROR_BADHOST,     "Bad host software or hardware"},
1059  {ROAR_ERROR_SWITCHPROTO, "Switch protocol"},
1060  {ROAR_ERROR_MOVEDPERM,   "Moved Permanently"},
1061  {ROAR_ERROR_MOVEDTEMP,   "Moved Temporary"},
1062  {ROAR_ERROR_USEPROXY,    "Use Proxy server"},
1063  {ROAR_ERROR_SEEOTHER,    "See other resource"},
1064  {ROAR_ERROR_GONE,        "Resource gone"},
1065  {-1, NULL}
1066 }, msgs_funny[] = {
1067//  {ROAR_ERROR_UNKNOWN,     "Unknown (maybe no) error"},
1068  {ROAR_ERROR_NONE,        "No error, huh?"},
1069  {ROAR_ERROR_PERM,        "Little kitty is not allowed to do this"},
1070  {ROAR_ERROR_NOENT,       "Mouse not found"},
1071//  {ROAR_ERROR_BADMSG,      "Bad message"},
1072  {ROAR_ERROR_BUSY,        "Another kitty is playing with this mouse"},
1073//  {ROAR_ERROR_CONNREFUSED, "Connection refused"},
1074//  {ROAR_ERROR_NOSYS,       "Function not implemented"},
1075//  {ROAR_ERROR_NOTSUP,      "Operation not supported"},
1076  {ROAR_ERROR_PIPE,        "Flood"},
1077//  {ROAR_ERROR_PROTO,       "Protocol error"},
1078//  {ROAR_ERROR_RANGE,       "Result too largegeneral out of range"},
1079//  {ROAR_ERROR_MSGSIZE,     "Message too long"},
1080//  {ROAR_ERROR_NOMEM,       "Not enough space"},
1081//  {ROAR_ERROR_INVAL,       "Invalid argument"},
1082//  {ROAR_ERROR_ALREADY,     "Connection already in progress"},
1083  {ROAR_ERROR_BADRQC,      "Stupid staff"},
1084//  {ROAR_ERROR_DOM,         "Mathematics argument out of domain of function"},
1085//  {ROAR_ERROR_EXIST,       "File or object exists"},
1086//  {ROAR_ERROR_FAULT,       "Bad address"},
1087//  {ROAR_ERROR_IO,          "IO-Error"},
1088//  {ROAR_ERROR_KEYEXPIRED,  "Key has expired"},
1089//  {ROAR_ERROR_KEYREJECTED, "Key was rejected by service"},
1090//  {ROAR_ERROR_LOOP,        "Too many recursions"},
1091//  {ROAR_ERROR_MFILE,       "Too many open files or objects"},
1092  {ROAR_ERROR_NAMETOOLONG, "Staff can not remember long names"},
1093//  {ROAR_ERROR_NODATA,      "No message is available on the read queue"},
1094  {ROAR_ERROR_NODEV,       "No such mouse"},
1095//  {ROAR_ERROR_NODRV,       "No such driver"},
1096  {ROAR_ERROR_NOSPC,       "Too many fish on desk"},
1097//  {ROAR_ERROR_TYPEMM,      "Type missmatch. Object of diffrent type required"},
1098//  {ROAR_ERROR_NORSYS,      "Feature not implemented by remote end"},
1099//  {ROAR_ERROR_NOTCONN,     "Socket or object not connected"},
1100//  {ROAR_ERROR_PROTONOSUP,  "Protocol not supported"},
1101//  {ROAR_ERROR_RIO,         "Remote IO Error"},
1102  {ROAR_ERROR_RO,          "Touching disallowed"},
1103//  {ROAR_ERROR_TIMEDOUT,    "Connection timed out"},
1104//  {ROAR_ERROR_AGAIN,       "Resource temporarily unavailable"},
1105//  {ROAR_ERROR_NOISE,       "Line too noisy"},
1106//  {ROAR_ERROR_LINKDOWN,    "Physical or logical link down"},
1107//  {ROAR_ERROR_INTERRUPTED, "Operation was interruped"},
1108//  {ROAR_ERROR_CAUSALITY,   "Causality error"},
1109//  {ROAR_ERROR_QUOTA,       "Quota exceeded"},
1110//  {ROAR_ERROR_BADLIB,      "Accessing a corrupted shared library"},
1111//  {ROAR_ERROR_NOMEDIUM,    "No medium found"},
1112//  {ROAR_ERROR_NOTUNIQ,     "Name not unique"},
1113//  {ROAR_ERROR_ILLSEQ,      "Illegal byte sequence"},
1114//  {ROAR_ERROR_ADDRINUSE,   "Address in use"},
1115  {ROAR_ERROR_HOLE,        "Hole in wall"},
1116//  {ROAR_ERROR_BADVERSION,  "Bad version"},
1117//  {ROAR_ERROR_NSVERSION,   "Not supported version"},
1118  {ROAR_ERROR_BADMAGIC,    "Magician's fault"},
1119//  {ROAR_ERROR_LOSTSYNC,    "Lost synchronization"},
1120//  {ROAR_ERROR_BADSEEK,     "Can not seek to destination position"},
1121//  {ROAR_ERROR_NOSEEK,      "Seeking not supported on resource"},
1122//  {ROAR_ERROR_BADCKSUM,    "Data integrity error"},
1123  {ROAR_ERROR_NOHORSE,     "No horse"},
1124//  {ROAR_ERROR_CHERNOBYL,   "Fatal device error"},
1125  {ROAR_ERROR_NOHUG,       "No hug"},
1126//  {ROAR_ERROR_TEXTBUSY,    "Text file busy"},
1127//  {ROAR_ERROR_NOTEMPTY,    "Directory not empty"},
1128//  {ROAR_ERROR_NODEUNREACH, "Node is unreachable"},
1129//  {ROAR_ERROR_IDREMOVED,   "Identifier removed"},
1130//  {ROAR_ERROR_INPROGRESS,  "Operation in progress"},
1131//  {ROAR_ERROR_NOCHILD,     "No child processesobject"},
1132//  {ROAR_ERROR_NETUNREACH,  "Network unreachable"},
1133//  {ROAR_ERROR_CANCELED,    "Operation canceled"},
1134//  {ROAR_ERROR_ISDIR,       "Is a directory"},
1135//  {ROAR_ERROR_NOTDIR,      "Not a directory"},
1136//  {ROAR_ERROR_BADEXEC,     "Executable file format error"},
1137//  {ROAR_ERROR_ISCONN,      "Socket/Object is connected"},
1138  {ROAR_ERROR_DEADLOCK,    "Mouse would die"},
1139//  {ROAR_ERROR_CONNRST,     "Connection reset"},
1140//  {ROAR_ERROR_BADFH,       "Bad file handle"},
1141//  {ROAR_ERROR_NOTSOCK,     "Not a socket"},
1142//  {ROAR_ERROR_TOOMANYARGS, "Argument list too long"},
1143//  {ROAR_ERROR_TOOLARGE,    "File/Object too large"},
1144//  {ROAR_ERROR_DESTADDRREQ, "Destination address required"},
1145//  {ROAR_ERROR_AFNOTSUP,    "Address family not supported"},
1146//  {ROAR_ERROR_NOPOWER,     "Operation can not be completed because we are low on power"},
1147//  {ROAR_ERROR_USER,        "Error in front of screen"},
1148//  {ROAR_ERROR_NFILE,       "Too many filesobjects open in system"},
1149//  {ROAR_ERROR_STALE,       "Stale file handle or object"},
1150  {ROAR_ERROR_XDEVLINK,    "Mice tails too short for kinking"},
1151//  {ROAR_ERROR_MLINK,       "Too many links to file or object"},
1152//  {ROAR_ERROR_NONET,       "Not connected to any network"},
1153//  {ROAR_ERROR_CONNRSTNET,  "Connection reset by network"},
1154//  {ROAR_ERROR_CONNABORTED, "Connection aborted"},
1155//  {ROAR_ERROR_BADHOST,     "Bad host software or hardware"},
1156//  {ROAR_ERROR_SWITCHPROTO, "Switch protocol"},
1157//  {ROAR_ERROR_MOVEDPERM,   "Moved Permanently"},
1158//  {ROAR_ERROR_MOVEDTEMP,   "Moved Temporary"},
1159//  {ROAR_ERROR_USEPROXY,    "Use Proxy server"},
1160//  {ROAR_ERROR_SEEOTHER,    "See other resource"},
1161//  {ROAR_ERROR_GONE,        "Resource gone"},
1162  {-1, NULL}
1163 };
1164 int i;
1165
1166 if ( config->opmode == ROAR_LIBROAR_CONFIG_OPMODE_MS ) {
1167  for (i = 0; msgs[i].msg != NULL; i++) {
1168   if ( msgs[i].err == error ) {
1169    return roar_error2str_ms(error, msgs[i].msg);
1170   }
1171  }
1172  return roar_error2str_ms(error, "<<<unknown error>>>");
1173 }
1174
1175 if ( config->opmode == ROAR_LIBROAR_CONFIG_OPMODE_FUNNY )
1176  for (i = 0; msgs_funny[i].msg != NULL; i++)
1177   if ( msgs_funny[i].err == error )
1178    return msgs_funny[i].msg;
1179
1180 for (i = 0; msgs[i].msg != NULL; i++)
1181  if ( msgs[i].err == error )
1182   return msgs[i].msg;
1183
1184 return NULL;
1185}
1186
1187//ll
Note: See TracBrowser for help on using the repository browser.