errstr.c 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * We assume there's only one error buffer for the whole system.
  3. * If you use ffork, you need to provide a _syserrstr. Since most
  4. * people will use libthread (which provides a _syserrstr), this is
  5. * okay.
  6. */
  7. #include <u.h>
  8. #include <errno.h>
  9. #include <string.h>
  10. #include <libc.h>
  11. enum
  12. {
  13. EPLAN9 = 0x19283745
  14. };
  15. char *(*_syserrstr)(void);
  16. static char xsyserr[ERRMAX];
  17. static char*
  18. getsyserr(void)
  19. {
  20. char *s;
  21. s = nil;
  22. if(_syserrstr)
  23. s = (*_syserrstr)();
  24. if(s == nil)
  25. s = xsyserr;
  26. return s;
  27. }
  28. int
  29. errstr(char *err, uint n)
  30. {
  31. char tmp[ERRMAX];
  32. char *syserr;
  33. strecpy(tmp, tmp+ERRMAX, err);
  34. rerrstr(err, n);
  35. syserr = getsyserr();
  36. strecpy(syserr, syserr+ERRMAX, tmp);
  37. errno = EPLAN9;
  38. return 0;
  39. }
  40. void
  41. rerrstr(char *err, uint n)
  42. {
  43. char *syserr;
  44. syserr = getsyserr();
  45. if(errno == EINTR)
  46. strcpy(syserr, "interrupted");
  47. else if(errno != EPLAN9)
  48. strcpy(syserr, strerror(errno));
  49. strecpy(err, err+n, syserr);
  50. }
  51. /* replaces __errfmt in libfmt */
  52. int
  53. __errfmt(Fmt *f)
  54. {
  55. if(errno == EPLAN9)
  56. return fmtstrcpy(f, getsyserr());
  57. return fmtstrcpy(f, strerror(errno));
  58. }
  59. void
  60. werrstr(char *fmt, ...)
  61. {
  62. va_list arg;
  63. char buf[ERRMAX];
  64. va_start(arg, fmt);
  65. vseprint(buf, buf+ERRMAX, fmt, arg);
  66. va_end(arg);
  67. errstr(buf, ERRMAX);
  68. }