Re: better run(4) fix (was: run(4): fix crash in run_task())

2015-07-12 Thread Stefan Sperling
On Sun, Jul 12, 2015 at 05:57:14PM +0200, Martin Pieuchot wrote:
   run_newstate_cb SCAN - INIT
   run_newstate_cb SCAN - SCAN
 
 How is this possible?  Why it isn't INIT - SCAN?

I'm not entirely sure.

I think one possible scenario is as follows:

 We're scanning. scan_to runs (every 200ms) and appends a state
 transition (i.e. run_newstate_cb()) for SCAN-SCAN on the cmdq
 to scan the next channel.

 Some process causes a call to run_stop() followed by run_init().
 (Note that 'ifconfig run0 mediaopt monitor up' starts a scan and
 then does IFF_UP. Somehow run_media_change runs, which does run_stop()
 followed by run_init(), but I haven't yet tracked down why -- perhaps
 to switch bands from 2GHz to 5GHz. But this seems to be an important
 ingrediant since the crash can't be trigged with 2GHz-only devices.)

 run_stop() calls timeout_del() to cancel scan_to.

 run_stop() calls ieee80211_new_state(), i.e. run_newstate(), which appends
 a state transition to INIT on the cmdq.

 run_stop() waits for run_usb_task to complete.

 usb_task_thread gets scheduled.

 run_task() runs, and executes the pending SCAN-SCAN transition first.
 This transition calls timeout_add on scan_to, effectively cancelling
 run_stop's call to timeout_del().
 After that, the SCAN-INIT transition is executed as well.

 usb_task_thread goes back to sleep.

 Now scan_to runs and puts run_newstate_cb() with for state transition
 SCAN-SCAN on the cmdq.

 run_stop() finishes up and returns.

 run_init() is called. It resets cmdq.{next,cur,queued} to zero,
 corrupting the cmdq.

 run_task() runs to execute the pending SCAN-SCAN transition.
 But cmdq is now corrupt and we crash.

If this is indeed what's happening, my diff ensures that no pending
SCAN-SCAN transition is on the cmdq before appending the transition
to INIT. However, the last SCAN-SCAN transition would still call
timeout_add for scan_to after run_stop called timeout_del. So the diff
may not be a bullet proof fix. Perhaps we should add a timeout_del
to run_newstate_cb if going back to INIT?

What do you think? Does this make any sense?
Are there other possiblities?

Perhaps we should try to find a whiteboard in calgary and draw
some diagrams ;-)



[patch] Path typo in FAQ

2015-07-12 Thread Michael McConville
Index: faq/faq15.html
===
RCS file: /cvs/www/faq/faq15.html,v
retrieving revision 1.109
diff -u -p -r1.109 faq15.html
--- faq/faq15.html  2 Jul 2015 05:49:04 -   1.109
+++ faq/faq15.html  13 Jul 2015 04:56:40 -
@@ -369,7 +369,7 @@ scaled. Below is the relevant section fr
 
 p
 Additionally, some packages provide configuration and other information
-in a file located in tt/usr/local/share/docs/pkg-readmes/tt.
+in a file located in tt/usr/local/share/doc/pkg-readmes/tt.
 
 p
 Let us now continue with an example of a package which has dependencies:
Index: faq/obsd-faq.txt
===
RCS file: /cvs/www/faq/obsd-faq.txt,v
retrieving revision 1.39
diff -u -p -r1.39 obsd-faq.txt
--- faq/obsd-faq.txt5 Jun 2015 12:04:13 -   1.39
+++ faq/obsd-faq.txt13 Jul 2015 04:56:41 -
@@ -13279,7 +13279,7 @@ the following example:
FontPath   /usr/X11R6/lib/X11/fonts/Type1/
 
 Additionally, some packages provide configuration and other information in a
-file located in /usr/local/share/docs/pkg-readmes.
+file located in /usr/local/share/doc/pkg-readmes.
 
 Let us now continue with an example of a package which has dependencies:
 



[patch] xlocale part 8: Switch _tolower_tab_ from global variable to per-thread function

2015-07-12 Thread Sebastien Marie
Same as before, but for _tolower_tab_

As _tolower_tab_ was the last initialized variable from
__install_currentrunelocale_ctype(), remove the now empty function.

-- 
Sebastien Marie

Index: b/include/ctype.h
===
--- a/include/ctype.h   2015-06-30 12:19:31.892786432 +0200
+++ b/include/ctype.h   2015-06-30 12:19:34.612825646 +0200
@@ -54,7 +54,7 @@
 __BEGIN_DECLS
 
 extern const char  *_ctype_(void);
-extern const short *_tolower_tab_;
+extern const short *_tolower_tab_(void);
 extern const short *_toupper_tab_(void);
 
 #if defined(__GNUC__) || defined(_ANSI_LIBRARY)
@@ -158,7 +158,7 @@
 {
if ((unsigned int)_c  255)
return (_c);
-   return ((_tolower_tab_ + 1)[_c]);
+   return ((_tolower_tab_() + 1)[_c]);
 }
 
 __only_inline int toupper(int _c)
Index: b/lib/libc/gen/tolower_.c
===
--- a/lib/libc/gen/tolower_.c   2015-06-30 12:00:09.503187344 +0200
+++ b/lib/libc/gen/tolower_.c   2015-06-30 12:19:34.612825646 +0200
@@ -45,13 +45,11 @@
0xf8,   0xf9,   0xfa,   0xfb,   0xfc,   0xfd,   0xfe,   0xff
 };
 
-const short *_tolower_tab_ = _C_tolower_;
-
 #undef tolower
 int
 tolower(int c)
 {
if ((unsigned int)c  255)
return(c);
-   return((_tolower_tab_ + 1)[c]);
+   return((_tolower_tab_() + 1)[c]);
 }
Index: b/lib/libc/locale/runeglue.c
===
--- a/lib/libc/locale/runeglue.c2015-06-30 12:19:31.902785988 +0200
+++ b/lib/libc/locale/runeglue.c2015-06-30 12:19:34.622824992 +0200
@@ -113,15 +113,3 @@
 
return 0;
 }
-
-void
-__install_currentrunelocale_ctype(locale_t locale)
-{
-   if (locale-lc_ctype-rl_tabs != NULL) {
-   /* LINTED const cast */
-   _tolower_tab_ = (const short *)
-   (locale-lc_ctype-rl_tabs-tolower_tab);
-   } else {
-   _tolower_tab_ = _C_tolower_;
-   }
-}
Index: b/lib/libc/locale/xlocale.c
===
--- a/lib/libc/locale/xlocale.c 2015-06-30 12:19:31.902785988 +0200
+++ b/lib/libc/locale/xlocale.c 2015-06-30 12:19:34.622824992 +0200
@@ -44,6 +44,18 @@
 
 /* exported via ctype.h */
 const short *
+_tolower_tab_()
+{
+   locale_t loc = _current_locale();
+
+   if (loc-lc_ctype-rl_tabs != NULL)
+   return (loc-lc_ctype-rl_tabs-tolower_tab);
+   else
+   return (_C_tolower_);
+}
+
+/* exported via ctype.h */
+const short *
 _toupper_tab_()
 {
locale_t loc = _current_locale();
Index: b/lib/libc/locale/rune_local.h
===
--- a/lib/libc/locale/rune_local.h  2015-06-30 12:18:53.262377426 +0200
+++ b/lib/libc/locale/rune_local.h  2015-06-30 12:19:34.622824992 +0200
@@ -43,7 +43,6 @@
 
 /* runeglue.c */
 extern int __make_ctype_tabs(_RuneLocale *);
-extern void __install_currentrunelocale_ctype(locale_t);
 
 /* ___runetype_mb.c */
 extern _RuneType ___runetype_mb(wint_t, locale_t);
Index: b/lib/libc/locale/setlocale.c
===
--- a/lib/libc/locale/setlocale.c   2015-06-30 12:18:53.262377426 +0200
+++ b/lib/libc/locale/setlocale.c   2015-06-30 12:19:34.622824992 +0200
@@ -189,7 +189,6 @@
switch (category) {
case LC_CTYPE:
(void)_xpg4_setrunelocale(C, LC_GLOBAL_LOCALE);
-   __install_currentrunelocale_ctype(LC_GLOBAL_LOCALE);
break;
case LC_MESSAGES:
case LC_COLLATE:
@@ -246,7 +245,6 @@
case LC_CTYPE:
if (_xpg4_setrunelocale(locname, LC_GLOBAL_LOCALE))
return -1;
-   __install_currentrunelocale_ctype(LC_GLOBAL_LOCALE);
break;
 
case LC_MESSAGES:



[patch] xlocale part 7: Switch _toupper_tab_ from global variable to per-thread function

2015-07-12 Thread Sebastien Marie
Same as previous, but for _toupper_tab_.
-- 
Sebastien Marie

Index: b/include/ctype.h
===
--- a/include/ctype.h   2015-06-30 12:19:07.342557440 +0200
+++ b/include/ctype.h   2015-06-30 12:19:31.892786432 +0200
@@ -55,7 +55,7 @@
 
 extern const char  *_ctype_(void);
 extern const short *_tolower_tab_;
-extern const short *_toupper_tab_;
+extern const short *_toupper_tab_(void);
 
 #if defined(__GNUC__) || defined(_ANSI_LIBRARY)
 intisalnum(int);
@@ -165,7 +165,7 @@
 {
if ((unsigned int)_c  255)
return (_c);
-   return ((_toupper_tab_ + 1)[_c]);
+   return ((_toupper_tab_() + 1)[_c]);
 }
 
 #if __BSD_VISIBLE || __ISO_C_VISIBLE = 1999 || __POSIX_VISIBLE  200112 \
Index: b/lib/libc/gen/toupper_.c
===
--- a/lib/libc/gen/toupper_.c   2015-06-30 12:00:10.023193401 +0200
+++ b/lib/libc/gen/toupper_.c   2015-06-30 12:19:31.892786432 +0200
@@ -46,13 +46,11 @@
0xf8,   0xf9,   0xfa,   0xfb,   0xfc,   0xfd,   0xfe,   0xff
 };
 
-const short *_toupper_tab_ = _C_toupper_;
-
 #undef toupper
 int
 toupper(int c)
 {
if ((unsigned int)c  255)
return(c);
-   return((_toupper_tab_ + 1)[c]);
+   return((_toupper_tab_() + 1)[c]);
 }
Index: b/lib/libc/locale/runeglue.c
===
--- a/lib/libc/locale/runeglue.c2015-06-30 12:19:07.352556508 +0200
+++ b/lib/libc/locale/runeglue.c2015-06-30 12:19:31.902785988 +0200
@@ -119,13 +119,9 @@
 {
if (locale-lc_ctype-rl_tabs != NULL) {
/* LINTED const cast */
-   _toupper_tab_ = (const short *)
-   (locale-lc_ctype-rl_tabs-toupper_tab);
-   /* LINTED const cast */
_tolower_tab_ = (const short *)
(locale-lc_ctype-rl_tabs-tolower_tab);
} else {
-   _toupper_tab_ = _C_toupper_;
_tolower_tab_ = _C_tolower_;
}
 }
Index: b/lib/libc/locale/xlocale.c
===
--- a/lib/libc/locale/xlocale.c 2015-06-30 12:19:25.942714494 +0200
+++ b/lib/libc/locale/xlocale.c 2015-06-30 12:19:31.902785988 +0200
@@ -41,3 +41,15 @@
else
return (_C_ctype_);
 }
+
+/* exported via ctype.h */
+const short *
+_toupper_tab_()
+{
+   locale_t loc = _current_locale();
+
+   if (loc-lc_ctype-rl_tabs != NULL)
+   return (loc-lc_ctype-rl_tabs-toupper_tab);
+   else
+   return (_C_toupper_);
+}



[patch] xlocale part 9: move others _Current*Locale variables to locale_t

2015-07-12 Thread Sebastien Marie
The patch integrate:
  - _CurrentMessagesLocale to locale_t (as lc_messages)
  - _CurrentMonetaryLocale to locale_t (as lc_monetary)
  - _CurrentNumericLocale to locale_t (as lc_numeric)
  - _CurrentTimeLocale to locale_t (as lc_time)

The localeconv() function has static variable that will be addressed in
following patch.

-- 
Sebastien Marie

Index: b/lib/libc/locale/_def_messages.c
===
--- a/lib/libc/locale/_def_messages.c   2015-07-08 11:38:48.371645285 +0200
+++ b/lib/libc/locale/_def_messages.c   2015-07-08 11:56:51.873920979 +0200
@@ -13,6 +13,4 @@
^[Nn],
yes,
no
-} ;
-
-const _MessagesLocale *_CurrentMessagesLocale = _DefaultMessagesLocale;
+};
Index: b/lib/libc/locale/_def_monetary.c
===
--- a/lib/libc/locale/_def_monetary.c   2015-07-08 11:38:48.371645285 +0200
+++ b/lib/libc/locale/_def_monetary.c   2015-07-08 11:56:51.873920979 +0200
@@ -34,5 +34,3 @@
CHAR_MAX,
CHAR_MAX,
 };
-
-const _MonetaryLocale *_CurrentMonetaryLocale = _DefaultMonetaryLocale;
Index: b/lib/libc/locale/_def_numeric.c
===
--- a/lib/libc/locale/_def_numeric.c2015-07-08 11:38:48.371645285 +0200
+++ b/lib/libc/locale/_def_numeric.c2015-07-08 11:56:51.873920979 +0200
@@ -13,5 +13,3 @@
,

 };
-
-const _NumericLocale *_CurrentNumericLocale = _DefaultNumericLocale;
Index: b/lib/libc/locale/_def_time.c
===
--- a/lib/libc/locale/_def_time.c   2015-07-08 11:38:48.371645285 +0200
+++ b/lib/libc/locale/_def_time.c   2015-07-08 11:56:51.883919979 +0200
@@ -32,5 +32,3 @@
%H:%M:%S,
%I:%M:%S %p
 };
-
-const _TimeLocale *_CurrentTimeLocale = _DefaultTimeLocale;
Index: b/lib/libc/locale/localeconv.c
===
--- a/lib/libc/locale/localeconv.c  2015-07-08 11:38:48.371645285 +0200
+++ b/lib/libc/locale/localeconv.c  2015-07-08 11:56:51.883919979 +0200
@@ -7,6 +7,8 @@
 #include sys/localedef.h
 #include locale.h
 
+#include xlocale_private.h
+
 /*
  * The localeconv() function constructs a struct lconv from the current
  * monetary and numeric locales.
@@ -26,38 +28,39 @@
 localeconv(void)
 {
 static struct lconv ret;
+locale_t loc = _current_locale();
 
 if (__mlocale_changed) {
/* LC_MONETARY */
-   ret.int_curr_symbol = _CurrentMonetaryLocale-int_curr_symbol;
-   ret.currency_symbol = _CurrentMonetaryLocale-currency_symbol;
-   ret.mon_decimal_point   = _CurrentMonetaryLocale-mon_decimal_point;
-   ret.mon_thousands_sep   = _CurrentMonetaryLocale-mon_thousands_sep;
-   ret.mon_grouping= _CurrentMonetaryLocale-mon_grouping;
-   ret.positive_sign   = _CurrentMonetaryLocale-positive_sign;
-   ret.negative_sign   = _CurrentMonetaryLocale-negative_sign;
-   ret.int_frac_digits = _CurrentMonetaryLocale-int_frac_digits;
-   ret.frac_digits = _CurrentMonetaryLocale-frac_digits;
-   ret.p_cs_precedes   = _CurrentMonetaryLocale-p_cs_precedes;
-   ret.p_sep_by_space  = _CurrentMonetaryLocale-p_sep_by_space;
-   ret.n_cs_precedes   = _CurrentMonetaryLocale-n_cs_precedes;
-   ret.n_sep_by_space  = _CurrentMonetaryLocale-n_sep_by_space;
-   ret.p_sign_posn = _CurrentMonetaryLocale-p_sign_posn;
-   ret.n_sign_posn = _CurrentMonetaryLocale-n_sign_posn;
-   ret.int_p_cs_precedes   = _CurrentMonetaryLocale-int_p_cs_precedes;
-   ret.int_p_sep_by_space  = _CurrentMonetaryLocale-int_p_sep_by_space;
-   ret.int_n_cs_precedes   = _CurrentMonetaryLocale-int_n_cs_precedes;
-   ret.int_n_sep_by_space  = _CurrentMonetaryLocale-int_n_sep_by_space;
-   ret.int_p_sign_posn = _CurrentMonetaryLocale-int_p_sign_posn;
-   ret.int_n_sign_posn = _CurrentMonetaryLocale-int_n_sign_posn;
+   ret.int_curr_symbol = loc-lc_monetary-int_curr_symbol;
+   ret.currency_symbol = loc-lc_monetary-currency_symbol;
+   ret.mon_decimal_point   = loc-lc_monetary-mon_decimal_point;
+   ret.mon_thousands_sep   = loc-lc_monetary-mon_thousands_sep;
+   ret.mon_grouping= loc-lc_monetary-mon_grouping;
+   ret.positive_sign   = loc-lc_monetary-positive_sign;
+   ret.negative_sign   = loc-lc_monetary-negative_sign;
+   ret.int_frac_digits = loc-lc_monetary-int_frac_digits;
+   ret.frac_digits = loc-lc_monetary-frac_digits;
+   ret.p_cs_precedes   = loc-lc_monetary-p_cs_precedes;
+   ret.p_sep_by_space  = loc-lc_monetary-p_sep_by_space;
+   ret.n_cs_precedes   = loc-lc_monetary-n_cs_precedes;
+   ret.n_sep_by_space  = loc-lc_monetary-n_sep_by_space;
+   ret.p_sign_posn = loc-lc_monetary-p_sign_posn;
+   

Re: Microsoft Now OpenBSD Foundation Gold Contributor

2015-07-12 Thread Tom Smyth
Congratulatons Lads,

On your new sponsorship
It is good news for the OpenBSD usercommunity,  great for funding of
existing great initiatives or other new initiatives,

It is good news for Microsoft users if Microsoft chooses to implement great
stable software such as open SSH and Libre SSL in their own product
offerings, Microsoft users can benefit making software from the good
quality audited code that you guys produce.

I also think it is cool that Microsoft supported the foundation in such
public manner... it is cool that they recognise in some way your
contibution to computer users the world over... and it is cool that they
showed it in cash :) PS I do hope they use Open SSH in Power Shell, :) and
use Libre SSL in software that presents SSL encrytped Services ...

As a user of both Microsoft and Open BSD ( I use each in very differing
circumstances) Im pleased with the news...  best of luck to the core
developers and the guys working hard in the open BSD foundation  keep up
the great work, well done

Sorry for writing this on Tech Mailing list :/ but felt I had to reply...

-- 
Kindest regards,
Tom Smyth

Mobile: +353 87 6193172
-
PLEASE CONSIDER THE ENVIRONMENT BEFORE YOU PRINT THIS E-MAIL
This email contains information which may be confidential or privileged.
The information is intended solely for the use of the individual or entity
named above.  If you are not the intended recipient, be aware that
any disclosure, copying, distribution or use of the contents of this
information is prohibited. If you have received this electronic
transmission in error, please notify me by telephone or by electronic mail
immediately. Any opinions expressed are those of the author, not the
company's  .This email does not constitute either offer or acceptance of
any contractually binding agreement. Such offer or acceptance must be
communicated in
writing. You are requested to carry out your own virus check before opening
any attachment. Thomas Smyth accepts no liability for any loss or damage
which may be caused by malicious software or attachments.


[patch] xlocale part 6: Switch _ctype_ from global variable to per-thread function

2015-07-12 Thread Sebastien Marie
_ctype_ is used in ctype.h header in order to define inline functions
for determining character class: isalnum(3), isalpha(3), ...

The character class comes from lc_ctype.

Switch _ctype_ from global variable to function in order to retrieve the
current locale state (global or per-thread).

-- 
Sebastien Marie

Index: b/include/ctype.h
===
--- a/include/ctype.h   2015-07-05 06:50:41.963279015 +0200
+++ b/include/ctype.h   2015-07-05 06:52:28.894297063 +0200
@@ -53,7 +53,7 @@
 
 __BEGIN_DECLS
 
-extern const char  *_ctype_;
+extern const char  *_ctype_(void);
 extern const short *_tolower_tab_;
 extern const short *_toupper_tab_;
 
@@ -90,57 +90,68 @@
 
 __only_inline int isalnum(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  (_U|_L|_N)));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  (_U|_L|_N)));
 }
 
 __only_inline int isalpha(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  (_U|_L)));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  (_U|_L)));
 }
 
 __only_inline int iscntrl(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  _C));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  _C));
 }
 
 __only_inline int isdigit(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  _N));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  _N));
 }
 
 __only_inline int isgraph(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  
(_P|_U|_L|_N)));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  (_P|_U|_L|_N)));
 }
 
 __only_inline int islower(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  _L));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  _L));
 }
 
 __only_inline int isprint(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  
(_P|_U|_L|_N|_B)));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  (_P|_U|_L|_N|_B)));
 }
 
 __only_inline int ispunct(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  _P));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  _P));
 }
 
 __only_inline int isspace(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  _S));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  _S));
 }
 
 __only_inline int isupper(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  _U));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  _U));
 }
 
 __only_inline int isxdigit(int _c)
 {
-   return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c]  (_N|_X)));
+   return (_c == -1 ?
+   0 : ((_ctype_() + 1)[(unsigned char)_c]  (_N|_X)));
 }
 
 __only_inline int tolower(int _c)
Index: b/lib/libc/gen/ctype_.c
===
--- a/lib/libc/gen/ctype_.c 2015-07-05 06:50:41.963279015 +0200
+++ b/lib/libc/gen/ctype_.c 2015-07-05 06:52:28.894297063 +0200
@@ -72,5 +72,3 @@
 0,  0,  0,  0,  0,  0,  0,  0, /* F0 */
 0,  0,  0,  0,  0,  0,  0,  0  /* F8 */
 };
-
-const char *_ctype_ = _C_ctype_;
Index: b/lib/libc/gen/isctype.c
===
--- a/lib/libc/gen/isctype.c2015-07-05 06:50:41.963279015 +0200
+++ b/lib/libc/gen/isctype.c2015-07-05 06:52:28.934295987 +0200
@@ -41,14 +41,16 @@
 int
 isalnum(int c)
 {
-   return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c]  (_U|_L|_N)));
+   return (c == EOF ?
+   0 : ((_ctype_() + 1)[(unsigned char)c]  (_U|_L|_N)));
 }
 
 #undef isalpha
 int
 isalpha(int c)
 {
-   return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c]  (_U|_L)));
+   return (c == EOF ?
+   0 : ((_ctype_() + 1)[(unsigned char)c]  (_U|_L)));
 }
 
 #undef isblank
@@ -62,63 +64,72 @@
 int
 iscntrl(int c)
 {
-   return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c]  _C));
+   return (c == EOF ?
+   0 : ((_ctype_() + 1)[(unsigned char)c]  _C));
 }
 
 #undef isdigit
 int
 isdigit(int c)
 {
-   return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c]  _N));
+   return (c == EOF ?
+   0 : ((_ctype_() + 1)[(unsigned char)c]  _N));
 }
 
 #undef isgraph
 int
 isgraph(int c)
 {
-   return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c]  
(_P|_U|_L|_N)));
+   return (c == EOF ?
+   0 : ((_ctype_() + 1)[(unsigned char)c]  (_P|_U|_L|_N)));
 }
 
 #undef islower
 int
 islower(int c)
 {
-   return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned 

Re: tcpdump -A: really printable characters

2015-07-12 Thread Christian Weisgerber
Sebastien Marie:

  --- tcpdump.c   18 Apr 2015 18:28:38 -  1.70
  +++ tcpdump.c   11 Jul 2015 20:35:11 -
  @@ -603,8 +603,10 @@ default_print_ascii(const u_char *cp, un
  printf(\n);
  for (i = 0; i  length; i++) {
  c = cp[i];
  -   c = isprint(c) || isspace(c) ? c : '.';
  -   putchar(c);
  +   if (isprint(c) || c == '\t' || c == '\n' || c == '\r')
 
 does printing '\r' will allow overriding previously printed char on line ?

Yes.  I thought of this, but note that default_print_ascii() is
only used for -A output, not for -X, and that all human-readable
protocols (SMTP, SIP, ...), which are the ones where you might want
to use -A in the first place, have \r\n line endings.  If you need
to see the exact bytes, use -X.

-- 
Christian naddy Weisgerber  na...@mips.inka.de



[patch] xlocale part 5: Switch __mb_cur_max from global variable to per-thread function

2015-07-12 Thread Sebastien Marie
ctype.h header define MB_CUR_MAX macro to be the maximum number of bytes
in a character specified by the current locale (category LC_CTYPE).

Switch the implementation from global variable to function, in order to
get the value from the current locale state (global or per-thread).

-- 
Sebastien Marie

Index: b/include/stdlib.h
===
--- a/include/stdlib.h  2015-06-30 12:00:11.373211391 +0200
+++ b/include/stdlib.h  2015-06-30 12:18:58.142432363 +0200
@@ -92,8 +92,8 @@
 
 #defineRAND_MAX0x7fff
 
-extern size_t  __mb_cur_max;
-#defineMB_CUR_MAX  __mb_cur_max
+extern size_t __mb_cur_max(void);
+#defineMB_CUR_MAX  __mb_cur_max()
 
 #include sys/cdefs.h
 
Index: b/lib/libc/locale/__mb_cur_max.c
===
--- a/lib/libc/locale/__mb_cur_max.c2015-06-30 12:00:11.373211391 +0200
+++ b/lib/libc/locale/__mb_cur_max.c2015-06-30 12:18:58.142432363 +0200
@@ -30,6 +30,19 @@
 #include sys/types.h
 #include limits.h
 
-size_t __mb_cur_max = 1;
+#include rune.h
+#include citrus/citrus_ctype_local.h
+#include xlocale_private.h
+
 size_t __mb_len_max_runtime = MB_LEN_MAX;
 
+size_t
+__mb_cur_max()
+{
+   locale_t loc = _current_locale();
+
+   if (loc-lc_ctype-rl_citrus_ctype != NULL)
+   return (loc-lc_ctype-rl_citrus_ctype-cc_mb_cur_max);
+   else
+   return (1);
+}
Index: b/lib/libc/locale/setrunelocale.c
===
--- a/lib/libc/locale/setrunelocale.c   2015-06-30 12:18:53.262377426 +0200
+++ b/lib/libc/locale/setrunelocale.c   2015-06-30 12:18:58.152431919 +0200
@@ -207,7 +207,6 @@
 
 found:
locale-lc_ctype = rl;
-   __mb_cur_max = rl-rl_citrus_ctype-cc_mb_cur_max;
 
return 0;
 }



[patch] xlocale part 11: make loadlocale() from setlocale.c reusable

2015-07-12 Thread Sebastien Marie
Change the loadlocale() prototype to be callable with specified locale_t
parameter. It will permit to reuse the code path for uselocale(3).

The current usage (with setlocale(3)) will just pass the global locale
state to function call.
-- 
Sebastien Marie

Index: b/lib/libc/locale/setlocale.c
===
--- a/lib/libc/locale/setlocale.c   2015-07-12 16:00:44.917433274 +0200
+++ b/lib/libc/locale/setlocale.c   2015-07-12 16:18:55.314603522 +0200
@@ -60,9 +60,9 @@
 static char current_locale_string[_LC_LAST * 33];
 
 static char*currentlocale(void);
-static void revert_to_default(int);
-static int load_locale_sub(int, const char *);
-static char*loadlocale(int, const char *);
+static void revert_to_default(int, struct _locale_t *);
+static int load_locale_sub(int, const char *, struct _locale_t *);
+static char*loadlocale(int, const char *, struct _locale_t *);
 static const char *__get_locale_env(int);
 
 char *
@@ -140,11 +140,13 @@
}
 
if (category)
-   return (loadlocale(category, new_categories[category]));
+   return (loadlocale(category, new_categories[category],
+   _lc_global_locale));
 
loadlocale_success = 0;
for (i = 1; i  _LC_LAST; ++i) {
-   if (loadlocale(i, new_categories[i]) != NULL)
+   if (loadlocale(i, new_categories[i],
+   _lc_global_locale) != NULL)
loadlocale_success = 1;
}
 
@@ -184,11 +186,11 @@
 }
 
 static void
-revert_to_default(int category)
+revert_to_default(int category, struct _locale_t *locale)
 {
switch (category) {
case LC_CTYPE:
-   (void)_xpg4_setrunelocale(C, LC_GLOBAL_LOCALE);
+   (void)_xpg4_setrunelocale(C, locale);
break;
case LC_MESSAGES:
case LC_COLLATE:
@@ -229,11 +231,11 @@
 }
 
 static int
-load_locale_sub(int category, const char *locname)
+load_locale_sub(int category, const char *locname, struct _locale_t *locale)
 {
/* check for the default locales */
if (!strcmp(locname, C) || !strcmp(locname, POSIX)) {
-   revert_to_default(category);
+   revert_to_default(category, locale);
return 0;
}
 
@@ -243,7 +245,7 @@
 
switch (category) {
case LC_CTYPE:
-   if (_xpg4_setrunelocale(locname, LC_GLOBAL_LOCALE))
+   if (_xpg4_setrunelocale(locname, locale))
return -1;
break;
 
@@ -261,16 +263,16 @@
 }
 
 static char *
-loadlocale(int category, const char *locname)
+loadlocale(int category, const char *locname, struct _locale_t *locale)
 {
-   if (strcmp(locname, _lc_global_locale.categories[category]) == 0)
-   return (_lc_global_locale.categories[category]);
+   if (strcmp(locname, locale-categories[category]) == 0)
+   return (locale-categories[category]);
 
-   if (!load_locale_sub(category, locname)) {
-   (void)strlcpy(_lc_global_locale.categories[category],
+   if (!load_locale_sub(category, locname, locale)) {
+   (void)strlcpy(locale-categories[category],
locname,
-   sizeof(_lc_global_locale.categories[category]));
-   return _lc_global_locale.categories[category];
+   sizeof(locale-categories[category]));
+   return locale-categories[category];
} else {
return NULL;
}



[patch] xlocale part 10: localeconv(3)

2015-07-12 Thread Sebastien Marie
Remove the static/global variables from localeconv(3).

- store the cached values inside struct _locale_t (like FreeBSD)

- use flags (member of locale_t) to track changes in lc_monetary or
  lc_numeric. Note that currently these categories support only C
  locale, so there are no code that change them (as for
  __mlocale_changed and __nlocale_changed before).

-- 
Sebastien Marie

Index: b/lib/libc/locale/localeconv.c
===
--- a/lib/libc/locale/localeconv.c  2015-07-08 11:56:51.883919979 +0200
+++ b/lib/libc/locale/localeconv.c  2015-07-08 14:49:26.182312619 +0200
@@ -18,8 +18,13 @@
  * lconv structure are computed only when the monetary or numeric
  * locale has been changed.
  */
-int __mlocale_changed = 1;
-int __nlocale_changed = 1;
+
+/* helpers */
+#define lconvcpy_monetary(_loc, _entry) \
+   (_loc-lconv_cached._entry = _loc-lc_monetary-_entry)
+
+#define lconvcpy_numeric(_loc, _entry) \
+   (_loc-lconv_cached._entry = (char *)_loc-lc_numeric-_entry)
 
 /*
  * Return the current locale conversion.
@@ -27,42 +32,43 @@
 struct lconv *
 localeconv(void)
 {
-static struct lconv ret;
-locale_t loc = _current_locale();
+   locale_t loc = _current_locale();
 
-if (__mlocale_changed) {
/* LC_MONETARY */
-   ret.int_curr_symbol = loc-lc_monetary-int_curr_symbol;
-   ret.currency_symbol = loc-lc_monetary-currency_symbol;
-   ret.mon_decimal_point   = loc-lc_monetary-mon_decimal_point;
-   ret.mon_thousands_sep   = loc-lc_monetary-mon_thousands_sep;
-   ret.mon_grouping= loc-lc_monetary-mon_grouping;
-   ret.positive_sign   = loc-lc_monetary-positive_sign;
-   ret.negative_sign   = loc-lc_monetary-negative_sign;
-   ret.int_frac_digits = loc-lc_monetary-int_frac_digits;
-   ret.frac_digits = loc-lc_monetary-frac_digits;
-   ret.p_cs_precedes   = loc-lc_monetary-p_cs_precedes;
-   ret.p_sep_by_space  = loc-lc_monetary-p_sep_by_space;
-   ret.n_cs_precedes   = loc-lc_monetary-n_cs_precedes;
-   ret.n_sep_by_space  = loc-lc_monetary-n_sep_by_space;
-   ret.p_sign_posn = loc-lc_monetary-p_sign_posn;
-   ret.n_sign_posn = loc-lc_monetary-n_sign_posn;
-   ret.int_p_cs_precedes   = loc-lc_monetary-int_p_cs_precedes;
-   ret.int_p_sep_by_space  = loc-lc_monetary-int_p_sep_by_space;
-   ret.int_n_cs_precedes   = loc-lc_monetary-int_n_cs_precedes;
-   ret.int_n_sep_by_space  = loc-lc_monetary-int_n_sep_by_space;
-   ret.int_p_sign_posn = loc-lc_monetary-int_p_sign_posn;
-   ret.int_n_sign_posn = loc-lc_monetary-int_n_sign_posn;
-   __mlocale_changed = 0;
-}
+   if (loc-flags  XLOCALE_MONETARY_CHANGED) {
+   lconvcpy_monetary(loc, int_curr_symbol);
+   lconvcpy_monetary(loc, currency_symbol);
+   lconvcpy_monetary(loc, mon_decimal_point);
+   lconvcpy_monetary(loc, mon_thousands_sep);
+   lconvcpy_monetary(loc, mon_grouping);
+   lconvcpy_monetary(loc, positive_sign);
+   lconvcpy_monetary(loc, negative_sign);
+   lconvcpy_monetary(loc, int_frac_digits);
+   lconvcpy_monetary(loc, frac_digits);
+   lconvcpy_monetary(loc, p_cs_precedes);
+   lconvcpy_monetary(loc, p_sep_by_space);
+   lconvcpy_monetary(loc, n_cs_precedes);
+   lconvcpy_monetary(loc, n_sep_by_space);
+   lconvcpy_monetary(loc, p_sign_posn);
+   lconvcpy_monetary(loc, n_sign_posn);
+   lconvcpy_monetary(loc, int_p_cs_precedes);
+   lconvcpy_monetary(loc, int_p_sep_by_space);
+   lconvcpy_monetary(loc, int_n_cs_precedes);
+   lconvcpy_monetary(loc, int_n_sep_by_space);
+   lconvcpy_monetary(loc, int_p_sign_posn);
+   lconvcpy_monetary(loc, int_n_sign_posn);
+
+   loc-flags = ~XLOCALE_MONETARY_CHANGED;
+   }
 
-if (__nlocale_changed) {
/* LC_NUMERIC */
-   ret.decimal_point   = (char *) loc-lc_numeric-decimal_point;
-   ret.thousands_sep   = (char *) loc-lc_numeric-thousands_sep;
-   ret.grouping= (char *) loc-lc_numeric-grouping;
-   __nlocale_changed = 0;
-}
+   if (loc-flags  XLOCALE_NUMERIC_CHANGED) {
+   lconvcpy_numeric(loc, decimal_point);
+   lconvcpy_numeric(loc, thousands_sep);
+   lconvcpy_numeric(loc, grouping);
+
+   loc-flags = ~XLOCALE_NUMERIC_CHANGED;
+   }
 
-return (ret);
+   return (loc-lconv_cached);
 }
Index: b/lib/libc/locale/xlocale.c
===
--- a/lib/libc/locale/xlocale.c 2015-07-08 11:56:51.883919979 +0200
+++ b/lib/libc/locale/xlocale.c 2015-07-08 14:09:51.275324172 +0200
@@ -25,13 +25,14 @@
  * hold the global state
  */
 

Re: better run(4) fix (was: run(4): fix crash in run_task())

2015-07-12 Thread Martin Pieuchot
On 11/07/15(Sat) 15:16, Stefan Sperling wrote:
 On Sat, Jul 11, 2015 at 09:54:34AM +0200, Stefan Sperling wrote:
  While run_task() iterates through the host command queue during a scan,
  the interface may get reset via run_stop() and run_init() when switching
  bands (2GHz - 5GHz) in run_media_change().
  
  The list state gets corrupted because run_init() resets the list counters
  while run_task() is still iterating the list. run_task() will now attempt
  to call garbage or NULL callback pointers.
  
  run_newstate_cb SCAN - INIT
  run_newstate_cb SCAN - SCAN

How is this possible?  Why it isn't INIT - SCAN?

  run_newstate_cb SCAN - SCAN
  run_task ring-next=7
  run_task ring-cur=0
  run_task ring-queued=-7   -- negative nonesense
  run_task cmd=0x80651110
  run_task cmd-cb=0x0
  
  The kernel now explodes trying to call cmd-cb.
  
  This can be reproduced by running 'ifconfig run0 mediaopt monitor up'.
 
 My previous duff cured a symptom.
 I believe this new diff closes the actual race.

I'm really not found of either diffs

 State transitions can already be waiting to be scheduled while run_stop()
 is scheduling another transition trying to bring the device back to INIT.
 Each state transition happens asynchronously in a process context.
^^

I guess it happens only with USB drivers and the net80211 stack is not
suppose to work this way, right?

 So if multiple transitions are scheduled they can happen out of order.

I can think of two cases when such thing can happen: when a state
transition schedule another one or when a timeout fires.  Do you
know what happens in the run(4) case?

 When injecting a state transition from the side to force the device
 into a particular state, like run_stop() does, we need to make sure the
 net80211 stack is not concurrently trying to transition the driver for
 other purposes, such as the scanning loop.

What are the contexts of from the side and net80211 stack?

 This issue probably affects a number of other wifi drivers as well.
 If this fix is good to go I'll do a tree-wide sweep soon.

I'd like to understand what you're fix is fixing 8)  Are we chasing a
problem of ic_state not being synchronized with the reality because
some code in interrupt context scheduled a state transition or are we
forcing multiple state transitions to not interleave an INIT change?

In any case, if we want to go MP, we should have a better understanding
of these state transitions :)

 Please disregard all the other hackish patches I mailed out this morning.
 
 Index: if_run.c
 ===
 RCS file: /cvs/src/sys/dev/usb/if_run.c,v
 retrieving revision 1.109
 diff -u -p -r1.109 if_run.c
 --- if_run.c  12 Jun 2015 15:47:31 -  1.109
 +++ if_run.c  11 Jul 2015 13:00:21 -
 @@ -1751,6 +1751,11 @@ run_do_async(struct run_softc *sc, void 
   return;
  
   s = splusb();
 + if (ring-queued == RUN_HOST_CMD_RING_COUNT) {
 + splx(s);
 + printf(%s: host cmd queue overrun\n, sc-sc_dev.dv_xname);
 + return; /* XXX */
 + }
   cmd = ring-cmd[ring-cur];
   cmd-cb = cb;
   KASSERT(len = sizeof (cmd-data));
 @@ -4504,7 +4509,9 @@ run_init(struct ifnet *ifp)
   }
  
   /* init host command ring */
 - sc-cmdq.cur = sc-cmdq.next = sc-cmdq.queued = 0;
 + if (sc-cmdq.queued != 0)
 + panic(outstanding host commands queued);
 + sc-cmdq.cur = sc-cmdq.next = 0;
  
   /* init Tx rings (4 EDCAs) */
   for (qid = 0; qid  4; qid++) {
 @@ -4739,9 +4746,17 @@ run_stop(struct ifnet *ifp, int disable)
   timeout_del(sc-calib_to);
  
   s = splusb();
 +
 + /*
 +  * Wait for all queued asynchronous commands to complete
 +  * before switching to INIT state.
 +  */
 + usb_wait_task(sc-sc_udev, sc-sc_task);
 +
   ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
 - /* wait for all queued asynchronous commands to complete */
 + /* Wait for asynchronous state transition to complete. */
   usb_wait_task(sc-sc_udev, sc-sc_task);
 +
   splx(s);
  
   /* Disable Tx/Rx DMA. */
 



Re: tcpdump -A: really printable characters

2015-07-12 Thread Sebastien Marie
On Sun, Jul 12, 2015 at 01:53:54PM +0200, Christian Weisgerber wrote:
 Sebastien Marie:
 
   --- tcpdump.c 18 Apr 2015 18:28:38 -  1.70
   +++ tcpdump.c 11 Jul 2015 20:35:11 -
   @@ -603,8 +603,10 @@ default_print_ascii(const u_char *cp, un
 printf(\n);
 for (i = 0; i  length; i++) {
 c = cp[i];
   - c = isprint(c) || isspace(c) ? c : '.';
   - putchar(c);
   + if (isprint(c) || c == '\t' || c == '\n' || c == '\r')
  
  does printing '\r' will allow overriding previously printed char on line ?
 
 Yes.  I thought of this, but note that default_print_ascii() is
 only used for -A output, not for -X, and that all human-readable
 protocols (SMTP, SIP, ...), which are the ones where you might want
 to use -A in the first place, have \r\n line endings.  If you need
 to see the exact bytes, use -X.
 

It makes sens. And it is the same as the previous behaviour (\r was
already printed).

OK semarie@
-- 
Sebastien Marie



Add support for SGR parameters 39 and 49

2015-07-12 Thread Matthew Martin
Currently on the console
echo '\033[34mblue\033[39m white'
will echo both words with a blue foreground. Add support for SGR 39 and
49 that reset the fg and bg color respectively back to default.

- Matthew Martin


Index: wsemul_vt100_subr.c
===
RCS file: /cvs/src/sys/dev/wscons/wsemul_vt100_subr.c,v
retrieving revision 1.20
diff -u -p -r1.20 wsemul_vt100_subr.c
--- wsemul_vt100_subr.c 14 Mar 2015 03:38:50 -  1.20
+++ wsemul_vt100_subr.c 12 Jul 2015 17:05:41 -
@@ -576,11 +576,19 @@ wsemul_vt100_handle_csi(struct wsemul_vt
flags |= WSATTR_WSCOLORS;
fgcol = ARG(n) - 30;
break;
+   case 39:
+   /* reset fg color */
+   fgcol = WSCOL_WHITE;
+   break;
case 40: case 41: case 42: case 43:
case 44: case 45: case 46: case 47:
/* bg color */
flags |= WSATTR_WSCOLORS;
bgcol = ARG(n) - 40;
+   break;
+   case 49:
+   /* reset bg color */
+   bgcol = WSCOL_BLACK;
break;
default:
 #ifdef VT100_PRINTUNKNOWN



[patch] xlocale part 12: add xlocale functions

2015-07-12 Thread Sebastien Marie
The patch add the following functions:
  - newlocale(3)
  - duplocale(3)
  - freelocale(3)
  - uselocale(3)

Documentation is missing for now. A separate patch will be provided.

uselocale(3):
  a locale state is installed only once per-thread. If the user pass the
  same locale_t object multiple times, the object will be duplicated. It
  simplifies the sharing management (there are no sharing), and it seems
  comformant to POSIX (for me at least).

  The uselocale() function shall set the current locale for the current
  thread to the locale represented by newloc.

  The locale represented by newloc is effectively used: the duplication
  don't change the representation, that is what the user expects to be
  installed.

  But comments would be welcome !


newlocale(3):
  The function is used to create a new locale state (not installed at
  this stage), from a base (a model).

  POSIX specifies that it is unspecified if the base locale_t is
  modified or freed (and new state based on it created).

  The current implementation create a new object (malloc) at each call,
  and free the base locale. This behaviour is more simple to manage
  the case where base is in already installed state (see freelocale(3)).

  The initialisation of a new locale state is done by calling
  loadlocale() for each categories, in the same manner setlocale(3) do
  it for global state.


duplocale(3):
  The implementation is similar to newlocale(3): we call loadlocale()
  for each categories, following the categories defined in the locale to
  be duplicated.


freelocale(3):
  POSIX specifies an undefined behavior for freeing NULL (not a locale_t
  object), LC_GLOBAL_LOCALE or used locale: we discard the free for any
  of these pointers.

  The free operation is somehow special: we reset the locale value for
  each categories to C locale. Doing that, loadlocale() function will
  take care to release any resources (as when calling from
  setlocale(3)). The resulting state will be pointers to statically
  defined C categories that shouldn't be touched.

  So, after reseting, just free() the locale state is enought.

-- 
Sebastien Marie

Index: b/include/locale.h
===
--- a/include/locale.h  2015-07-12 16:18:14.994338422 +0200
+++ b/include/locale.h  2015-07-12 16:21:38.775929858 +0200
@@ -95,6 +95,20 @@
 extern struct _locale_t _lc_global_locale;
 #define LC_GLOBAL_LOCALE (_lc_global_locale)
 
+#defineLC_CTYPE_MASK   (1  0)
+#defineLC_NUMERIC_MASK (1  1)
+#defineLC_TIME_MASK(1  2)
+#defineLC_COLLATE_MASK (1  3)
+#defineLC_MONETARY_MASK(1  4)
+#defineLC_MESSAGES_MASK(1  5)
+
+#defineLC_ALL_MASK (0xff)
+
+locale_t   newlocale(int, const char *, locale_t);
+locale_t   duplocale(locale_t);
+void   freelocale(locale_t);
+locale_t   uselocale(locale_t);
+
 #endif /* __POSIX_VISIBLE = 200809 */
 __END_DECLS
 
Index: b/lib/libc/locale/xlocale.c
===
--- a/lib/libc/locale/xlocale.c 2015-07-12 16:18:14.994338422 +0200
+++ b/lib/libc/locale/xlocale.c 2015-07-12 16:21:38.775929858 +0200
@@ -80,6 +80,36 @@
 }
 
 
+struct _locale_t *
+uselocale(struct _locale_t * newloc)
+{
+   struct _locale_t * oldloc = NULL;
+
+   /* query mode */
+   if (newloc == NULL)
+   return (_current_locale());
+
+   /* reset to global locale */
+   if (newloc == _lc_global_locale)
+   newloc = NULL;
+
+   /* a locale is installed once: duplicate it */
+   if (xlocale_is_installed(newloc-flags))
+   if ((newloc = duplocale(newloc)) == NULL)
+   return (NULL);
+
+   /* install the new locale */
+   newloc-flags |= XLOCALE_INSTALLED;
+   oldloc = _set_current_locale(newloc);
+
+   /* clear install flag on old locale */
+   if (oldloc != _lc_global_locale)
+   oldloc-flags = ~XLOCALE_INSTALLED;
+
+   return (oldloc);
+}
+
+
 /* exported via ctype.h */
 const char *
 _ctype_(void)
Index: b/lib/libc/locale/setlocale.c
===
--- a/lib/libc/locale/setlocale.c   2015-07-12 16:18:55.314603522 +0200
+++ b/lib/libc/locale/setlocale.c   2015-07-12 17:46:36.429343448 +0200
@@ -32,6 +32,7 @@
  */
 
 #include sys/localedef.h
+#include errno.h
 #include locale.h
 #include limits.h
 #include paths.h
@@ -300,3 +301,110 @@
 
return env;
 }
+
+
+struct _locale_t *
+newlocale(int category_mask, const char *locale, struct _locale_t *base)
+{
+   int i, loadlocale_success;
+   struct _locale_t *newloc = NULL;
+
+   /* default value for base */
+   if (base == NULL)
+   base = _lc_global_locale;
+
+   if ((newloc = malloc(sizeof(struct _locale_t))) == NULL)
+   /* errno from malloc */
+