Changeset d3ce33fa in mainline


Ignore:
Timestamp:
2011-07-05T19:01:18Z (13 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d9eaa43
Parents:
4f86fa3
Message:

signal.h: Add some functions and implementations

Location:
uspace/lib/posix
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/signal.c

    r4f86fa3 rd3ce33fa  
    3737#include "signal.h"
    3838#include "internal/common.h"
     39#include "limits.h"
     40#include "stdlib.h"
     41#include "string.h"
     42#include "errno.h"
     43
     44#include "libc/fibril_synch.h"
     45#include "libc/task.h"
     46
     47/* Used to serialize signal handling. */
     48static FIBRIL_MUTEX_INITIALIZE(_signal_mutex);
     49
     50static posix_sigset_t _signal_mask = 0;
     51
     52#define DEFAULT_HANDLER { .sa_handler = SIG_DFL, \
     53    .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL }
     54
     55static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = {
     56        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     57        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     58        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     59        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     60        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     61        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     62        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER
     63};
     64
     65void __posix_default_signal_handler(int signo)
     66{
     67        switch (signo) {
     68        case SIGABRT:
     69                abort();
     70        case SIGQUIT:
     71                fprintf(stderr, "Quit signal raised. Exiting.");
     72                exit(EXIT_FAILURE);
     73        case SIGINT:
     74                fprintf(stderr, "Interrupt signal caught. Exiting.");
     75                exit(EXIT_FAILURE);
     76        case SIGTERM:
     77                fprintf(stderr, "Termination signal caught. Exiting.");
     78                exit(EXIT_FAILURE);
     79        case SIGSTOP:
     80                fprintf(stderr, "Stop signal caught, but unsupported. Ignoring.");
     81                break;
     82        case SIGKILL:
     83                /* This will only occur when raise or similar is called. */
     84                /* Commit suicide. */
     85                task_kill(task_get_id());
     86               
     87                /* Should not be reached. */
     88                abort();
     89        case SIGFPE:
     90        case SIGBUS:
     91        case SIGILL:
     92        case SIGSEGV:
     93                posix_psignal(signo, "Hardware exception raised by user code");
     94                abort();
     95        case SIGSYS:
     96        case SIGXCPU:
     97        case SIGXFSZ:
     98        case SIGTRAP:
     99        case SIGHUP:
     100        case SIGPIPE:
     101        case SIGPOLL:
     102        case SIGURG:
     103        case SIGTSTP:
     104        case SIGTTIN:
     105        case SIGTTOU:
     106                posix_psignal(signo, "Unsupported signal caught");
     107                abort();
     108        case SIGCHLD:
     109        case SIGUSR1:
     110        case SIGUSR2:
     111        case SIGALRM:
     112        case SIGVTALRM:
     113        case SIGPROF:
     114        case SIGCONT:
     115                /* ignored */
     116                break;
     117        }
     118}
     119
     120void __posix_hold_signal_handler(int signo)
     121{
     122        /* Nothing */
     123}
     124
     125void __posix_ignore_signal_handler(int signo)
     126{
     127        /* Nothing */
     128}
     129
     130
     131int posix_sigemptyset(posix_sigset_t *set)
     132{
     133        assert(set != NULL);
     134
     135        *set = 0;
     136        return 0;
     137}
     138
     139int posix_sigfillset(posix_sigset_t *set)
     140{
     141        assert(set != NULL);
     142
     143        *set = UINT32_MAX;
     144        return 0;
     145}
     146
     147int posix_sigaddset(posix_sigset_t *set, int signo)
     148{
     149        assert(set != NULL);
     150
     151        *set |= (1 << signo);
     152        return 0;
     153}
     154
     155int posix_sigdelset(posix_sigset_t *set, int signo)
     156{
     157        assert(set != NULL);
     158
     159        *set &= ~(1 << signo);
     160        return 0;
     161}
     162
     163int posix_sigismember(const posix_sigset_t *set, int signo)
     164{
     165        assert(set != NULL);
     166       
     167        return (*set & (1 << signo)) != 0;
     168}
     169
     170static void _sigaction_unsafe(int sig, const struct posix_sigaction *restrict act,
     171    struct posix_sigaction *restrict oact)
     172{
     173        if (oact != NULL) {
     174                memcpy(oact, &_signal_actions[sig],
     175                    sizeof(struct posix_sigaction));
     176        }
     177
     178        if (act != NULL) {
     179                memcpy(&_signal_actions[sig], act,
     180                    sizeof(struct posix_sigaction));
     181        }
     182}
     183
     184int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
     185    struct posix_sigaction *restrict oact)
     186{
     187        if (sig > _TOP_SIGNAL || (act != NULL &&
     188            (sig == SIGKILL || sig == SIGSTOP))) {
     189                errno = EINVAL;
     190                return -1;
     191        }
     192
     193        if (sig > _TOP_CATCHABLE_SIGNAL) {
     194                posix_psignal(sig,
     195                    "WARNING: registering handler for a partially"
     196                    " or fully unsupported signal. This handler may only be"
     197                    " invoked by the raise() function, which may not be what"
     198                    " the application developer intended.\nSignal name");
     199        }
     200
     201        fibril_mutex_lock(&_signal_mutex);
     202        _sigaction_unsafe(sig, act, oact);
     203        fibril_mutex_unlock(&_signal_mutex);
     204
     205        return 0;
     206}
    39207
    40208void (*posix_signal(int sig, void (*func)(int)))(int)
    41209{
    42         // TODO
    43         not_implemented();
     210        struct posix_sigaction new = {
     211                .sa_handler = func,
     212                .sa_mask = 0,
     213                .sa_flags = 0,
     214                .sa_sigaction = NULL
     215        };
     216        struct posix_sigaction old;
     217        if (posix_sigaction(sig, func == NULL ? NULL : &new, &old) == 0) {
     218                return old.sa_handler;
     219        } else {
     220                return SIG_ERR;
     221        }
     222}
     223
     224static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
     225{
     226        assert(signo >= 0 && signo <= _TOP_SIGNAL);
     227        assert(siginfo != NULL);
     228
     229        fibril_mutex_lock(&_signal_mutex);
     230
     231        struct posix_sigaction action = _signal_actions[signo];
     232
     233        if (posix_sigismember(&_signal_mask, signo) ||
     234            action.sa_handler == SIG_HOLD) {
     235                // TODO: queue signal
     236                fibril_mutex_unlock(&_signal_mutex);
     237                return -1;
     238        }
     239
     240        /* Modifying signal mask is unnecessary,
     241         * signal handling is serialized.
     242         */
     243
     244        if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) {
     245                _signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER;
     246        };
     247
     248        if (action.sa_flags & SA_SIGINFO) {
     249                assert(action.sa_sigaction != NULL);
     250                action.sa_sigaction(signo, siginfo, NULL);
     251        } else {
     252                assert(action.sa_handler != NULL);
     253                action.sa_handler(signo);
     254        }
     255
     256        fibril_mutex_unlock(&_signal_mutex);
     257
     258        return 0;
    44259}
    45260
    46261int posix_raise(int sig)
    47262{
    48         // TODO
    49         not_implemented();
    50 }
    51 
    52 int posix_kill(posix_pid_t pid, int sig)
    53 {
    54         // TODO
    55         not_implemented();
    56 }
    57 
    58 int posix_sigaddset(posix_sigset_t *set, int signo)
    59 {
    60         // TODO
    61         not_implemented();
    62 }
    63 
    64 int posix_sigemptyset(posix_sigset_t *set)
    65 {
    66         // TODO
    67         not_implemented();
     263        if (sig >= 0 && sig <= _TOP_SIGNAL) {
     264                posix_siginfo_t siginfo = {
     265                        .si_signo = sig,
     266                        .si_code = SI_USER
     267                };
     268                return _raise_sigaction(sig, &siginfo);
     269        } else {
     270                errno = EINVAL;
     271                return -1;
     272        }
     273}
     274
     275int posix_kill(posix_pid_t pid, int signo)
     276{
     277        if (pid < 1) {
     278                // TODO
     279                errno = ENOTSUP;
     280                return -1;
     281        }
     282
     283        if (pid == task_get_id()) {
     284                return posix_raise(signo);
     285        }
     286
     287        if (pid > _TOP_SIGNAL) {
     288                errno = EINVAL;
     289                return -1;
     290        }
     291
     292        switch (signo) {
     293        case SIGKILL:
     294                task_kill(pid);
     295                break;
     296        default:
     297                /* Nothing else supported yet. */
     298                errno = ENOTSUP;
     299                return -1;
     300        }
     301
     302        return 0;
     303}
     304
     305int posix_killpg(posix_pid_t pid, int sig)
     306{
     307        assert(pid > 1);
     308        return posix_kill(-pid, sig);
     309}
     310
     311void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message)
     312{
     313        assert(pinfo != NULL);
     314        posix_psignal(pinfo->si_signo, message);
     315        // TODO: print si_code
     316}
     317
     318void posix_psignal(int signum, const char *message)
     319{
     320        char *sigmsg = posix_strsignal(signum);
     321        if (message == NULL || *message == '\0') {
     322                fprintf(stderr, "%s\n", sigmsg);
     323        } else {
     324                fprintf(stderr, "%s: %s\n", message, sigmsg);
     325        }
     326}
     327
     328int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
     329    posix_sigset_t *restrict oset)
     330{
     331        fibril_mutex_lock(&_signal_mutex);
     332
     333        if (oset != NULL) {
     334                *oset = _signal_mask;
     335        }
     336        if (set != NULL) {
     337                switch (how) {
     338                case SIG_BLOCK:
     339                        _signal_mask |= *set;
     340                        break;
     341                case SIG_UNBLOCK:
     342                        _signal_mask &= ~*set;
     343                        break;
     344                case SIG_SETMASK:
     345                        _signal_mask = *set;
     346                        break;
     347                default:
     348                        fibril_mutex_unlock(&_signal_mutex);
     349                        return EINVAL;
     350                }
     351        }
     352
     353        // TODO: queued signal handling
     354
     355        fibril_mutex_unlock(&_signal_mutex);
     356
     357        return 0;
    68358}
    69359
     
    71361    posix_sigset_t *restrict oset)
    72362{
    73         // TODO
    74         not_implemented();
     363        int result = posix_thread_sigmask(how, set, oset);
     364        if (result != 0) {
     365                errno = result;
     366                return -1;
     367        }
     368        return 0;
    75369}
    76370
  • uspace/lib/posix/signal.h

    r4f86fa3 rd3ce33fa  
    3939#include "sys/types.h"
    4040
    41 /* HelenOS doesn't have signals, so calls to functions of this header
    42  * are just replaced with their respective failure return value.
    43  *
    44  * Other macros and constants are here just to satisfy the symbol resolver
    45  * and have no practical value whatsoever, until HelenOS implements some
    46  * equivalent of signals. Maybe something neat based on IPC will be devised
    47  * in the future?
    48  */
     41extern void __posix_default_signal_handler(int signo);
     42extern void __posix_hold_signal_handler(int signo);
     43extern void __posix_ignore_signal_handler(int signo);
    4944
    5045#undef SIG_DFL
    51 #define SIG_DFL ((void (*)(int)) 0)
     46#define SIG_DFL ((void (*)(int)) __posix_default_signal_handler)
    5247#undef SIG_ERR
    53 #define SIG_ERR ((void (*)(int)) 0)
     48#define SIG_ERR ((void (*)(int)) NULL)
    5449#undef SIG_HOLD
    55 #define SIG_HOLD ((void (*)(int)) 0)
     50#define SIG_HOLD ((void (*)(int)) __posix_hold_signal_handler)
    5651#undef SIG_IGN
    57 #define SIG_IGN ((void (*)(int)) 0)
     52#define SIG_IGN ((void (*)(int)) __posix_ignore_signal_handler)
    5853
    5954typedef int posix_sig_atomic_t;
    60 typedef int posix_sigset_t;
     55typedef uint32_t posix_sigset_t;
    6156typedef struct posix_mcontext {
    6257        // FIXME: should not be empty to avoid compiler warnings (-pedantic)
     
    116111/* Values of posix_sigevent::sigev_notify */
    117112#undef SIGEV_NONE
     113#undef SIGEV_SIGNAL
     114#undef SIGEV_THREAD
    118115#define SIGEV_NONE 0
    119 #undef SIGEV_SIGNAL
    120116#define SIGEV_SIGNAL 0
    121 #undef SIGEV_THREAD
    122117#define SIGEV_THREAD 0
    123118
    124119#undef SIGRT_MIN
     120#undef SIGRT_MAX
    125121#define SIGRT_MIN 0
    126 #undef SIGRT_MAX
    127122#define SIGRT_MAX 0
    128123
    129124#undef SIG_BLOCK
     125#undef SIG_UNBLOCK
     126#undef SIG_SETMASK
    130127#define SIG_BLOCK 0
    131 #undef SIG_UNBLOCK
    132 #define SIG_UNBLOCK 0
    133 #undef SIG_SETMASK
    134 #define SIG_SETMASK 0
     128#define SIG_UNBLOCK 1
     129#define SIG_SETMASK 2
    135130
    136131#undef SA_NOCLDSTOP
    137 #define SA_NOCLDSTOP 0
    138132#undef SA_ONSTACK
    139 #define SA_ONSTACK 0
    140133#undef SA_RESETHAND
    141 #define SA_RESETHAND 0
    142134#undef SA_RESTART
    143 #define SA_RESTART 0
    144135#undef SA_SIGINFO
    145 #define SA_SIGINFO 0
    146136#undef SA_NOCLDWAIT
    147 #define SA_NOCLDWAIT 0
    148137#undef SA_NODEFER
    149 #define SA_NODEFER 0
     138#define SA_NOCLDSTOP (1 << 0)
     139#define SA_ONSTACK (1 << 1)
     140#define SA_RESETHAND (1 << 2)
     141#define SA_RESTART (1 << 3)
     142#define SA_SIGINFO (1 << 4)
     143#define SA_NOCLDWAIT (1 << 5)
     144#define SA_NODEFER (1 << 6)
    150145
    151146#undef SS_ONSTACK
     147#undef SS_DISABLE
    152148#define SS_ONSTACK 0
    153 #undef SS_DISABLE
    154149#define SS_DISABLE 0
    155150
    156151#undef MINSIGSTKSZ
     152#undef SIGSTKSZ
    157153#define MINSIGSTKSZ 0
    158 #undef SIGSTKSZ
    159154#define SIGSTKSZ 0
    160155
    161156/* full POSIX set */
    162157enum {
     158        /* Termination Signals */
    163159        SIGABRT,
     160        SIGQUIT,
     161        SIGINT,
     162        SIGTERM,
     163       
     164        /* Child Signal */
     165        SIGCHLD,
     166       
     167        /* User signals */
     168        SIGUSR1,
     169        SIGUSR2,
     170
     171        /* Timer */
    164172        SIGALRM,
     173        SIGVTALRM,
     174        SIGPROF, /* obsolete */
     175
     176        _TOP_CATCHABLE_SIGNAL = SIGPROF,
     177
     178        /* Process Scheduler Interaction - not supported */
     179        SIGSTOP,
     180        SIGCONT,
     181
     182        /* Process Termination - can't be caught */
     183        SIGKILL,
     184
     185        _TOP_SENDABLE_SIGNAL = SIGKILL,
     186
     187        /* Hardware Exceptions - can't be caught or sent */
     188        SIGFPE,
    165189        SIGBUS,
    166         SIGCHLD,
    167         SIGCONT,
    168         SIGFPE,
     190        SIGILL,
     191        SIGSEGV,
     192
     193        /* Other Exceptions - not supported */
     194        SIGSYS,
     195        SIGXCPU,
     196        SIGXFSZ,
     197
     198        /* Debugging - not supported */
     199        SIGTRAP,
     200
     201        /* Communication Signals - not supported */
    169202        SIGHUP,
    170         SIGILL,
    171         SIGINT,
    172         SIGKILL,
    173203        SIGPIPE,
    174         SIGQUIT,
    175         SIGSEGV,
    176         SIGSTOP,
    177         SIGTERM,
     204        SIGPOLL, /* obsolete */
     205        SIGURG,
     206
     207        /* Terminal Signals - not supported */
    178208        SIGTSTP,
    179209        SIGTTIN,
    180210        SIGTTOU,
    181         SIGUSR1,
    182         SIGUSR2,
    183         SIGPOLL,
    184         SIGPROF,
    185         SIGSYS,
    186         SIGTRAP,
    187         SIGURG,
    188         SIGVTALRM,
    189         SIGXCPU,
    190         SIGXFSZ
    191 };
     211       
     212        _TOP_SIGNAL = SIGTTOU
     213};
     214
     215/* Values for sigaction field si_code. */
     216
     217enum {
     218        SI_USER,
     219        SI_QUEUE,
     220        SI_TIMER,
     221        SI_ASYNCIO,
     222        SI_MESGQ,
     223        ILL_ILLOPC,
     224        ILL_ILLOPN,
     225        ILL_ILLADR,
     226        ILL_ILLTRP,
     227        ILL_PRVOPC,
     228        ILL_PRVREG,
     229        ILL_COPROC,
     230        ILL_BADSTK,
     231        FPE_INTDIV,
     232        FPE_INTOVF,
     233        FPE_FLTDIV,
     234        FPE_FLTOVF,
     235        FPE_FLTUND,
     236        FPE_FLTRES,
     237        FPE_FLTINV,
     238        FPE_FLTSUB,
     239        SEGV_MAPERR,
     240        SEGV_ACCERR,
     241        BUS_ADRALN,
     242        BUS_ADRERR,
     243        BUS_OBJERR,
     244        TRAP_BRKPT,
     245        TRAP_TRACE,
     246        CLD_EXITED,
     247        CLD_KILLED,
     248        CLD_DUMPED,
     249        CLD_TRAPPED,
     250        CLD_STOPPED,
     251        CLD_CONTINUED,
     252        POLL_IN,
     253        POLL_OUT,
     254        POLL_MSG,
     255        POLL_ERR,
     256        POLL_PRI,
     257        POLL_HUP
     258};
     259
     260extern int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
     261    struct posix_sigaction *restrict oact);
    192262
    193263extern void (*posix_signal(int sig, void (*func)(int)))(int);
    194264extern int posix_raise(int sig);
    195265extern int posix_kill(posix_pid_t pid, int sig);
    196 
     266extern int posix_killpg(posix_pid_t pid, int sig);
     267
     268extern void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message);
     269extern void posix_psignal(int signum, const char *message);
     270
     271extern int posix_sigemptyset(posix_sigset_t *set);
     272extern int posix_sigfillset(posix_sigset_t *set);
    197273extern int posix_sigaddset(posix_sigset_t *set, int signo);
    198 extern int posix_sigemptyset(posix_sigset_t *set);
     274extern int posix_sigdelset(posix_sigset_t *set, int signo);
     275extern int posix_sigismember(const posix_sigset_t *set, int signo);
     276
     277extern int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
     278    posix_sigset_t *restrict oset);
    199279extern int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
    200280    posix_sigset_t *restrict oset);
     
    214294        #define raise posix_raise
    215295        #define kill posix_kill
     296        #define killpg posix_killpg
     297
     298        #define psiginfo posix_psiginfo
     299        #define psignal posix_psignal
     300
     301        #define sigemptyset posix_sigemptyset
     302        #define sigfillset posix_sigfillset
    216303        #define sigaddset posix_sigaddset
    217         #define sigemptyset posix_sigemptyset
     304        #define sigdelset posix_sigdelset
     305        #define sigismember posix_sigismember
     306
     307        #define pthread_sigmask posix_thread_sigmask
    218308        #define sigprocmask posix_sigprocmask
    219309#endif
  • uspace/lib/posix/string.c

    r4f86fa3 rd3ce33fa  
    4343#include "limits.h"
    4444#include "stdlib.h"
     45#include "signal.h"
    4546
    4647#include "libc/str_error.h"
     
    570571}
    571572
     573/**
     574 *
     575 * @param signum
     576 * @return
     577 */
     578char *posix_strsignal(int signum)
     579{
     580        static const char *const sigstrings[] = {
     581                [SIGABRT] = "SIGABRT (Process abort signal)",
     582                [SIGALRM] = "SIGALRM (Alarm clock)",
     583                [SIGBUS] = "SIGBUS (Access to an undefined portion of a memory object)",
     584                [SIGCHLD] = "SIGCHLD (Child process terminated, stopped, or continued)",
     585                [SIGCONT] = "SIGCONT (Continue executing, if stopped)",
     586                [SIGFPE] = "SIGFPE (Erroneous arithmetic operation)",
     587                [SIGHUP] = "SIGHUP (Hangup)",
     588                [SIGILL] = "SIGILL (Illegal instruction)",
     589                [SIGINT] = "SIGINT (Terminal interrupt signal)",
     590                [SIGKILL] = "SIGKILL (Kill process)",
     591                [SIGPIPE] = "SIGPIPE (Write on a pipe with no one to read it)",
     592                [SIGQUIT] = "SIGQUIT (Terminal quit signal)",
     593                [SIGSEGV] = "SIGSEGV (Invalid memory reference)",
     594                [SIGSTOP] = "SIGSTOP (Stop executing)",
     595                [SIGTERM] = "SIGTERM (Termination signal)",
     596                [SIGTSTP] = "SIGTSTP (Terminal stop signal)",
     597                [SIGTTIN] = "SIGTTIN (Background process attempting read)",
     598                [SIGTTOU] = "SIGTTOU (Background process attempting write)",
     599                [SIGUSR1] = "SIGUSR1 (User-defined signal 1)",
     600                [SIGUSR2] = "SIGUSR2 (User-defined signal 2)",
     601                [SIGPOLL] = "SIGPOLL (Pollable event)",
     602                [SIGPROF] = "SIGPROF (Profiling timer expired)",
     603                [SIGSYS] = "SIGSYS (Bad system call)",
     604                [SIGTRAP] = "SIGTRAP (Trace/breakpoint trap)",
     605                [SIGURG] = "SIGURG (High bandwidth data is available at a socket)",
     606                [SIGVTALRM] = "SIGVTALRM (Virtual timer expired)",
     607                [SIGXCPU] = "SIGXCPU (CPU time limit exceeded)",
     608                [SIGXFSZ] = "SIGXFSZ (File size limit exceeded)"
     609        };
     610
     611        if (signum <= _TOP_SIGNAL) {
     612                return (char *) sigstrings[signum];
     613        }
     614
     615        return (char *) "ERROR, Invalid signal number";
     616}
     617
    572618/** @}
    573619 */
  • uspace/lib/posix/string.h

    r4f86fa3 rd3ce33fa  
    103103extern size_t posix_strnlen(const char *s, size_t n);
    104104
     105/* Signal messages */
     106extern char *posix_strsignal(int signum);
     107
    105108/* Legacy declarations */
    106109#ifndef POSIX_STRINGS_H_
     
    143146        #define strnlen posix_strnlen
    144147
     148        #define strsignal posix_strsignal
     149
    145150        #define ffs posix_ffs
    146151        #define strcasecmp posix_strcasecmp
Note: See TracChangeset for help on using the changeset viewer.