summaryrefslogtreecommitdiffstats
path: root/src/kash/shinstance.h
blob: f181f3367b0996d669b610bf90af753c7a04d08d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
/* $Id: shinstance.h 3480 2020-09-21 11:20:56Z bird $ */
/** @file
 * The shell instance and it's methods.
 */

/*
 * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
 *
 *
 * This file is part of kBuild.
 *
 * kBuild is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * kBuild is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with kBuild; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef ___shinstance_h
#define ___shinstance_h

#include <stdio.h> /* BUFSIZ */
#include <signal.h> /* NSIG */
#ifndef _MSC_VER
# include <termios.h>
# include <sys/types.h>
# include <sys/ioctl.h>
# include <sys/resource.h>
#endif
#include <errno.h>
#ifdef _MSC_VER
# define EWOULDBLOCK    140
#endif

#include "shtypes.h"
#include "shthread.h"
#include "shfile.h"
#include "shheap.h"
#include "shell.h"
#include "output.h"
#include "options.h"

#include "expand.h"
#include "exec.h"
#include "var.h"
#include "show.h"

#ifdef _MSC_VER
# define strcasecmp stricmp
# define strncasecmp strnicmp
#endif

#ifndef SH_FORKED_MODE
extern shmtx g_sh_exec_inherit_mtx;
#endif

#ifndef SH_FORKED_MODE
/**
 * Subshell status.
 */
typedef struct shsubshellstatus
{
    unsigned volatile   refs;           /**< Reference counter. */
    int volatile        status;         /**< The exit code. */
    KBOOL volatile      done;           /**< Set if done (valid exit code). */
    void               *towaiton;       /**< Event semaphore / whatever to wait on. */
# if K_OS == K_OS_WINDOWS
    uintptr_t volatile  hThread;        /**< The thread handle (child closes this). */
# endif
    struct shsubshellstatus *next;      /**< Next free one on the free chain. */
} shsubshellstatus;
#else
struct shsubshellstatus;
#endif

/**
 * A child process.
 */
typedef struct shchild
{
    shpid               pid;            /**< The pid. */
#if K_OS == K_OS_WINDOWS
    void               *hChild;         /**< The handle to wait on. */
#endif
#ifndef SH_FORKED_MODE
    shsubshellstatus   *subshellstatus; /**< Pointer to the subshell status structure.  NULL if child process. */
#endif
} shchild;

/* memalloc.c */
#define MINSIZE 504		/* minimum size of a block */
struct stack_block {
	struct stack_block *prev;
	char space[MINSIZE];
};

#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
/** Parser stack allocator block.
 * These are reference counted so they can be shared between the parent and
 * child shells.  They are also using as an alternative to copying function
 * definitions, here the final goal is to automatically emit separate
 * pstack_blocks for function while parsing to make it more flexible. */
typedef struct pstack_block {
    /** Pointer to the next unallocated byte (= stacknxt). */
    char               *nextbyte;
    /** Number of bytes available in the current stack block (= stacknleft). */
    size_t              avail;
    /* Number of chars left for string data (PSTPUTC, PSTUPUTC, et al) (= sstrnleft). */
    size_t              strleft;
    /** Top of the allocation stack (nextbyte points within this). */
    struct stack_block *top;
    /** Size of the top stack element (user space only). */
    size_t              topsize;
    /** @name statistics
     * @{ */
    size_t              allocations;
    size_t              bytesalloced;
    size_t              nodesalloced;
    size_t              entriesalloced;
    size_t              strbytesalloced;
    size_t              blocks;
    size_t              fragmentation;
    /** @} */
    /** Reference counter. */
    unsigned volatile   refs;
    /** Whether to make it current when is restored to the top of the stack. */
    KBOOL               done;
    /** The first stack block. */
    struct stack_block  first;
} pstack_block;
#endif

/* input.c */
struct strpush {
	struct strpush *prev;	/* preceding string on stack */
	char *prevstring;
	int prevnleft;
	int prevlleft;
	struct alias *ap;	/* if push was associated with an alias */
};

/*
 * The parsefile structure pointed to by the global variable parsefile
 * contains information about the current file being read.
 */
struct parsefile {
	struct parsefile *prev;	/* preceding file on stack */
	int linno;		/* current line */
	int fd;			/* file descriptor (or -1 if string) */
	int nleft;		/* number of chars left in this line */
	int lleft;		/* number of chars left in this buffer */
	char *nextc;		/* next char in buffer */
	char *buf;		/* input buffer */
	struct strpush *strpush; /* for pushing strings at this level */
	struct strpush basestrpush; /* so pushing one is fast */
};

/* exec.c */
#define CMDTABLESIZE 31		/* should be prime */
#define ARB 1			/* actual size determined at run time */

struct tblentry {
	struct tblentry *next;	/* next entry in hash chain */
	union param param;	/* definition of builtin function */
	short cmdtype;		/* index identifying command */
	char rehash;		/* if set, cd done since entry created */
	char cmdname[ARB];	/* name of command */
};

/* expand.c */
/*
 * Structure specifying which parts of the string should be searched
 * for IFS characters.
 */
struct ifsregion {
	struct ifsregion *next;	/* next region in list */
	int begoff;		/* offset of start of region */
	int endoff;		/* offset of end of region */
	int inquotes;		/* search for nul bytes only */
};

/* redir.c */
struct redirtab {
	struct redirtab *next;
	short renamed[10];
};

/**
 * This is a replacement for temporary node field nfile.expfname.
 * Uses stack allocator, created by expredir(), duplicated by
 * subshellinitredir() and popped (but not freed) by expredircleanup().
 */
typedef struct redirexpfnames
{
    struct redirexpfnames *prev;        /**< Previous record. */
    unsigned            depth;          /**< Nesting depth. */
    unsigned            count;          /**< Number of expanded filenames in the array. */
    char               *names[1];       /**< Variable size. */
} redirexpfnames;


/**
 * A shell instance.
 *
 * This is the core structure of the shell, it contains all
 * the data associated with a shell process except that it's
 * running in a thread and not a separate process.
 */
struct shinstance
{
    struct shinstance  *next;           /**< The next shell instance. */
    struct shinstance  *prev;           /**< The previous shell instance. */
    struct shinstance  *parent;         /**< The parent shell instance. */
    shpid               pid;            /**< The (fake) process id of this shell instance. */
    shtid               tid;            /**< The thread identifier of the thread for this shell. */
    shpid               pgid;           /**< Process group ID. */
    shfdtab             fdtab;          /**< The file descriptor table. */
    shsigaction_t       sigactions[NSIG]; /**< The signal actions registered with this shell instance. */
    shsigset_t          sigmask;        /**< Our signal mask. */
    char              **shenviron;      /**< The environment vector. */
    int                 linked;         /**< Set if we're still linked. */
    unsigned            num_children;   /**< Number of children in the array. */
    shchild            *children;       /**< The child array. */
#ifndef SH_FORKED_MODE
    int (*thread)(struct shinstance *, void *); /**< The thread procedure. */
    void               *threadarg;      /**< The thread argument. */
    struct jmploc      *exitjmp;        /**< Long jump target in sh_thread_wrapper for use by sh__exit. */
    shsubshellstatus   *subshellstatus; /**< Pointer to the subshell status structure (NULL if root). */
#endif

    /* alias.c */
#define ATABSIZE 39
    struct alias       *atab[ATABSIZE];
    unsigned            aliases;        /**< Number of active aliases. */

    /* cd.c */
    char               *curdir;         /**< current working directory */
    char               *prevdir;        /**< previous working directory */
    char               *cdcomppath;     /**< (stalloc) */
    int                 getpwd_first;   /**< static in getpwd. (initialized to 1!) */

    /* error.h */
    struct jmploc      *handler;
    int                 exception;
    int                 exerrno/* = 0 */; /**< Last exec error */
    int volatile        suppressint;
    int volatile        intpending;

    /* error.c */
    char                errmsg_buf[16]; /**< static in errmsg. (bss) */

    /* eval.h */
    char               *commandname;    /**< currently executing command */
    int                 exitstatus;     /**< exit status of last command */
    int                 back_exitstatus;/**< exit status of backquoted command */
    struct strlist     *cmdenviron;     /**< environment for builtin command (varlist from evalcommand()) */
    int                 funcnest;       /**< depth of function calls */
    int                 evalskip;       /**< set if we are skipping commands */
    int                 skipcount;      /**< number of levels to skip */
    int                 loopnest;       /**< current loop nesting level */
    int                 commandnamemalloc; /**< Set if commandname is malloc'ed (only subshells). */

    /* expand.c */
    char               *expdest;        /**< output of current string (stack) */
    struct nodelist    *argbackq;       /**< list of back quote expressions */
    struct ifsregion    ifsfirst;       /**< first struct in list of ifs regions */
    struct ifsregion   *ifslastp;       /**< last struct in list */
    struct arglist      exparg;         /**< holds expanded arg list (stack) */
    char               *expdir;         /**< Used by expandmeta. */

    /* exec.h */
    const char         *pathopt;        /**< set by padvance */

    /* exec.c */
    struct tblentry    *cmdtable[CMDTABLESIZE];
    int                 builtinloc/* = -1*/;    /**< index in path of %builtin, or -1 */

    /* input.h */
    int                 plinno/* = 1 */;/**< input line number */
    int                 parsenleft;     /**< number of characters left in input buffer */
    char               *parsenextc;     /**< next character in input buffer */
    int                 init_editline/* = 0 */;     /**< 0 == not setup, 1 == OK, -1 == failed */

    /* input.c */
    int                 parselleft;     /**< copy of parsefile->lleft */
    struct parsefile    basepf;         /**< top level input file */
    char                basebuf[BUFSIZ];/**< buffer for top level input file */
    struct parsefile   *parsefile/* = &basepf*/;    /**< current input file */
#ifndef SMALL
    EditLine           *el;             /**< cookie for editline package */
#endif

    /* jobs.h */
    shpid               backgndpid/* = -1 */;   /**< pid of last background process */
    int                 job_warning;    /**< user was warned about stopped jobs */

    /* jobs.c */
    struct job         *jobtab;         /**< array of jobs */
    int                 njobs;          /**< size of array */
    int                 jobs_invalid;   /**< set in child */
    shpid               initialpgrp;    /**< pgrp of shell on invocation */
    int                 curjob/* = -1*/;/**< current job */
    int                 ttyfd/* = -1*/;
    int                 jobctl;         /**< job control enabled / disabled */
    char               *cmdnextc;
    int                 cmdnleft;


    /* mail.c */
#define MAXMBOXES 10
    int                 nmboxes;        /**< number of mailboxes */
    time_t              mailtime[MAXMBOXES]; /**< times of mailboxes */

    /* main.h */
    shpid               rootpid;        /**< pid of main shell. */
    int                 rootshell;      /**< true if we aren't a child of the main shell. */
    struct shinstance  *psh_rootshell;  /**< The root shell pointer. (!rootshell) */

    /* memalloc.h */
    char               *stacknxt/* = stackbase.space*/;
    int                 stacknleft/* = MINSIZE*/;
    int                 sstrnleft;
    int                 herefd/* = -1 */;

    /* memalloc.c */
    struct stack_block  stackbase;
    struct stack_block *stackp/* = &stackbase*/;
    struct stackmark   *markp;

#ifdef KASH_SEPARATE_PARSER_ALLOCATOR
    pstack_block       *curpstack;      /**< The pstack entry we're currently allocating from (NULL when not in parse.c). */
    pstack_block      **pstack;         /**< Stack of parsed stuff. */
    unsigned            pstacksize;     /**< Number of entries in pstack. */
    unsigned            pstackalloced;  /**< The allocated size of pstack. */
    pstack_block       *freepstack;     /**< One cached pstack entry (lots of parsecmd calls). */
#endif

    /* myhistedit.h */
    int                 displayhist;
#ifndef SMALL
    History            *hist;
    EditLine           *el;
#endif

    /* output.h */
    struct output       output;
    struct output       errout;
    struct output       memout;
    struct output      *out1;
    struct output      *out2;

    /* output.c */
#define OUTBUFSIZ BUFSIZ
#define MEM_OUT -3                      /**< output to dynamically allocated memory */

    /* options.h */
    struct optent       optlist[NOPTS];
    char               *minusc;         /**< argument to -c option */
    char               *arg0;           /**< $0 */
    struct shparam      shellparam;     /**< $@ */
    char              **argptr;         /**< argument list for builtin commands */
    char               *optionarg;      /**< set by nextopt */
    char               *optptr;         /**< used by nextopt */
    char              **orgargv;        /**< The original argument vector (for cleanup). */
    int                 arg0malloc;     /**< Indicates whether arg0 was allocated or is part of orgargv. */

    /* parse.h */
    int                 tokpushback;
    int                 whichprompt;    /**< 1 == PS1, 2 == PS2 */

    /* parser.c */
    int                 noalias/* = 0*/;/**< when set, don't handle aliases */
    struct heredoc     *heredoclist;    /**< list of here documents to read */
    int                 parsebackquote; /**< nonzero if we are inside backquotes */
    int                 doprompt;       /**< if set, prompt the user */
    int                 needprompt;     /**< true if interactive and at start of line */
    int                 lasttoken;      /**< last token read */
    char               *wordtext;       /**< text of last word returned by readtoken */
    int                 checkkwd;       /**< 1 == check for kwds, 2 == also eat newlines */
    struct nodelist    *backquotelist;
    union node         *redirnode;
    struct heredoc     *heredoc;
    int                 quoteflag;      /**< set if (part of) last token was quoted */
    int                 startlinno;     /**< line # where last token started */

    /* redir.c */
    struct redirtab    *redirlist;
    int                 fd0_redirected/* = 0*/;
    redirexpfnames     *expfnames;      /**< Expanded filenames for current redirection setup. */

    /* show.c */
    char                tracebuf[1024];
    size_t              tracepos;
    int                 tracefd;

    /* trap.h */
    int                 pendingsigs;    /**< indicates some signal received */

    /* trap.c */
    char                gotsig[NSIG];   /**< indicates specified signal received */
    char               *trap[NSIG+1];   /**< trap handler commands */
    char                sigmode[NSIG];  /**< current value of signal */

    /* var.h */
    struct localvar    *localvars;
    struct var          vatty;
    struct var          vifs;
    struct var          vmail;
    struct var          vmpath;
    struct var          vpath;
#ifdef _MSC_VER
    struct var          vpath2;
#endif
    struct var          vps1;
    struct var          vps2;
    struct var          vps4;
#ifndef SMALL
    struct var          vterm;
    struct var          vhistsize;
#endif
    struct var          voptind;
#ifdef PC_OS2_LIBPATHS
    struct var          libpath_vars[4];
#endif
#ifdef SMALL
# define VTABSIZE 39
#else
# define VTABSIZE 517
#endif
    struct var         *vartab[VTABSIZE];

    /* builtins.h */

    /* bltin/test.c */
    char              **t_wp;
    struct t_op const  *t_wp_op;
};

extern void sh_init_globals(void);
extern shinstance *sh_create_root_shell(char **, char **);
extern shinstance *sh_create_child_shell(shinstance *);

/* environment & pwd.h */
char *sh_getenv(shinstance *, const char *);
char **sh_environ(shinstance *);
const char *sh_gethomedir(shinstance *, const char *);

/* signals */
#define SH_SIG_UNK ((shsig_t)(intptr_t)-199)
#define SH_SIG_DFL ((shsig_t)(intptr_t)SIG_DFL)
#define SH_SIG_IGN ((shsig_t)(intptr_t)SIG_IGN)
#define SH_SIG_ERR ((shsig_t)(intptr_t)SIG_ERR)
#ifdef _MSC_VER
#   define SA_RESTART       0x02
#   define SIG_BLOCK         1
#   define SIG_UNBLOCK       2
#   define SIG_SETMASK       3

#   define SIGHUP            1          /* _SIGHUP_IGNORE */
/*# define SIGINT            2 */
#   define SIGQUIT           3          /* _SIGQUIT_IGNORE */
/*# define SIGILL            4 */
/*# define SIGFPE            8 */
/*# define SIGSEGV          11 */
#   define SIGPIPE          13          /* _SIGPIPE_IGNORE */
/*# define SIGTERM          15 */
#   define SIGTTIN          16          /* _SIGIOINT_IGNORE */
#   define SIGTSTP          17          /* _SIGSTOP_IGNORE */
#   define SIGTTOU          18
#   define SIGCONT          20
/*# define SIGBREAK         21 */
/*# define SIGABRT          22 */
const char *strsignal(int iSig);
#endif /* _MSC_VER */
#ifndef HAVE_SYS_SIGNAME
extern const char * const sys_signame[NSIG];
#endif

int sh_sigaction(shinstance *, int, const struct shsigaction *, struct shsigaction *);
shsig_t sh_signal(shinstance *, int, shsig_t);
int sh_siginterrupt(shinstance *, int, int);
void sh_sigemptyset(shsigset_t *);
void sh_sigfillset(shsigset_t *);
void sh_sigaddset(shsigset_t *, int);
void sh_sigdelset(shsigset_t *, int);
int sh_sigismember(shsigset_t const *, int);
int sh_sigprocmask(shinstance *, int, shsigset_t const *, shsigset_t *);
SH_NORETURN_1 void sh_abort(shinstance *) SH_NORETURN_2;
void sh_raise_sigint(shinstance *);
int sh_kill(shinstance *, shpid, int);
int sh_killpg(shinstance *, shpid, int);

/* times */
#include <time.h>
#ifdef _MSC_VER
    typedef struct shtms
    {
        clock_t tms_utime;
        clock_t tms_stime;
        clock_t tms_cutime;
        clock_t tms_cstime;
    } shtms;
#else
#   include <sys/times.h>
    typedef struct tms shtms;
#endif
clock_t sh_times(shinstance *, shtms *);
int sh_sysconf_clk_tck(void);

/* wait / process */
int sh_add_child(shinstance *psh, shpid pid, void *hChild, struct shsubshellstatus *sts);
#ifdef _MSC_VER
#   include <process.h>
#   define WNOHANG         1       /* Don't hang in wait. */
#   define WUNTRACED       2       /* Tell about stopped, untraced children. */
#   define WCONTINUED      4       /* Report a job control continued process. */
#   define _W_INT(w)       (*(int *)&(w))  /* Convert union wait to int. */
#   define WCOREFLAG       0200
#   define _WSTATUS(x)     (_W_INT(x) & 0177)
#   define _WSTOPPED       0177            /* _WSTATUS if process is stopped */
#   define WIFSTOPPED(x)   (_WSTATUS(x) == _WSTOPPED)
#   define WSTOPSIG(x)     (_W_INT(x) >> 8)
#   define WIFSIGNALED(x)  (_WSTATUS(x) != 0 && !WIFSTOPPED(x) && !WIFCONTINUED(x)) /* bird: made GLIBC tests happy. */
#   define WTERMSIG(x)     (_WSTATUS(x))
#   define WIFEXITED(x)    (_WSTATUS(x) == 0)
#   define WEXITSTATUS(x)  (_W_INT(x) >> 8)
#   define WIFCONTINUED(x) (x == 0x13)     /* 0x13 == SIGCONT */
#   define WCOREDUMP(x)    (_W_INT(x) & WCOREFLAG)
#   define W_EXITCODE(ret, sig)    ((ret) << 8 | (sig))
#   define W_STOPCODE(sig)         ((sig) << 8 | _WSTOPPED)
#else
#   include <sys/wait.h>
#   ifdef __HAIKU__
#       define WCOREDUMP(x) WIFCORED(x)
#   endif
#endif
#ifdef SH_FORKED_MODE
shpid sh_fork(shinstance *);
#else
shpid sh_thread_start(shinstance *pshparent, shinstance *pshchild, int (*thread)(shinstance *, void *), void *arg);
#endif
shpid sh_waitpid(shinstance *, shpid, int *, int);
SH_NORETURN_1 void sh__exit(shinstance *, int) SH_NORETURN_2;
int sh_execve(shinstance *, const char *, const char * const*, const char * const *);
uid_t sh_getuid(shinstance *);
uid_t sh_geteuid(shinstance *);
gid_t sh_getgid(shinstance *);
gid_t sh_getegid(shinstance *);
shpid sh_getpid(shinstance *);
shpid sh_getpgrp(shinstance *);
shpid sh_getpgid(shinstance *, shpid);
int sh_setpgid(shinstance *, shpid, shpid);

/* tc* */
shpid sh_tcgetpgrp(shinstance *, int);
int sh_tcsetpgrp(shinstance *, int, shpid);

/* sys/resource.h */
#ifdef _MSC_VER
    typedef int64_t shrlim_t;
    typedef struct shrlimit
    {
        shrlim_t   rlim_cur;
        shrlim_t   rlim_max;
    } shrlimit;
#   define RLIMIT_CPU     0
#   define RLIMIT_FSIZE   1
#   define RLIMIT_DATA    2
#   define RLIMIT_STACK   3
#   define RLIMIT_CORE    4
#   define RLIMIT_RSS     5
#   define RLIMIT_MEMLOCK 6
#   define RLIMIT_NPROC   7
#   define RLIMIT_NOFILE  8
#   define RLIMIT_SBSIZE  9
#   define RLIMIT_VMEM    10
#   define RLIM_NLIMITS   11
#   define RLIM_INFINITY  (0x7fffffffffffffffLL)
#else
    typedef rlim_t          shrlim_t;
    typedef struct rlimit   shrlimit;
#endif
int sh_getrlimit(shinstance *, int, shrlimit *);
int sh_setrlimit(shinstance *, int, const shrlimit *);

/* string.h */
const char *sh_strerror(shinstance *, int);

#ifdef DEBUG
# define TRACE2(param)	trace param
# define TRACE2V(param)	tracev param
#else
# define TRACE2(param)  do { } while (0)
# define TRACE2V(param) do { } while (0)
#endif

#endif