2005-10-24 23:26:25 +08:00
|
|
|
|
/** \file builtin_ulimit.c Functions defining the ulimit builtin
|
2005-10-15 06:33:01 +08:00
|
|
|
|
|
2005-10-24 23:26:25 +08:00
|
|
|
|
Functions used for implementing the ulimit builtin.
|
2005-10-15 06:33:01 +08:00
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <wchar.h>
|
|
|
|
|
#include <wctype.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <sys/resource.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#include "util.h"
|
|
|
|
|
#include "builtin.h"
|
|
|
|
|
#include "common.h"
|
|
|
|
|
#include "wgetopt.h"
|
2006-01-04 20:51:02 +08:00
|
|
|
|
#include "translate.h"
|
2005-10-15 06:33:01 +08:00
|
|
|
|
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Struct describing a resource limit
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
struct resource_t
|
|
|
|
|
{
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Resource id
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
int resource;
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Description of resource
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
const wchar_t *desc;
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Switch used on commandline to specify resource
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
wchar_t switch_char;
|
2005-11-25 22:16:57 +08:00
|
|
|
|
/**
|
|
|
|
|
The implicit multiplier used when setting getting values
|
|
|
|
|
*/
|
|
|
|
|
int multiplier;
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Array of resource_t structs, describing all known resource types.
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
const static struct resource_t resource_arr[] =
|
|
|
|
|
{
|
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
RLIMIT_CORE, L"Maximum size of core files created", L'c', 1024
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
RLIMIT_DATA, L"Maximum size of a process’s data segment", L'd', 1024
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f', 1024
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
,
|
2005-11-24 19:13:21 +08:00
|
|
|
|
#if HAVE_RLIMIT_MEMLOCK
|
2005-10-15 06:33:01 +08:00
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l', 1024
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
,
|
2005-11-24 19:13:21 +08:00
|
|
|
|
#endif
|
|
|
|
|
#if HAVE_RLIMIT_RSS
|
2005-10-15 06:33:01 +08:00
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
RLIMIT_RSS, L"Maximum resident set size", L'm', 1024
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
,
|
2005-11-24 19:13:21 +08:00
|
|
|
|
#endif
|
2005-10-15 06:33:01 +08:00
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
RLIMIT_NOFILE, L"Maximum number of open file descriptors", L'n', 1
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
RLIMIT_STACK, L"Maximum stack size", L's', 1024
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't', 1
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
,
|
2005-11-24 19:13:21 +08:00
|
|
|
|
#if HAVE_RLIMIT_NPROC
|
2005-10-15 06:33:01 +08:00
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u', 1
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
,
|
2005-11-24 19:13:21 +08:00
|
|
|
|
#endif
|
2005-10-17 21:36:57 +08:00
|
|
|
|
#if HAVE_RLIMIT_AS
|
2005-10-15 06:33:01 +08:00
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v', 1024
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
,
|
2005-10-17 21:36:57 +08:00
|
|
|
|
#endif
|
2005-10-15 06:33:01 +08:00
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
0, 0, 0, 0
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Get the implicit multiplication factor for the specified resource limit
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
static int get_multiplier( int what )
|
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for( i=0; resource_arr[i].desc; i++ )
|
2005-10-15 06:33:01 +08:00
|
|
|
|
{
|
2005-11-25 22:16:57 +08:00
|
|
|
|
if( resource_arr[i].resource == what )
|
|
|
|
|
{
|
|
|
|
|
return resource_arr[i].multiplier;
|
|
|
|
|
}
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
2005-11-25 22:16:57 +08:00
|
|
|
|
return -1;
|
2005-10-15 06:33:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Return the value for the specified resource limit
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
static rlim_t get( int resource, int hard )
|
|
|
|
|
{
|
|
|
|
|
struct rlimit ls;
|
|
|
|
|
|
|
|
|
|
getrlimit( resource, &ls );
|
|
|
|
|
|
|
|
|
|
return hard ? ls.rlim_max:ls.rlim_cur;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Print the value of the specified resource limit
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
static void print( int resource, int hard )
|
|
|
|
|
{
|
|
|
|
|
rlim_t l = get( resource, hard );
|
|
|
|
|
|
|
|
|
|
if( l == RLIM_INFINITY )
|
|
|
|
|
sb_append( sb_out, L"unlimited\n" );
|
|
|
|
|
else
|
|
|
|
|
sb_printf( sb_out, L"%d\n", l );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Print values of all resource limits
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
static void print_all( int hard )
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int w=0;
|
|
|
|
|
|
|
|
|
|
for( i=0; resource_arr[i].desc; i++ )
|
|
|
|
|
{
|
|
|
|
|
w=maxi( w, my_wcswidth(resource_arr[i].desc));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for( i=0; resource_arr[i].desc; i++ )
|
|
|
|
|
{
|
|
|
|
|
struct rlimit ls;
|
|
|
|
|
rlim_t l;
|
|
|
|
|
getrlimit( resource_arr[i].resource, &ls );
|
|
|
|
|
l = hard ? ls.rlim_max:ls.rlim_cur;
|
|
|
|
|
|
|
|
|
|
wchar_t *unit = ((resource_arr[i].resource==RLIMIT_CPU)?L"(seconds, ":(get_multiplier(resource_arr[i].resource)==1?L"(":L"(kB, "));
|
|
|
|
|
|
|
|
|
|
sb_printf( sb_out,
|
|
|
|
|
L"%-*ls %10ls-%lc) ",
|
|
|
|
|
w,
|
|
|
|
|
resource_arr[i].desc,
|
|
|
|
|
unit,
|
|
|
|
|
resource_arr[i].switch_char);
|
|
|
|
|
|
|
|
|
|
if( l == RLIM_INFINITY )
|
|
|
|
|
sb_append( sb_out, L"unlimited\n" );
|
|
|
|
|
else
|
|
|
|
|
sb_printf( sb_out, L"%d\n", l );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Returns the description for the specified resource limit
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
static const wchar_t *get_desc( int what )
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for( i=0; resource_arr[i].desc; i++ )
|
|
|
|
|
{
|
|
|
|
|
if( resource_arr[i].resource == what )
|
|
|
|
|
{
|
|
|
|
|
return resource_arr[i].desc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return L"Not a resource";
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Set the new value of the specified resource limit
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
static int set( int resource, int hard, int soft, rlim_t value )
|
|
|
|
|
{
|
|
|
|
|
struct rlimit ls;
|
|
|
|
|
getrlimit( resource, &ls );
|
|
|
|
|
if( value != RLIM_INFINITY )
|
|
|
|
|
value *= get_multiplier( resource );
|
|
|
|
|
|
|
|
|
|
if( hard )
|
|
|
|
|
{
|
|
|
|
|
ls.rlim_max = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( soft )
|
|
|
|
|
{
|
|
|
|
|
ls.rlim_cur = value;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Do not attempt to set the soft limit higher than the hard limit
|
|
|
|
|
*/
|
|
|
|
|
if( ( value == RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY ) ||
|
|
|
|
|
( value != RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY && value > ls.rlim_max))
|
|
|
|
|
{
|
|
|
|
|
ls.rlim_cur = ls.rlim_max;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( setrlimit( resource, &ls ) )
|
|
|
|
|
{
|
|
|
|
|
if( errno == EPERM )
|
|
|
|
|
sb_printf( sb_err, L"ulimit: Permission denied when changing resource of type '%ls'\n", get_desc( resource ) );
|
|
|
|
|
else
|
|
|
|
|
builtin_wperror( L"ulimit" );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-24 23:26:25 +08:00
|
|
|
|
/**
|
|
|
|
|
Set all resource limits
|
|
|
|
|
*/
|
2005-10-15 06:33:01 +08:00
|
|
|
|
static int set_all( int hard, int soft, rlim_t value )
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int res=0;
|
|
|
|
|
|
|
|
|
|
for( i=0; resource_arr[i].desc; i++ )
|
|
|
|
|
{
|
|
|
|
|
if( set( resource_arr[i].resource, hard, soft, value ) )
|
|
|
|
|
res = 1;
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int builtin_ulimit( wchar_t ** argv )
|
|
|
|
|
{
|
|
|
|
|
int hard=0;
|
|
|
|
|
int soft=0;
|
|
|
|
|
|
|
|
|
|
int what = RLIMIT_FSIZE;
|
|
|
|
|
int report_all = 0;
|
|
|
|
|
|
|
|
|
|
int argc = builtin_count_args( argv );
|
|
|
|
|
|
|
|
|
|
woptind=0;
|
|
|
|
|
|
|
|
|
|
while( 1 )
|
|
|
|
|
{
|
|
|
|
|
const static struct woption
|
|
|
|
|
long_options[] =
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
L"all", no_argument, 0, 'a'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"hard", no_argument, 0, 'H'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"soft", no_argument, 0, 'S'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"core-size", no_argument, 0, 'c'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"data-size", no_argument, 0, 'd'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"file-size", no_argument, 0, 'f'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"lock-size", no_argument, 0, 'l'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"resident-set-size", no_argument, 0, 'm'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"file-descriptor-count", no_argument, 0, 'n'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"pipe-size", no_argument, 0, 'p'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"cpu-time", no_argument, 0, 't'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"process-count", no_argument, 0, 'u'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
L"virtual-memory-size", no_argument, 0, 'v'
|
|
|
|
|
}
|
|
|
|
|
,
|
|
|
|
|
{
|
|
|
|
|
0, 0, 0, 0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int opt_index = 0;
|
|
|
|
|
|
|
|
|
|
int opt = wgetopt_long( argc,
|
|
|
|
|
argv,
|
|
|
|
|
L"aHScdflmnptuv",
|
|
|
|
|
long_options,
|
|
|
|
|
&opt_index );
|
|
|
|
|
if( opt == -1 )
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
switch( opt )
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
if(long_options[opt_index].flag != 0)
|
|
|
|
|
break;
|
2006-01-04 20:51:02 +08:00
|
|
|
|
sb_printf( sb_err,
|
|
|
|
|
BUILTIN_ERR_UNKNOWN,
|
|
|
|
|
argv[0],
|
|
|
|
|
long_options[opt_index].name );
|
2005-10-15 06:33:01 +08:00
|
|
|
|
builtin_print_help( argv[0], sb_err );
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
case L'a':
|
|
|
|
|
report_all=1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case L'H':
|
|
|
|
|
hard=1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case L'S':
|
|
|
|
|
soft=1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case L'c':
|
|
|
|
|
what=RLIMIT_CORE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case L'd':
|
|
|
|
|
what=RLIMIT_DATA;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case L'f':
|
|
|
|
|
what=RLIMIT_FSIZE;
|
|
|
|
|
break;
|
2005-11-24 19:13:21 +08:00
|
|
|
|
#if HAVE_RLIMIT_MEMLOCK
|
2005-10-15 06:33:01 +08:00
|
|
|
|
case L'l':
|
|
|
|
|
what=RLIMIT_MEMLOCK;
|
|
|
|
|
break;
|
2005-11-24 19:13:21 +08:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if HAVE_RLIMIT_RSS
|
2005-10-15 06:33:01 +08:00
|
|
|
|
case L'm':
|
|
|
|
|
what=RLIMIT_RSS;
|
|
|
|
|
break;
|
2005-11-24 19:13:21 +08:00
|
|
|
|
#endif
|
2005-10-15 06:33:01 +08:00
|
|
|
|
|
|
|
|
|
case L'n':
|
|
|
|
|
what=RLIMIT_NOFILE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case L's':
|
|
|
|
|
what=RLIMIT_STACK;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case L't':
|
|
|
|
|
what=RLIMIT_CPU;
|
|
|
|
|
break;
|
2005-11-24 19:13:21 +08:00
|
|
|
|
|
|
|
|
|
#if HAVE_RLIMIT_NPROC
|
2005-10-15 06:33:01 +08:00
|
|
|
|
case L'u':
|
|
|
|
|
what=RLIMIT_NPROC;
|
|
|
|
|
break;
|
2005-11-24 19:13:21 +08:00
|
|
|
|
#endif
|
2005-10-15 06:33:01 +08:00
|
|
|
|
|
2005-10-17 21:36:57 +08:00
|
|
|
|
#if HAVE_RLIMIT_AS
|
2005-10-15 06:33:01 +08:00
|
|
|
|
case L'v':
|
|
|
|
|
what=RLIMIT_AS;
|
|
|
|
|
break;
|
2005-10-17 21:36:57 +08:00
|
|
|
|
#endif
|
2005-10-15 06:33:01 +08:00
|
|
|
|
|
|
|
|
|
case L'?':
|
|
|
|
|
builtin_print_help( argv[0], sb_err );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch( argc - woptind )
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
/*
|
|
|
|
|
Show current limit value
|
|
|
|
|
*/
|
|
|
|
|
if( report_all )
|
|
|
|
|
{
|
|
|
|
|
print_all( hard );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
print( what, hard );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
Change current limit value
|
|
|
|
|
*/
|
|
|
|
|
rlim_t new_limit;
|
|
|
|
|
wchar_t *end;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Set both hard and soft limits if nothing else was specified
|
|
|
|
|
*/
|
|
|
|
|
if( !(hard+soft) )
|
|
|
|
|
{
|
|
|
|
|
hard=soft=1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( wcscasecmp( argv[woptind], L"unlimited" )==0)
|
|
|
|
|
{
|
|
|
|
|
new_limit = RLIM_INFINITY;
|
|
|
|
|
}
|
|
|
|
|
else if( wcscasecmp( argv[woptind], L"hard" )==0)
|
|
|
|
|
{
|
|
|
|
|
new_limit = get( what, 1 );
|
|
|
|
|
}
|
|
|
|
|
else if( wcscasecmp( argv[woptind], L"soft" )==0)
|
|
|
|
|
{
|
|
|
|
|
new_limit = get( what, soft );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
errno=0;
|
|
|
|
|
new_limit = wcstol( argv[woptind], &end, 10 );
|
|
|
|
|
if( errno || *end )
|
|
|
|
|
{
|
|
|
|
|
sb_printf( sb_err,
|
|
|
|
|
L"%ls: Invalid limit '%ls'\n",
|
|
|
|
|
argv[0],
|
|
|
|
|
argv[woptind] );
|
|
|
|
|
builtin_print_help( argv[0], sb_err );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( report_all )
|
|
|
|
|
{
|
|
|
|
|
return set_all( hard, soft, new_limit );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return set( what, hard, soft, new_limit );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
sb_append2( sb_err,
|
|
|
|
|
argv[0],
|
|
|
|
|
L": Too many arguments\n",
|
|
|
|
|
(void *)0 );
|
|
|
|
|
builtin_print_help( argv[0], sb_err );
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|