mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-07 11:35:15 +08:00
Implement the ulimit builtin
darcs-hash:20051014223301-ac50b-f4e6303dcfbe26318e23020444b54d80fed9f535.gz
This commit is contained in:
parent
0ebf6db4b9
commit
638df31ca4
|
@ -58,7 +58,7 @@ COMMON_OBJS := function.o builtin.o common.o complete.o env.o exec.o \
|
||||||
COMMON_OBJS_WITH_HEADER := builtin_help.o
|
COMMON_OBJS_WITH_HEADER := builtin_help.o
|
||||||
|
|
||||||
# main.c exists, but main.h does not, etc.
|
# main.c exists, but main.h does not, etc.
|
||||||
COMMON_OBJS_WITH_CODE := builtin_set.o builtin_commandline.o
|
COMMON_OBJS_WITH_CODE := builtin_set.o builtin_commandline.o builtin_ulimit.c
|
||||||
|
|
||||||
# All objects that the system needs to build fish
|
# All objects that the system needs to build fish
|
||||||
FISH_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) $(COMMON_OBJS_WITH_HEADER) main.o
|
FISH_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) $(COMMON_OBJS_WITH_HEADER) main.o
|
||||||
|
@ -87,7 +87,8 @@ BUILTIN_DOC_SRC := doc_src/source.txt doc_src/and.txt \
|
||||||
doc_src/functions.txt doc_src/if.txt doc_src/jobs.txt \
|
doc_src/functions.txt doc_src/if.txt doc_src/jobs.txt \
|
||||||
doc_src/not.txt doc_src/or.txt doc_src/random.txt \
|
doc_src/not.txt doc_src/or.txt doc_src/random.txt \
|
||||||
doc_src/return.txt doc_src/read.txt doc_src/set.txt \
|
doc_src/return.txt doc_src/read.txt doc_src/set.txt \
|
||||||
doc_src/status.txt doc_src/switch.txt doc_src/while.txt
|
doc_src/status.txt doc_src/switch.txt doc_src/ulimit.txt \
|
||||||
|
doc_src/while.txt
|
||||||
|
|
||||||
#
|
#
|
||||||
# Files generated by running doxygen on the files in $(BUILTIN_DOC_SRC)
|
# Files generated by running doxygen on the files in $(BUILTIN_DOC_SRC)
|
||||||
|
|
11
builtin.c
11
builtin.c
|
@ -108,12 +108,8 @@ int builtin_count_args( wchar_t **argv )
|
||||||
return argc;
|
return argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
This function works like wperror, but it prints its result into
|
void builtin_wperror( const wchar_t *s)
|
||||||
the sb_err string_buffer_t instead of to stderr. Used by the builtin
|
|
||||||
commands.
|
|
||||||
*/
|
|
||||||
static void builtin_wperror( const wchar_t *s)
|
|
||||||
{
|
{
|
||||||
if( s != 0 )
|
if( s != 0 )
|
||||||
{
|
{
|
||||||
|
@ -2797,6 +2793,7 @@ void builtin_init()
|
||||||
hash_put( &builtin, L"bind", (void*) &builtin_bind );
|
hash_put( &builtin, L"bind", (void*) &builtin_bind );
|
||||||
hash_put( &builtin, L"random", (void*) &builtin_random );
|
hash_put( &builtin, L"random", (void*) &builtin_random );
|
||||||
hash_put( &builtin, L"status", (void*) &builtin_status );
|
hash_put( &builtin, L"status", (void*) &builtin_status );
|
||||||
|
hash_put( &builtin, L"ulimit", (void*) &builtin_ulimit );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Builtins that are handled directly by the parser. They are
|
Builtins that are handled directly by the parser. They are
|
||||||
|
@ -2853,6 +2850,7 @@ void builtin_init()
|
||||||
intern_static( L"or" );
|
intern_static( L"or" );
|
||||||
intern_static( L"begin" );
|
intern_static( L"begin" );
|
||||||
intern_static( L"status" );
|
intern_static( L"status" );
|
||||||
|
intern_static( L"ulimit" );
|
||||||
|
|
||||||
builtin_help_init();
|
builtin_help_init();
|
||||||
}
|
}
|
||||||
|
@ -2980,6 +2978,7 @@ const wchar_t *builtin_get_desc( const wchar_t *b )
|
||||||
hash_put( desc, L"and", L"Execute second command if first suceeds");
|
hash_put( desc, L"and", L"Execute second command if first suceeds");
|
||||||
hash_put( desc, L"begin", L"Create a block of code" );
|
hash_put( desc, L"begin", L"Create a block of code" );
|
||||||
hash_put( desc, L"status", L"Return status information about fish" );
|
hash_put( desc, L"status", L"Return status information about fish" );
|
||||||
|
hash_put( desc, L"ulimit", L"Set or get the shells resurce usage limits" );
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash_get( desc, b );
|
return hash_get( desc, b );
|
||||||
|
|
|
@ -105,5 +105,13 @@ void builtin_print_help( wchar_t *cmd, string_buffer_t *b );
|
||||||
|
|
||||||
int builtin_set(wchar_t **argv);
|
int builtin_set(wchar_t **argv);
|
||||||
int builtin_commandline(wchar_t **argv);
|
int builtin_commandline(wchar_t **argv);
|
||||||
|
int builtin_ulimit(wchar_t **argv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function works like wperror, but it prints its result into
|
||||||
|
the sb_err string_buffer_t instead of to stderr. Used by the builtin
|
||||||
|
commands.
|
||||||
|
*/
|
||||||
|
void builtin_wperror( const wchar_t *s);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
453
builtin_ulimit.c
Normal file
453
builtin_ulimit.c
Normal file
|
@ -0,0 +1,453 @@
|
||||||
|
/** \file builtin_commandline.c Functions defining the commandline builtin
|
||||||
|
|
||||||
|
Functions used for implementing the commandline builtin.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#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"
|
||||||
|
|
||||||
|
struct resource_t
|
||||||
|
{
|
||||||
|
int resource;
|
||||||
|
const wchar_t *desc;
|
||||||
|
wchar_t switch_char;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
const static struct resource_t resource_arr[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
RLIMIT_CORE, L"Maximum size of core files created", L'c'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
RLIMIT_DATA, L"Maximum size of a process’s data segment", L'd'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
RLIMIT_RSS, L"Maximum resident set size", L'm'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
RLIMIT_NOFILE, L"Maximum number of open file descriptors", L'n'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
RLIMIT_STACK, L"Maximum stack size", L's'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
0, 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
static int get_multiplier( int what )
|
||||||
|
{
|
||||||
|
if( ( what == RLIMIT_NPROC ) ||
|
||||||
|
( what == RLIMIT_NOFILE ) ||
|
||||||
|
( what == RLIMIT_CPU ) )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static rlim_t get( int resource, int hard )
|
||||||
|
{
|
||||||
|
struct rlimit ls;
|
||||||
|
|
||||||
|
getrlimit( resource, &ls );
|
||||||
|
|
||||||
|
return hard ? ls.rlim_max:ls.rlim_cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
sb_append2( sb_err,
|
||||||
|
argv[0],
|
||||||
|
BUILTIN_ERR_UNKNOWN,
|
||||||
|
L" ",
|
||||||
|
long_options[opt_index].name,
|
||||||
|
L"\n",
|
||||||
|
(void *)0 );
|
||||||
|
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;
|
||||||
|
|
||||||
|
case L'l':
|
||||||
|
what=RLIMIT_MEMLOCK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case L'm':
|
||||||
|
what=RLIMIT_RSS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case L'n':
|
||||||
|
what=RLIMIT_NOFILE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case L's':
|
||||||
|
what=RLIMIT_STACK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case L't':
|
||||||
|
what=RLIMIT_CPU;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case L'u':
|
||||||
|
what=RLIMIT_NPROC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case L'v':
|
||||||
|
what=RLIMIT_AS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
107
wutil.c
107
wutil.c
|
@ -195,6 +195,19 @@ void wperror(const wchar_t *s)
|
||||||
|
|
||||||
#if !HAVE_WPRINTF
|
#if !HAVE_WPRINTF
|
||||||
|
|
||||||
|
void pad( void (*writer)(wchar_t), int count)
|
||||||
|
{
|
||||||
|
|
||||||
|
int i;
|
||||||
|
if( count < 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( i=0; i<count; i++ )
|
||||||
|
{
|
||||||
|
writer( L' ' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Generic formatting function. All other string formatting functions
|
Generic formatting function. All other string formatting functions
|
||||||
are secretly a wrapper around this function. vgprintf does not
|
are secretly a wrapper around this function. vgprintf does not
|
||||||
|
@ -205,13 +218,14 @@ void wperror(const wchar_t *s)
|
||||||
Currently supported functionality:
|
Currently supported functionality:
|
||||||
|
|
||||||
- precision specification, both through .* and .N
|
- precision specification, both through .* and .N
|
||||||
- width specification through *
|
- width specification through * and N
|
||||||
- long versions of all filters thorugh l and ll prefix
|
- long versions of all filters thorugh l and ll prefix
|
||||||
- Character outout using %c
|
- Character outout using %c
|
||||||
- String output through %s
|
- String output through %s
|
||||||
- Floating point number output through %f
|
- Floating point number output through %f
|
||||||
- Integer output through %d or %i
|
- Integer output through %d or %i
|
||||||
- Unsigned integer output through %u
|
- Unsigned integer output through %u
|
||||||
|
- Left padding using the - prefix
|
||||||
|
|
||||||
For a full description on the usage of *printf, see use 'man 3 printf'.
|
For a full description on the usage of *printf, see use 'man 3 printf'.
|
||||||
*/
|
*/
|
||||||
|
@ -232,9 +246,20 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||||
filter++;
|
filter++;
|
||||||
int loop=1;
|
int loop=1;
|
||||||
int precision=-1;
|
int precision=-1;
|
||||||
|
int pad_left = 1;
|
||||||
|
|
||||||
|
if( iswdigit( *filter ) )
|
||||||
|
{
|
||||||
|
width=0;
|
||||||
|
while( (*filter >= L'0') && (*filter <= L'9'))
|
||||||
|
{
|
||||||
|
width=10*width+(*filter++ - L'0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while( loop )
|
while( loop )
|
||||||
{
|
{
|
||||||
|
|
||||||
switch(*filter)
|
switch(*filter)
|
||||||
{
|
{
|
||||||
case L'l':
|
case L'l':
|
||||||
|
@ -242,15 +267,21 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||||
is_long++;
|
is_long++;
|
||||||
filter++;
|
filter++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L'*':
|
case L'*':
|
||||||
/* Set minimum field width */
|
/* Set minimum field width */
|
||||||
width = va_arg( va, int );
|
width = va_arg( va, int );
|
||||||
filter++;
|
filter++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case L'-':
|
||||||
|
filter++;
|
||||||
|
pad_left=0;
|
||||||
|
break;
|
||||||
|
|
||||||
case L'.':
|
case L'.':
|
||||||
/*
|
/*
|
||||||
Set precision.
|
Set precision.
|
||||||
Hasn't been tested enough yet, so I don't really trust it.
|
|
||||||
*/
|
*/
|
||||||
filter++;
|
filter++;
|
||||||
if( *filter == L'*' )
|
if( *filter == L'*' )
|
||||||
|
@ -272,30 +303,37 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( *filter )
|
switch( *filter )
|
||||||
{
|
{
|
||||||
case L'c':
|
case L'c':
|
||||||
{
|
{
|
||||||
wchar_t c;
|
wchar_t c;
|
||||||
|
|
||||||
c = is_long?va_arg(va, wchar_t):btowc(va_arg(va, int));
|
if( (width >= 0) && pad_left )
|
||||||
if( width>= 0 )
|
|
||||||
{
|
{
|
||||||
int i;
|
pad( writer, width-1 );
|
||||||
for( i=1; i<width; i++ )
|
count += maxi( width-1, 0 );
|
||||||
{
|
|
||||||
writer( L' ' );
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c = is_long?va_arg(va, wchar_t):btowc(va_arg(va, int));
|
||||||
if( precision != 0 )
|
if( precision != 0 )
|
||||||
writer( c );
|
writer( c );
|
||||||
|
|
||||||
|
|
||||||
|
if( (width >= 0) && !pad_left )
|
||||||
|
{
|
||||||
|
pad( writer, width-1 );
|
||||||
|
count += maxi( width-1, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case L's':
|
case L's':
|
||||||
{
|
{
|
||||||
|
|
||||||
wchar_t *ss=0;
|
wchar_t *ss=0;
|
||||||
if( is_long )
|
if( is_long )
|
||||||
{
|
{
|
||||||
|
@ -316,14 +354,10 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( width>=0 )
|
if( (width >= 0) && pad_left )
|
||||||
{
|
{
|
||||||
int i;
|
pad( writer, width-wcslen(ss) );
|
||||||
for( i=wcslen(ss); i<width; i++ )
|
count += maxi(width-wcslen(ss), 0);
|
||||||
{
|
|
||||||
writer( L' ' );
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *s=ss;
|
wchar_t *s=ss;
|
||||||
|
@ -338,6 +372,12 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( (width >= 0) && !pad_left )
|
||||||
|
{
|
||||||
|
pad( writer, width-wcslen(ss) );
|
||||||
|
count += maxi( width-wcslen(ss), 0 );
|
||||||
|
}
|
||||||
|
|
||||||
if( !is_long )
|
if( !is_long )
|
||||||
free( ss );
|
free( ss );
|
||||||
|
|
||||||
|
@ -387,15 +427,10 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( width >= 0 )
|
if( (width >= 0) && pad_left )
|
||||||
{
|
{
|
||||||
int i;
|
pad( writer, width-strlen(str) );
|
||||||
|
count +=maxi(width-strlen(str), 0 );
|
||||||
for( i=strlen(str); i<width; i++ )
|
|
||||||
{
|
|
||||||
writer( L' ' );
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = str;
|
pos = str;
|
||||||
|
@ -406,6 +441,12 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( (width >= 0) && !pad_left )
|
||||||
|
{
|
||||||
|
pad( writer, width-strlen(str) );
|
||||||
|
count += maxi(width-strlen(str), 0 );
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,14 +491,10 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( width>=0 )
|
if( (width >= 0) && pad_left )
|
||||||
{
|
{
|
||||||
int i;
|
pad( writer, width-strlen(str) );
|
||||||
for( i=strlen(str); i<width; i++ )
|
count += maxi( width-strlen(str), 0 );
|
||||||
{
|
|
||||||
writer( L' ' );
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = str;
|
pos = str;
|
||||||
|
@ -468,6 +505,12 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( (width >= 0) && !pad_left )
|
||||||
|
{
|
||||||
|
pad( writer, width-strlen(str) );
|
||||||
|
count += maxi( width-strlen(str), 0 );
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user