mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Release Cosmopolitan v3.6.0
This release is an atomic upgrade to GCC 14.1.0 with C23 and C++23
This commit is contained in:
parent
62ace3623a
commit
5660ec4741
1585 changed files with 117353 additions and 271644 deletions
7
Makefile
7
Makefile
|
@ -150,10 +150,10 @@ export MODE
|
||||||
export SOURCE_DATE_EPOCH
|
export SOURCE_DATE_EPOCH
|
||||||
export TMPDIR
|
export TMPDIR
|
||||||
|
|
||||||
COSMOCC = .cosmocc/3.5.7
|
COSMOCC = .cosmocc/3.6.0
|
||||||
BOOTSTRAP = $(COSMOCC)/bin
|
BOOTSTRAP = $(COSMOCC)/bin
|
||||||
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
|
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
|
||||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.5.7 596876951b62ad2530c63afc40edd805d751fcb2416e544d249af04ad00bb4ed)
|
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.6.0 4918c45ac3e0972ff260e2a249e25716881e39fb679d5e714ae216a2ef6c3f7e)
|
||||||
|
|
||||||
AS = $(TOOLCHAIN)as
|
AS = $(TOOLCHAIN)as
|
||||||
CC = $(TOOLCHAIN)gcc
|
CC = $(TOOLCHAIN)gcc
|
||||||
|
@ -293,8 +293,7 @@ include third_party/openmp/BUILD.mk # │
|
||||||
include third_party/pcre/BUILD.mk # │
|
include third_party/pcre/BUILD.mk # │
|
||||||
include third_party/less/BUILD.mk # │
|
include third_party/less/BUILD.mk # │
|
||||||
include net/https/BUILD.mk # │
|
include net/https/BUILD.mk # │
|
||||||
include third_party/regex/BUILD.mk # │
|
include third_party/regex/BUILD.mk #─┘
|
||||||
include third_party/bash/BUILD.mk #─┘
|
|
||||||
include third_party/tidy/BUILD.mk
|
include third_party/tidy/BUILD.mk
|
||||||
include third_party/BUILD.mk
|
include third_party/BUILD.mk
|
||||||
include third_party/nsync/testing/BUILD.mk
|
include third_party/nsync/testing/BUILD.mk
|
||||||
|
|
|
@ -139,10 +139,10 @@ DEFAULT_CPPFLAGS += \
|
||||||
-isystem libc/isystem
|
-isystem libc/isystem
|
||||||
|
|
||||||
DEFAULT_CFLAGS = \
|
DEFAULT_CFLAGS = \
|
||||||
-std=gnu2x
|
-std=gnu23
|
||||||
|
|
||||||
DEFAULT_CXXFLAGS = \
|
DEFAULT_CXXFLAGS = \
|
||||||
-std=gnu++20 \
|
-std=gnu++23 \
|
||||||
-fno-rtti \
|
-fno-rtti \
|
||||||
-fno-exceptions \
|
-fno-exceptions \
|
||||||
-fuse-cxa-atexit \
|
-fuse-cxa-atexit \
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
#include <__atomic/fence.h>
|
#include <__atomic/fence.h>
|
||||||
#include <stdckdint.h>
|
#include <stdckdint.h>
|
||||||
|
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
namespace ctl {
|
namespace ctl {
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
11603
examples/unbourne.c
11603
examples/unbourne.c
File diff suppressed because it is too large
Load diff
|
@ -133,8 +133,8 @@ int nice(int) libcesque;
|
||||||
int open(const char *, int, ...) libcesque;
|
int open(const char *, int, ...) libcesque;
|
||||||
int openat(int, const char *, int, ...) libcesque;
|
int openat(int, const char *, int, ...) libcesque;
|
||||||
int pause(void) libcesque;
|
int pause(void) libcesque;
|
||||||
int pipe(int[hasatleast 2]) libcesque;
|
int pipe(int[2]) libcesque;
|
||||||
int pipe2(int[hasatleast 2], int) libcesque;
|
int pipe2(int[2], int) libcesque;
|
||||||
int posix_fadvise(int, int64_t, int64_t, int) libcesque;
|
int posix_fadvise(int, int64_t, int64_t, int) libcesque;
|
||||||
int posix_madvise(void *, uint64_t, int) libcesque;
|
int posix_madvise(void *, uint64_t, int) libcesque;
|
||||||
int raise(int) libcesque;
|
int raise(int) libcesque;
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
* @see pipe2()
|
* @see pipe2()
|
||||||
*/
|
*/
|
||||||
int pipe(int pipefd[hasatleast 2]) {
|
int pipe(int pipefd[2]) {
|
||||||
int rc;
|
int rc;
|
||||||
if (!pipefd) {
|
if (!pipefd) {
|
||||||
// needed for windows which is polyfilled
|
// needed for windows which is polyfilled
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
* @param flags can have O_CLOEXEC or O_DIRECT or O_NONBLOCK
|
* @param flags can have O_CLOEXEC or O_DIRECT or O_NONBLOCK
|
||||||
* @return 0 on success, or -1 w/ errno and pipefd isn't modified
|
* @return 0 on success, or -1 w/ errno and pipefd isn't modified
|
||||||
*/
|
*/
|
||||||
int pipe2(int pipefd[hasatleast 2], int flags) {
|
int pipe2(int pipefd[2], int flags) {
|
||||||
int rc;
|
int rc;
|
||||||
if (flags & ~(O_CLOEXEC | O_NONBLOCK | (O_DIRECT != -1u ? O_DIRECT : 0))) {
|
if (flags & ~(O_CLOEXEC | O_NONBLOCK | (O_DIRECT != -1u ? O_DIRECT : 0))) {
|
||||||
return einval();
|
return einval();
|
||||||
|
|
|
@ -20,14 +20,14 @@ struct Map {
|
||||||
intptr_t hand; /* windows nt only */
|
intptr_t hand; /* windows nt only */
|
||||||
union {
|
union {
|
||||||
struct Tree tree;
|
struct Tree tree;
|
||||||
struct Map *free;
|
struct Map *freed;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Maps {
|
struct Maps {
|
||||||
atomic_int lock;
|
atomic_int lock;
|
||||||
struct Tree *maps;
|
struct Tree *maps;
|
||||||
_Atomic(struct Map *) free;
|
_Atomic(struct Map *) freed;
|
||||||
size_t count;
|
size_t count;
|
||||||
size_t pages;
|
size_t pages;
|
||||||
_Atomic(char *) pick;
|
_Atomic(char *) pick;
|
||||||
|
|
|
@ -131,7 +131,7 @@ static int __muntrack(char *addr, size_t size, int pagesz,
|
||||||
if (addr <= map_addr && addr + PGUP(size) >= map_addr + PGUP(map_size)) {
|
if (addr <= map_addr && addr + PGUP(size) >= map_addr + PGUP(map_size)) {
|
||||||
// remove mapping completely
|
// remove mapping completely
|
||||||
tree_remove(&__maps.maps, &map->tree);
|
tree_remove(&__maps.maps, &map->tree);
|
||||||
map->free = *deleted;
|
map->freed = *deleted;
|
||||||
*deleted = map;
|
*deleted = map;
|
||||||
__maps.pages -= (map_size + pagesz - 1) / pagesz;
|
__maps.pages -= (map_size + pagesz - 1) / pagesz;
|
||||||
__maps.count -= 1;
|
__maps.count -= 1;
|
||||||
|
@ -155,7 +155,7 @@ static int __muntrack(char *addr, size_t size, int pagesz,
|
||||||
__maps.pages -= (left + pagesz - 1) / pagesz;
|
__maps.pages -= (left + pagesz - 1) / pagesz;
|
||||||
leftmap->addr = map_addr;
|
leftmap->addr = map_addr;
|
||||||
leftmap->size = left;
|
leftmap->size = left;
|
||||||
leftmap->free = *deleted;
|
leftmap->freed = *deleted;
|
||||||
*deleted = leftmap;
|
*deleted = leftmap;
|
||||||
__maps_check();
|
__maps_check();
|
||||||
} else {
|
} else {
|
||||||
|
@ -171,7 +171,7 @@ static int __muntrack(char *addr, size_t size, int pagesz,
|
||||||
__maps.pages -= (right + pagesz - 1) / pagesz;
|
__maps.pages -= (right + pagesz - 1) / pagesz;
|
||||||
rightmap->addr = addr;
|
rightmap->addr = addr;
|
||||||
rightmap->size = right;
|
rightmap->size = right;
|
||||||
rightmap->free = *deleted;
|
rightmap->freed = *deleted;
|
||||||
*deleted = rightmap;
|
*deleted = rightmap;
|
||||||
__maps_check();
|
__maps_check();
|
||||||
} else {
|
} else {
|
||||||
|
@ -200,7 +200,7 @@ static int __muntrack(char *addr, size_t size, int pagesz,
|
||||||
__maps.count += 1;
|
__maps.count += 1;
|
||||||
middlemap->addr = addr;
|
middlemap->addr = addr;
|
||||||
middlemap->size = size;
|
middlemap->size = size;
|
||||||
middlemap->free = *deleted;
|
middlemap->freed = *deleted;
|
||||||
*deleted = middlemap;
|
*deleted = middlemap;
|
||||||
__maps_check();
|
__maps_check();
|
||||||
} else {
|
} else {
|
||||||
|
@ -217,9 +217,9 @@ static int __muntrack(char *addr, size_t size, int pagesz,
|
||||||
void __maps_free(struct Map *map) {
|
void __maps_free(struct Map *map) {
|
||||||
map->size = 0;
|
map->size = 0;
|
||||||
map->addr = MAP_FAILED;
|
map->addr = MAP_FAILED;
|
||||||
map->free = atomic_load_explicit(&__maps.free, memory_order_relaxed);
|
map->freed = atomic_load_explicit(&__maps.freed, memory_order_relaxed);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (atomic_compare_exchange_weak_explicit(&__maps.free, &map->free, map,
|
if (atomic_compare_exchange_weak_explicit(&__maps.freed, &map->freed, map,
|
||||||
memory_order_release,
|
memory_order_release,
|
||||||
memory_order_relaxed))
|
memory_order_relaxed))
|
||||||
break;
|
break;
|
||||||
|
@ -229,7 +229,7 @@ void __maps_free(struct Map *map) {
|
||||||
static void __maps_free_all(struct Map *list) {
|
static void __maps_free_all(struct Map *list) {
|
||||||
struct Map *next;
|
struct Map *next;
|
||||||
for (struct Map *map = list; map; map = next) {
|
for (struct Map *map = list; map; map = next) {
|
||||||
next = map->free;
|
next = map->freed;
|
||||||
__maps_free(map);
|
__maps_free(map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,9 +285,9 @@ static void __maps_insert(struct Map *map) {
|
||||||
|
|
||||||
struct Map *__maps_alloc(void) {
|
struct Map *__maps_alloc(void) {
|
||||||
struct Map *map;
|
struct Map *map;
|
||||||
map = atomic_load_explicit(&__maps.free, memory_order_relaxed);
|
map = atomic_load_explicit(&__maps.freed, memory_order_relaxed);
|
||||||
while (map) {
|
while (map) {
|
||||||
if (atomic_compare_exchange_weak_explicit(&__maps.free, &map, map->free,
|
if (atomic_compare_exchange_weak_explicit(&__maps.freed, &map, map->freed,
|
||||||
memory_order_acquire,
|
memory_order_acquire,
|
||||||
memory_order_relaxed))
|
memory_order_relaxed))
|
||||||
return map;
|
return map;
|
||||||
|
@ -346,7 +346,7 @@ static int __munmap(char *addr, size_t size) {
|
||||||
|
|
||||||
// delete mappings
|
// delete mappings
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
for (struct Map *map = deleted; map; map = map->free) {
|
for (struct Map *map = deleted; map; map = map->freed) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
if (sys_munmap(map->addr, map->size))
|
if (sys_munmap(map->addr, map->size))
|
||||||
rc = -1;
|
rc = -1;
|
||||||
|
@ -359,7 +359,7 @@ static int __munmap(char *addr, size_t size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// free mappings
|
// freed mappings
|
||||||
__maps_free_all(deleted);
|
__maps_free_all(deleted);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -451,7 +451,7 @@ TryAgain:
|
||||||
}
|
}
|
||||||
|
|
||||||
// polyfill map fixed noreplace
|
// polyfill map fixed noreplace
|
||||||
// we assume non-linux gives us addr if it's free
|
// we assume non-linux gives us addr if it's freed
|
||||||
// that's what linux (e.g. rhel7) did before noreplace
|
// that's what linux (e.g. rhel7) did before noreplace
|
||||||
if (noreplace && res.addr != addr) {
|
if (noreplace && res.addr != addr) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include "third_party/libcxx/__threading_support"
|
|
1
libc/isystem/amxcomplexintrin.h
Normal file
1
libc/isystem/amxcomplexintrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/amxcomplexintrin.internal.h"
|
1
libc/isystem/amxfp16intrin.h
Normal file
1
libc/isystem/amxfp16intrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/amxfp16intrin.internal.h"
|
1
libc/isystem/avxifmaintrin.h
Normal file
1
libc/isystem/avxifmaintrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/avxifmaintrin.internal.h"
|
1
libc/isystem/avxneconvertintrin.h
Normal file
1
libc/isystem/avxneconvertintrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/avxneconvertintrin.internal.h"
|
1
libc/isystem/avxvnniint16intrin.h
Normal file
1
libc/isystem/avxvnniint16intrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/avxvnniint16intrin.internal.h"
|
1
libc/isystem/avxvnniint8intrin.h
Normal file
1
libc/isystem/avxvnniint8intrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/avxvnniint8intrin.internal.h"
|
1
libc/isystem/bmmintrin.h
Normal file
1
libc/isystem/bmmintrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/bmmintrin.internal.h"
|
1
libc/isystem/cmpccxaddintrin.h
Normal file
1
libc/isystem/cmpccxaddintrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/cmpccxaddintrin.internal.h"
|
1
libc/isystem/prfchiintrin.h
Normal file
1
libc/isystem/prfchiintrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/prfchiintrin.internal.h"
|
1
libc/isystem/raointintrin.h
Normal file
1
libc/isystem/raointintrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/raointintrin.internal.h"
|
1
libc/isystem/sha512intrin.h
Normal file
1
libc/isystem/sha512intrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/sha512intrin.internal.h"
|
1
libc/isystem/sm3intrin.h
Normal file
1
libc/isystem/sm3intrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/sm3intrin.internal.h"
|
1
libc/isystem/sm4intrin.h
Normal file
1
libc/isystem/sm4intrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/sm4intrin.internal.h"
|
1
libc/isystem/usermsrintrin.h
Normal file
1
libc/isystem/usermsrintrin.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "third_party/intel/usermsrintrin.internal.h"
|
|
@ -159,10 +159,7 @@ typedef double double_t;
|
||||||
#define fpclassify(x) \
|
#define fpclassify(x) \
|
||||||
__builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
|
__builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
|
||||||
|
|
||||||
#define signbit(x) \
|
#define signbit(x) __builtin_signbit(x)
|
||||||
(sizeof(x) == sizeof(long double) ? __builtin_signbitl(x) \
|
|
||||||
: sizeof(x) == sizeof(float) ? __builtin_signbitf(x) \
|
|
||||||
: __builtin_signbit(x))
|
|
||||||
|
|
||||||
extern int signgam;
|
extern int signgam;
|
||||||
|
|
||||||
|
|
|
@ -271,8 +271,8 @@ textwindows void WinMainForked(void) {
|
||||||
__threaded = false;
|
__threaded = false;
|
||||||
|
|
||||||
// fixup memory manager
|
// fixup memory manager
|
||||||
__maps.free = 0;
|
|
||||||
__maps.maps = 0;
|
__maps.maps = 0;
|
||||||
|
__maps.freed = 0;
|
||||||
__maps.count = 0;
|
__maps.count = 0;
|
||||||
__maps.pages = 0;
|
__maps.pages = 0;
|
||||||
for (struct Tree *e = tree_first(maps); e; e = tree_next(e)) {
|
for (struct Tree *e = tree_first(maps); e; e = tree_next(e)) {
|
||||||
|
|
|
@ -449,7 +449,10 @@ static int __fmt_stoa(int out(const char *, void *, size_t), void *arg,
|
||||||
} else if (signbit == 15) {
|
} else if (signbit == 15) {
|
||||||
precision = strnlen16((const char16_t *)p, precision);
|
precision = strnlen16((const char16_t *)p, precision);
|
||||||
} else {
|
} else {
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wstringop-overread"
|
||||||
precision = strnlen(p, precision);
|
precision = strnlen(p, precision);
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -204,7 +204,7 @@ static double sin_pi(double x)
|
||||||
double lgamma_r(double x, int *signgamp)
|
double lgamma_r(double x, int *signgamp)
|
||||||
{
|
{
|
||||||
union {double f; uint64_t i;} u = {x};
|
union {double f; uint64_t i;} u = {x};
|
||||||
double_t t,y,z,nadj,p,p1,p2,p3,q,r,w;
|
double_t t,y,z,nadj=0,p,p1,p2,p3,q,r,w;
|
||||||
uint32_t ix;
|
uint32_t ix;
|
||||||
int sign,i;
|
int sign,i;
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ static float sin_pi(float x)
|
||||||
float lgammaf_r(float x, int *signgamp)
|
float lgammaf_r(float x, int *signgamp)
|
||||||
{
|
{
|
||||||
union {float f; uint32_t i;} u = {x};
|
union {float f; uint32_t i;} u = {x};
|
||||||
float t,y,z,nadj,p,p1,p2,p3,q,r,w;
|
float t,y,z,nadj=0,p,p1,p2,p3,q,r,w;
|
||||||
uint32_t ix;
|
uint32_t ix;
|
||||||
int i,sign;
|
int i,sign;
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,7 @@ static long double sin_pi(long double x)
|
||||||
}
|
}
|
||||||
|
|
||||||
long double lgammal_r(long double x, int *sg) {
|
long double lgammal_r(long double x, int *sg) {
|
||||||
long double t, y, z, nadj, p, p1, p2, q, r, w;
|
long double t, y, z, nadj=0, p, p1, p2, q, r, w;
|
||||||
union ldshape u = {x};
|
union ldshape u = {x};
|
||||||
uint32_t ix = (u.i.se & 0x7fffU)<<16 | u.i.m>>48;
|
uint32_t ix = (u.i.se & 0x7fffU)<<16 | u.i.m>>48;
|
||||||
int sign = u.i.se >> 15;
|
int sign = u.i.se >> 15;
|
||||||
|
|
|
@ -80,23 +80,19 @@ void SetUp(void) {
|
||||||
sigaction(SIGSEGV, &sa, 0);
|
sigaction(SIGSEGV, &sa, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int StackOverflow(int f(), int n) {
|
int StackOverflow(void);
|
||||||
if (n < INT_MAX) {
|
int (*pStackOverflow)(void) = StackOverflow;
|
||||||
return f(f, n + 1) - 1;
|
int StackOverflow(void) {
|
||||||
} else {
|
return pStackOverflow();
|
||||||
return INT_MAX;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int (*pStackOverflow)(int (*)(), int) = StackOverflow;
|
|
||||||
|
|
||||||
TEST(stackoverflow, standardStack_altStack_process_longjmp) {
|
TEST(stackoverflow, standardStack_altStack_process_longjmp) {
|
||||||
if (IsTiny())
|
if (IsTiny())
|
||||||
return; // TODO(jart): why?
|
return; // TODO(jart): why?
|
||||||
|
|
||||||
int jumpcode;
|
int jumpcode;
|
||||||
if (!(jumpcode = setjmp(recover))) {
|
if (!(jumpcode = setjmp(recover))) {
|
||||||
exit(pStackOverflow(pStackOverflow, 0));
|
exit(pStackOverflow());
|
||||||
}
|
}
|
||||||
ASSERT_EQ(123, jumpcode);
|
ASSERT_EQ(123, jumpcode);
|
||||||
ASSERT_TRUE(smashed_stack);
|
ASSERT_TRUE(smashed_stack);
|
||||||
|
|
|
@ -51,16 +51,12 @@ void CrashHandler(int sig, siginfo_t *si, void *ctx) {
|
||||||
longjmp(recover, 123);
|
longjmp(recover, 123);
|
||||||
}
|
}
|
||||||
|
|
||||||
int StackOverflow(int f(), int n) {
|
int StackOverflow(void);
|
||||||
if (n < INT_MAX) {
|
int (*pStackOverflow)(void) = StackOverflow;
|
||||||
return f(f, n + 1) - 1;
|
int StackOverflow(void) {
|
||||||
} else {
|
return pStackOverflow();
|
||||||
return INT_MAX;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int (*pStackOverflow)(int (*)(), int) = StackOverflow;
|
|
||||||
|
|
||||||
void *MyPosixThread(void *arg) {
|
void *MyPosixThread(void *arg) {
|
||||||
int jumpcode;
|
int jumpcode;
|
||||||
struct sigaction sa, o1, o2;
|
struct sigaction sa, o1, o2;
|
||||||
|
@ -75,7 +71,7 @@ void *MyPosixThread(void *arg) {
|
||||||
sigaction(SIGBUS, &sa, &o1);
|
sigaction(SIGBUS, &sa, &o1);
|
||||||
sigaction(SIGSEGV, &sa, &o2);
|
sigaction(SIGSEGV, &sa, &o2);
|
||||||
if (!(jumpcode = setjmp(recover))) {
|
if (!(jumpcode = setjmp(recover))) {
|
||||||
exit(pStackOverflow(pStackOverflow, 0));
|
exit(pStackOverflow());
|
||||||
}
|
}
|
||||||
ASSERT_EQ(123, jumpcode);
|
ASSERT_EQ(123, jumpcode);
|
||||||
sigaction(SIGSEGV, &o2, 0);
|
sigaction(SIGSEGV, &o2, 0);
|
||||||
|
|
|
@ -85,16 +85,12 @@ void CrashHandler(int sig, siginfo_t *si, void *arg) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int StackOverflow(int f(), int n) {
|
int StackOverflow(void);
|
||||||
if (n < INT_MAX) {
|
int (*pStackOverflow)(void) = StackOverflow;
|
||||||
return f(f, n + 1) - 1;
|
int StackOverflow(void) {
|
||||||
} else {
|
return pStackOverflow();
|
||||||
return INT_MAX;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int (*pStackOverflow)(int (*)(), int) = StackOverflow;
|
|
||||||
|
|
||||||
void *MyPosixThread(void *arg) {
|
void *MyPosixThread(void *arg) {
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
struct sigaltstack ss;
|
struct sigaltstack ss;
|
||||||
|
@ -107,7 +103,7 @@ void *MyPosixThread(void *arg) {
|
||||||
sa.sa_sigaction = CrashHandler;
|
sa.sa_sigaction = CrashHandler;
|
||||||
sigaction(SIGBUS, &sa, 0);
|
sigaction(SIGBUS, &sa, 0);
|
||||||
sigaction(SIGSEGV, &sa, 0);
|
sigaction(SIGSEGV, &sa, 0);
|
||||||
exit(pStackOverflow(pStackOverflow, 0));
|
exit(pStackOverflow());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,16 +45,12 @@ void CrashHandler(int sig) {
|
||||||
pthread_exit((void *)123L);
|
pthread_exit((void *)123L);
|
||||||
}
|
}
|
||||||
|
|
||||||
int StackOverflow(int f(), int n) {
|
int StackOverflow(void);
|
||||||
if (n < INT_MAX) {
|
int (*pStackOverflow)(void) = StackOverflow;
|
||||||
return f(f, n + 1) - 1;
|
int StackOverflow(void) {
|
||||||
} else {
|
return pStackOverflow();
|
||||||
return INT_MAX;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int (*pStackOverflow)(int (*)(), int) = StackOverflow;
|
|
||||||
|
|
||||||
void *MyPosixThread(void *arg) {
|
void *MyPosixThread(void *arg) {
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
struct sigaltstack ss;
|
struct sigaltstack ss;
|
||||||
|
@ -67,7 +63,7 @@ void *MyPosixThread(void *arg) {
|
||||||
sa.sa_handler = CrashHandler;
|
sa.sa_handler = CrashHandler;
|
||||||
sigaction(SIGBUS, &sa, 0);
|
sigaction(SIGBUS, &sa, 0);
|
||||||
sigaction(SIGSEGV, &sa, 0);
|
sigaction(SIGSEGV, &sa, 0);
|
||||||
exit(pStackOverflow(pStackOverflow, 0));
|
exit(pStackOverflow());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,18 +34,14 @@ void CrashHandler(int sig) {
|
||||||
pthread_exit(0);
|
pthread_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int StackOverflow(int f(), int n) {
|
int StackOverflow(void);
|
||||||
if (n < INT_MAX) {
|
int (*pStackOverflow)(void) = StackOverflow;
|
||||||
return f(f, n + 1) - 1;
|
int StackOverflow(void) {
|
||||||
} else {
|
return pStackOverflow();
|
||||||
return INT_MAX;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int (*pStackOverflow)(int (*)(), int) = StackOverflow;
|
|
||||||
|
|
||||||
void *MyPosixThread(void *arg) {
|
void *MyPosixThread(void *arg) {
|
||||||
exit(pStackOverflow(pStackOverflow, 0));
|
exit(pStackOverflow());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/math.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
#include "third_party/libcxx/math.h"
|
|
||||||
|
|
||||||
TEST(fmax, test) {
|
TEST(fmax, test) {
|
||||||
EXPECT_TRUE(fmax(2., 3.) == 3.);
|
EXPECT_TRUE(fmax(2., 3.) == 3.);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
|
#include "libc/intrin/weaken.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/mem/leaks.h"
|
#include "libc/mem/leaks.h"
|
||||||
|
@ -27,12 +28,8 @@
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
int StackOverflow(int f(), int n) {
|
int StackOverflow(void) {
|
||||||
if (n < INT_MAX) {
|
return _weaken(StackOverflow)();
|
||||||
return f(f, n + 1) - 1;
|
|
||||||
} else {
|
|
||||||
return INT_MAX;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FpuCrash(void) {
|
void FpuCrash(void) {
|
||||||
|
@ -95,7 +92,7 @@ int (*pRodataOverrunCrash)(int) = RodataOverrunCrash;
|
||||||
char *(*pStackOverrunCrash)(int) = StackOverrunCrash;
|
char *(*pStackOverrunCrash)(int) = StackOverrunCrash;
|
||||||
char *(*pMemoryLeakCrash)(void) = MemoryLeakCrash;
|
char *(*pMemoryLeakCrash)(void) = MemoryLeakCrash;
|
||||||
int (*pNpeCrash)(char *) = NpeCrash;
|
int (*pNpeCrash)(char *) = NpeCrash;
|
||||||
int (*pStackOverflow)(int (*)(), int) = StackOverflow;
|
int (*pStackOverflow)(void) = StackOverflow;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
ShowCrashReports();
|
ShowCrashReports();
|
||||||
|
@ -123,7 +120,7 @@ int main(int argc, char *argv[]) {
|
||||||
case 8:
|
case 8:
|
||||||
exit(pNpeCrash(0));
|
exit(pNpeCrash(0));
|
||||||
case 9:
|
case 9:
|
||||||
exit(pStackOverflow(pStackOverflow, 0));
|
exit(pStackOverflow());
|
||||||
default:
|
default:
|
||||||
fputs("error: unrecognized argument\n", stderr);
|
fputs("error: unrecognized argument\n", stderr);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
|
#include "libc/math.h"
|
||||||
#include "libc/mem/gc.h"
|
#include "libc/mem/gc.h"
|
||||||
#include "libc/nt/createfile.h"
|
#include "libc/nt/createfile.h"
|
||||||
#include "libc/nt/enum/accessmask.h"
|
#include "libc/nt/enum/accessmask.h"
|
||||||
|
@ -36,7 +37,6 @@
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
#include "libc/thread/thread.h"
|
#include "libc/thread/thread.h"
|
||||||
#include "libc/x/x.h"
|
#include "libc/x/x.h"
|
||||||
#include "third_party/libcxx/math.h"
|
|
||||||
|
|
||||||
bool gotsome;
|
bool gotsome;
|
||||||
ucontext_t uc, goback;
|
ucontext_t uc, goback;
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
||||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
|
||||||
│ │
|
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
|
||||||
│ above copyright notice and this permission notice appear in all copies. │
|
|
||||||
│ │
|
|
||||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
||||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
||||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
||||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
||||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
||||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
||||||
#include "libc/calls/struct/cpuset.h"
|
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
|
||||||
#include "libc/testlib/testlib.h"
|
|
||||||
#include "libc/thread/thread.h"
|
|
||||||
#include "libc/thread/thread2.h"
|
|
||||||
|
|
||||||
TEST(pthread_setaffinity_np, test) {
|
|
||||||
|
|
||||||
// works on almost nothing
|
|
||||||
if (IsXnu())
|
|
||||||
return;
|
|
||||||
if (IsNetbsd())
|
|
||||||
return;
|
|
||||||
if (IsOpenbsd())
|
|
||||||
return;
|
|
||||||
if (__get_cpu_count() < 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// save bitset
|
|
||||||
cpu_set_t old;
|
|
||||||
if (!IsWindows())
|
|
||||||
ASSERT_EQ(0, pthread_getaffinity_np(pthread_self(), sizeof(old), &old));
|
|
||||||
|
|
||||||
// go to first cpu
|
|
||||||
cpu_set_t bitset;
|
|
||||||
CPU_ZERO(&bitset);
|
|
||||||
CPU_SET(0, &bitset);
|
|
||||||
ASSERT_EQ(0, pthread_setaffinity_np(pthread_self(), sizeof(bitset), &bitset));
|
|
||||||
ASSERT_EQ(0, sched_getcpu());
|
|
||||||
|
|
||||||
// go to second cpu
|
|
||||||
CPU_ZERO(&bitset);
|
|
||||||
CPU_SET(1, &bitset);
|
|
||||||
ASSERT_EQ(0, pthread_setaffinity_np(pthread_self(), sizeof(bitset), &bitset));
|
|
||||||
ASSERT_EQ(1, sched_getcpu());
|
|
||||||
|
|
||||||
// restore bitset
|
|
||||||
if (!IsWindows())
|
|
||||||
ASSERT_EQ(0, pthread_setaffinity_np(pthread_self(), sizeof(old), &old));
|
|
||||||
}
|
|
|
@ -31,7 +31,7 @@ TEST(HasControlCodes, test) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(HasControlCodes, testDoesUtf8) {
|
TEST(HasControlCodes, testDoesUtf8) {
|
||||||
EXPECT_EQ(-1, HasControlCodes(u8"→", -1, kControlC0 | kControlC1));
|
EXPECT_EQ(-1, HasControlCodes("→", -1, kControlC0 | kControlC1));
|
||||||
EXPECT_EQ(-1, HasControlCodes("\304\200", -1, kControlC0 | kControlC1));
|
EXPECT_EQ(-1, HasControlCodes("\304\200", -1, kControlC0 | kControlC1));
|
||||||
EXPECT_NE(-1, HasControlCodes("\300\200", -1, kControlC0 | kControlC1));
|
EXPECT_NE(-1, HasControlCodes("\300\200", -1, kControlC0 | kControlC1));
|
||||||
EXPECT_EQ(-1, HasControlCodes("\300\200", -1, kControlC1));
|
EXPECT_EQ(-1, HasControlCodes("\300\200", -1, kControlC1));
|
||||||
|
|
1
third_party/BUILD.mk
vendored
1
third_party/BUILD.mk
vendored
|
@ -5,7 +5,6 @@
|
||||||
o/$(MODE)/third_party: \
|
o/$(MODE)/third_party: \
|
||||||
o/$(MODE)/third_party/argon2 \
|
o/$(MODE)/third_party/argon2 \
|
||||||
o/$(MODE)/third_party/awk \
|
o/$(MODE)/third_party/awk \
|
||||||
o/$(MODE)/third_party/bash \
|
|
||||||
o/$(MODE)/third_party/bzip2 \
|
o/$(MODE)/third_party/bzip2 \
|
||||||
o/$(MODE)/third_party/chibicc \
|
o/$(MODE)/third_party/chibicc \
|
||||||
o/$(MODE)/third_party/compiler_rt \
|
o/$(MODE)/third_party/compiler_rt \
|
||||||
|
|
164
third_party/aarch64/acc_prof.internal.h
vendored
164
third_party/aarch64/acc_prof.internal.h
vendored
|
@ -1,164 +0,0 @@
|
||||||
#if defined(__aarch64__) && !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
||||||
#ifndef _ACC_PROF_H
|
|
||||||
#define _ACC_PROF_H 1
|
|
||||||
#include "third_party/aarch64/openacc.internal.h"
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
typedef enum acc_event_t
|
|
||||||
{
|
|
||||||
acc_ev_none = 0,
|
|
||||||
acc_ev_device_init_start,
|
|
||||||
acc_ev_device_init_end,
|
|
||||||
acc_ev_device_shutdown_start,
|
|
||||||
acc_ev_device_shutdown_end,
|
|
||||||
acc_ev_runtime_shutdown,
|
|
||||||
acc_ev_create,
|
|
||||||
acc_ev_delete,
|
|
||||||
acc_ev_alloc,
|
|
||||||
acc_ev_free,
|
|
||||||
acc_ev_enter_data_start,
|
|
||||||
acc_ev_enter_data_end,
|
|
||||||
acc_ev_exit_data_start,
|
|
||||||
acc_ev_exit_data_end,
|
|
||||||
acc_ev_update_start,
|
|
||||||
acc_ev_update_end,
|
|
||||||
acc_ev_compute_construct_start,
|
|
||||||
acc_ev_compute_construct_end,
|
|
||||||
acc_ev_enqueue_launch_start,
|
|
||||||
acc_ev_enqueue_launch_end,
|
|
||||||
acc_ev_enqueue_upload_start,
|
|
||||||
acc_ev_enqueue_upload_end,
|
|
||||||
acc_ev_enqueue_download_start,
|
|
||||||
acc_ev_enqueue_download_end,
|
|
||||||
acc_ev_wait_start,
|
|
||||||
acc_ev_wait_end,
|
|
||||||
acc_ev_last
|
|
||||||
} acc_event_t;
|
|
||||||
typedef signed long int _acc_prof_ssize_t;
|
|
||||||
typedef unsigned long int _acc_prof_size_t;
|
|
||||||
typedef int _acc_prof_int_t;
|
|
||||||
#define _ACC_PROF_VALID_BYTES_STRUCT(_struct, _lastfield, _valid_bytes_lastfield) offsetof (_struct, _lastfield) + (_valid_bytes_lastfield)
|
|
||||||
#if 0
|
|
||||||
#define _ACC_PROF_VALID_BYTES_TYPE_N(_type, _n, _valid_bytes_type) ((_n - 1) * sizeof (_type) + (_valid_bytes_type))
|
|
||||||
#endif
|
|
||||||
#define _ACC_PROF_VALID_BYTES_BASICTYPE(_basictype) (sizeof (_basictype))
|
|
||||||
typedef struct acc_prof_info
|
|
||||||
{
|
|
||||||
acc_event_t event_type;
|
|
||||||
_acc_prof_int_t valid_bytes;
|
|
||||||
_acc_prof_int_t version;
|
|
||||||
acc_device_t device_type;
|
|
||||||
_acc_prof_int_t device_number;
|
|
||||||
_acc_prof_int_t thread_id;
|
|
||||||
_acc_prof_ssize_t async;
|
|
||||||
_acc_prof_ssize_t async_queue;
|
|
||||||
const char *src_file;
|
|
||||||
const char *func_name;
|
|
||||||
_acc_prof_int_t line_no, end_line_no;
|
|
||||||
_acc_prof_int_t func_line_no, func_end_line_no;
|
|
||||||
#define _ACC_PROF_INFO_VALID_BYTES _ACC_PROF_VALID_BYTES_STRUCT (acc_prof_info, func_end_line_no, _ACC_PROF_VALID_BYTES_BASICTYPE (_acc_prof_int_t))
|
|
||||||
} acc_prof_info;
|
|
||||||
#define _ACC_PROF_INFO_VERSION 201711
|
|
||||||
typedef enum acc_construct_t
|
|
||||||
{
|
|
||||||
acc_construct_parallel = 0,
|
|
||||||
acc_construct_kernels,
|
|
||||||
acc_construct_loop,
|
|
||||||
acc_construct_data,
|
|
||||||
acc_construct_enter_data,
|
|
||||||
acc_construct_exit_data,
|
|
||||||
acc_construct_host_data,
|
|
||||||
acc_construct_atomic,
|
|
||||||
acc_construct_declare,
|
|
||||||
acc_construct_init,
|
|
||||||
acc_construct_shutdown,
|
|
||||||
acc_construct_set,
|
|
||||||
acc_construct_update,
|
|
||||||
acc_construct_routine,
|
|
||||||
acc_construct_wait,
|
|
||||||
acc_construct_runtime_api,
|
|
||||||
acc_construct_serial
|
|
||||||
} acc_construct_t;
|
|
||||||
typedef struct acc_data_event_info
|
|
||||||
{
|
|
||||||
acc_event_t event_type;
|
|
||||||
_acc_prof_int_t valid_bytes;
|
|
||||||
acc_construct_t parent_construct;
|
|
||||||
_acc_prof_int_t implicit;
|
|
||||||
void *tool_info;
|
|
||||||
const char *var_name;
|
|
||||||
_acc_prof_size_t bytes;
|
|
||||||
const void *host_ptr;
|
|
||||||
const void *device_ptr;
|
|
||||||
#define _ACC_DATA_EVENT_INFO_VALID_BYTES _ACC_PROF_VALID_BYTES_STRUCT (acc_data_event_info, device_ptr, _ACC_PROF_VALID_BYTES_BASICTYPE (void *))
|
|
||||||
} acc_data_event_info;
|
|
||||||
typedef struct acc_launch_event_info
|
|
||||||
{
|
|
||||||
acc_event_t event_type;
|
|
||||||
_acc_prof_int_t valid_bytes;
|
|
||||||
acc_construct_t parent_construct;
|
|
||||||
_acc_prof_int_t implicit;
|
|
||||||
void *tool_info;
|
|
||||||
const char *kernel_name;
|
|
||||||
_acc_prof_size_t num_gangs, num_workers, vector_length;
|
|
||||||
#define _ACC_LAUNCH_EVENT_INFO_VALID_BYTES _ACC_PROF_VALID_BYTES_STRUCT (acc_launch_event_info, vector_length, _ACC_PROF_VALID_BYTES_BASICTYPE (_acc_prof_size_t))
|
|
||||||
} acc_launch_event_info;
|
|
||||||
typedef struct acc_other_event_info
|
|
||||||
{
|
|
||||||
acc_event_t event_type;
|
|
||||||
_acc_prof_int_t valid_bytes;
|
|
||||||
acc_construct_t parent_construct;
|
|
||||||
_acc_prof_int_t implicit;
|
|
||||||
void *tool_info;
|
|
||||||
#define _ACC_OTHER_EVENT_INFO_VALID_BYTES _ACC_PROF_VALID_BYTES_STRUCT (acc_other_event_info, tool_info, _ACC_PROF_VALID_BYTES_BASICTYPE (void *))
|
|
||||||
} acc_other_event_info;
|
|
||||||
typedef union acc_event_info
|
|
||||||
{
|
|
||||||
acc_event_t event_type;
|
|
||||||
acc_data_event_info data_event;
|
|
||||||
acc_launch_event_info launch_event;
|
|
||||||
acc_other_event_info other_event;
|
|
||||||
} acc_event_info;
|
|
||||||
typedef enum acc_device_api
|
|
||||||
{
|
|
||||||
acc_device_api_none = 0,
|
|
||||||
acc_device_api_cuda,
|
|
||||||
acc_device_api_opencl,
|
|
||||||
acc_device_api_coi,
|
|
||||||
acc_device_api_other
|
|
||||||
} acc_device_api;
|
|
||||||
typedef struct acc_api_info
|
|
||||||
{
|
|
||||||
acc_device_api device_api;
|
|
||||||
_acc_prof_int_t valid_bytes;
|
|
||||||
acc_device_t device_type;
|
|
||||||
_acc_prof_int_t vendor;
|
|
||||||
const void *device_handle;
|
|
||||||
const void *context_handle;
|
|
||||||
const void *async_handle;
|
|
||||||
#define _ACC_API_INFO_VALID_BYTES _ACC_PROF_VALID_BYTES_STRUCT (acc_api_info, async_handle, _ACC_PROF_VALID_BYTES_BASICTYPE (void *))
|
|
||||||
} acc_api_info;
|
|
||||||
typedef void (*acc_prof_callback) (acc_prof_info *, acc_event_info *,
|
|
||||||
acc_api_info *);
|
|
||||||
typedef enum acc_register_t
|
|
||||||
{
|
|
||||||
acc_reg = 0,
|
|
||||||
acc_toggle = 1,
|
|
||||||
acc_toggle_per_thread = 2
|
|
||||||
} acc_register_t;
|
|
||||||
typedef void (*acc_prof_reg) (acc_event_t, acc_prof_callback, acc_register_t);
|
|
||||||
extern void acc_prof_register (acc_event_t, acc_prof_callback,
|
|
||||||
acc_register_t) __GOACC_NOTHROW;
|
|
||||||
extern void acc_prof_unregister (acc_event_t, acc_prof_callback,
|
|
||||||
acc_register_t) __GOACC_NOTHROW;
|
|
||||||
typedef void (*acc_query_fn) ();
|
|
||||||
typedef acc_query_fn (*acc_prof_lookup_func) (const char *);
|
|
||||||
extern acc_query_fn acc_prof_lookup (const char *) __GOACC_NOTHROW;
|
|
||||||
extern void acc_register_library (acc_prof_reg, acc_prof_reg,
|
|
||||||
acc_prof_lookup_func);
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
70
third_party/aarch64/arm_acle.internal.h
vendored
70
third_party/aarch64/arm_acle.internal.h
vendored
|
@ -27,6 +27,32 @@ _GCC_ARM_ACLE_DATA_FN (revsh, bswap16, int16_t, int16_t)
|
||||||
_GCC_ARM_ACLE_DATA_FN (rev, bswap32, uint32_t, uint32_t)
|
_GCC_ARM_ACLE_DATA_FN (rev, bswap32, uint32_t, uint32_t)
|
||||||
_GCC_ARM_ACLE_DATA_FN (revll, bswap64, uint64_t, uint64_t)
|
_GCC_ARM_ACLE_DATA_FN (revll, bswap64, uint64_t, uint64_t)
|
||||||
#undef _GCC_ARM_ACLE_DATA_FN
|
#undef _GCC_ARM_ACLE_DATA_FN
|
||||||
|
__extension__ extern __inline void
|
||||||
|
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
||||||
|
__pld (void const volatile *__addr)
|
||||||
|
{
|
||||||
|
return __builtin_aarch64_pld (__addr);
|
||||||
|
}
|
||||||
|
__extension__ extern __inline void
|
||||||
|
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
||||||
|
__pli (void const volatile *__addr)
|
||||||
|
{
|
||||||
|
return __builtin_aarch64_pli (__addr);
|
||||||
|
}
|
||||||
|
__extension__ extern __inline void
|
||||||
|
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
||||||
|
__plix (unsigned int __cache, unsigned int __rettn,
|
||||||
|
void const volatile *__addr)
|
||||||
|
{
|
||||||
|
return __builtin_aarch64_plix (__cache, __rettn, __addr);
|
||||||
|
}
|
||||||
|
__extension__ extern __inline void
|
||||||
|
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
||||||
|
__pldx (unsigned int __access, unsigned int __cache, unsigned int __rettn,
|
||||||
|
void const volatile *__addr)
|
||||||
|
{
|
||||||
|
return __builtin_aarch64_pldx (__access, __cache, __rettn, __addr);
|
||||||
|
}
|
||||||
__extension__ extern __inline unsigned long
|
__extension__ extern __inline unsigned long
|
||||||
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
||||||
__revl (unsigned long __value)
|
__revl (unsigned long __value)
|
||||||
|
@ -188,34 +214,7 @@ __ttest (void)
|
||||||
#pragma GCC pop_options
|
#pragma GCC pop_options
|
||||||
#endif
|
#endif
|
||||||
#ifdef __ARM_FEATURE_LS64
|
#ifdef __ARM_FEATURE_LS64
|
||||||
#pragma GCC push_options
|
|
||||||
#pragma GCC target ("+nothing+ls64")
|
|
||||||
typedef __arm_data512_t data512_t;
|
typedef __arm_data512_t data512_t;
|
||||||
__extension__ extern __inline data512_t
|
|
||||||
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
|
||||||
__arm_ld64b (const void *__addr)
|
|
||||||
{
|
|
||||||
return __builtin_aarch64_ld64b (__addr);
|
|
||||||
}
|
|
||||||
__extension__ extern __inline void
|
|
||||||
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
|
||||||
__arm_st64b (void *__addr, data512_t __value)
|
|
||||||
{
|
|
||||||
__builtin_aarch64_st64b (__addr, __value);
|
|
||||||
}
|
|
||||||
__extension__ extern __inline uint64_t
|
|
||||||
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
|
||||||
__arm_st64bv (void *__addr, data512_t __value)
|
|
||||||
{
|
|
||||||
return __builtin_aarch64_st64bv (__addr, __value);
|
|
||||||
}
|
|
||||||
__extension__ extern __inline uint64_t
|
|
||||||
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
|
||||||
__arm_st64bv0 (void *__addr, data512_t __value)
|
|
||||||
{
|
|
||||||
return __builtin_aarch64_st64bv0 (__addr, __value);
|
|
||||||
}
|
|
||||||
#pragma GCC pop_options
|
|
||||||
#endif
|
#endif
|
||||||
#pragma GCC push_options
|
#pragma GCC push_options
|
||||||
#pragma GCC target ("+nothing+rng")
|
#pragma GCC target ("+nothing+rng")
|
||||||
|
@ -233,7 +232,7 @@ __rndrrs (uint64_t *__res)
|
||||||
}
|
}
|
||||||
#pragma GCC pop_options
|
#pragma GCC pop_options
|
||||||
#pragma GCC push_options
|
#pragma GCC push_options
|
||||||
#pragma GCC target ("arch=armv8.5-a+memtag")
|
#pragma GCC target ("+nothing+memtag")
|
||||||
#define __arm_mte_create_random_tag(__ptr, __u64_mask) __builtin_aarch64_memtag_irg(__ptr, __u64_mask)
|
#define __arm_mte_create_random_tag(__ptr, __u64_mask) __builtin_aarch64_memtag_irg(__ptr, __u64_mask)
|
||||||
#define __arm_mte_exclude_tag(__ptr, __u64_excluded) __builtin_aarch64_memtag_gmi(__ptr, __u64_excluded)
|
#define __arm_mte_exclude_tag(__ptr, __u64_excluded) __builtin_aarch64_memtag_gmi(__ptr, __u64_excluded)
|
||||||
#define __arm_mte_ptrdiff(__ptr_a, __ptr_b) __builtin_aarch64_memtag_subp(__ptr_a, __ptr_b)
|
#define __arm_mte_ptrdiff(__ptr_a, __ptr_b) __builtin_aarch64_memtag_subp(__ptr_a, __ptr_b)
|
||||||
|
@ -241,6 +240,21 @@ __rndrrs (uint64_t *__res)
|
||||||
#define __arm_mte_set_tag(__tagged_address) __builtin_aarch64_memtag_set_tag(__tagged_address)
|
#define __arm_mte_set_tag(__tagged_address) __builtin_aarch64_memtag_set_tag(__tagged_address)
|
||||||
#define __arm_mte_get_tag(__address) __builtin_aarch64_memtag_get_tag(__address)
|
#define __arm_mte_get_tag(__address) __builtin_aarch64_memtag_get_tag(__address)
|
||||||
#pragma GCC pop_options
|
#pragma GCC pop_options
|
||||||
|
#define __arm_rsr(__regname) __builtin_aarch64_rsr (__regname)
|
||||||
|
#define __arm_rsrp(__regname) __builtin_aarch64_rsrp (__regname)
|
||||||
|
#define __arm_rsr64(__regname) __builtin_aarch64_rsr64 (__regname)
|
||||||
|
#define __arm_rsrf(__regname) __builtin_aarch64_rsrf (__regname)
|
||||||
|
#define __arm_rsrf64(__regname) __builtin_aarch64_rsrf64 (__regname)
|
||||||
|
#define __arm_wsr(__regname, __value) __builtin_aarch64_wsr (__regname, __value)
|
||||||
|
#define __arm_wsrp(__regname, __value) __builtin_aarch64_wsrp (__regname, __value)
|
||||||
|
#define __arm_wsr64(__regname, __value) __builtin_aarch64_wsr64 (__regname, __value)
|
||||||
|
#define __arm_wsrf(__regname, __value) __builtin_aarch64_wsrf (__regname, __value)
|
||||||
|
#define __arm_wsrf64(__regname, __value) __builtin_aarch64_wsrf64 (__regname, __value)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target ("+nothing+d128")
|
||||||
|
#define __arm_rsr128(__regname) __builtin_aarch64_rsr128 (__regname)
|
||||||
|
#define __arm_wsr128(__regname, __value) __builtin_aarch64_wsr128 (__regname, __value)
|
||||||
|
#pragma GCC pop_options
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
4
third_party/aarch64/arm_fp16.internal.h
vendored
4
third_party/aarch64/arm_fp16.internal.h
vendored
|
@ -2,7 +2,7 @@
|
||||||
#ifndef _AARCH64_FP16_H_
|
#ifndef _AARCH64_FP16_H_
|
||||||
#define _AARCH64_FP16_H_
|
#define _AARCH64_FP16_H_
|
||||||
#pragma GCC push_options
|
#pragma GCC push_options
|
||||||
#pragma GCC target ("arch=armv8.2-a+fp16")
|
#pragma GCC target ("+nothing+fp16")
|
||||||
typedef __fp16 float16_t;
|
typedef __fp16 float16_t;
|
||||||
__extension__ extern __inline float16_t
|
__extension__ extern __inline float16_t
|
||||||
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
||||||
|
@ -260,7 +260,7 @@ __extension__ extern __inline float16_t
|
||||||
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
||||||
vnegh_f16 (float16_t __a)
|
vnegh_f16 (float16_t __a)
|
||||||
{
|
{
|
||||||
return __builtin_aarch64_neghf (__a);
|
return -__a;
|
||||||
}
|
}
|
||||||
__extension__ extern __inline float16_t
|
__extension__ extern __inline float16_t
|
||||||
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
|
||||||
|
|
2971
third_party/aarch64/arm_neon.internal.h
vendored
2971
third_party/aarch64/arm_neon.internal.h
vendored
File diff suppressed because it is too large
Load diff
111
third_party/aarch64/openacc.internal.h
vendored
111
third_party/aarch64/openacc.internal.h
vendored
|
@ -1,111 +0,0 @@
|
||||||
#if defined(__aarch64__) && !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
||||||
#ifndef _OPENACC_H
|
|
||||||
#define _OPENACC_H 1
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
#if __cplusplus >= 201103
|
|
||||||
# define __GOACC_NOTHROW noexcept
|
|
||||||
#elif __cplusplus
|
|
||||||
# define __GOACC_NOTHROW throw ()
|
|
||||||
#else
|
|
||||||
# define __GOACC_NOTHROW __attribute__ ((__nothrow__))
|
|
||||||
#endif
|
|
||||||
typedef enum acc_device_t {
|
|
||||||
acc_device_current = -1,
|
|
||||||
acc_device_none = 0,
|
|
||||||
acc_device_default = 1,
|
|
||||||
acc_device_host = 2,
|
|
||||||
acc_device_not_host = 4,
|
|
||||||
acc_device_nvidia = 5,
|
|
||||||
acc_device_radeon = 8,
|
|
||||||
_ACC_device_hwm,
|
|
||||||
_ACC_highest = __INT_MAX__,
|
|
||||||
_ACC_neg = -1
|
|
||||||
} acc_device_t;
|
|
||||||
typedef enum acc_device_property_t {
|
|
||||||
acc_property_memory = 1,
|
|
||||||
acc_property_free_memory = 2,
|
|
||||||
acc_property_name = 0x10001,
|
|
||||||
acc_property_vendor = 0x10002,
|
|
||||||
acc_property_driver = 0x10003
|
|
||||||
} acc_device_property_t;
|
|
||||||
typedef enum acc_async_t {
|
|
||||||
acc_async_noval = -1,
|
|
||||||
acc_async_sync = -2
|
|
||||||
} acc_async_t;
|
|
||||||
int acc_get_num_devices (acc_device_t) __GOACC_NOTHROW;
|
|
||||||
void acc_set_device_type (acc_device_t) __GOACC_NOTHROW;
|
|
||||||
acc_device_t acc_get_device_type (void) __GOACC_NOTHROW;
|
|
||||||
void acc_set_device_num (int, acc_device_t) __GOACC_NOTHROW;
|
|
||||||
int acc_get_device_num (acc_device_t) __GOACC_NOTHROW;
|
|
||||||
size_t acc_get_property
|
|
||||||
(int, acc_device_t, acc_device_property_t) __GOACC_NOTHROW;
|
|
||||||
const char *acc_get_property_string
|
|
||||||
(int, acc_device_t, acc_device_property_t) __GOACC_NOTHROW;
|
|
||||||
int acc_async_test (int) __GOACC_NOTHROW;
|
|
||||||
int acc_async_test_all (void) __GOACC_NOTHROW;
|
|
||||||
void acc_wait (int) __GOACC_NOTHROW;
|
|
||||||
void acc_async_wait (int) __GOACC_NOTHROW;
|
|
||||||
void acc_wait_async (int, int) __GOACC_NOTHROW;
|
|
||||||
void acc_wait_all (void) __GOACC_NOTHROW;
|
|
||||||
void acc_async_wait_all (void) __GOACC_NOTHROW;
|
|
||||||
void acc_wait_all_async (int) __GOACC_NOTHROW;
|
|
||||||
void acc_init (acc_device_t) __GOACC_NOTHROW;
|
|
||||||
void acc_shutdown (acc_device_t) __GOACC_NOTHROW;
|
|
||||||
#ifdef __cplusplus
|
|
||||||
int acc_on_device (int __arg) __GOACC_NOTHROW;
|
|
||||||
#else
|
|
||||||
int acc_on_device (acc_device_t __arg) __GOACC_NOTHROW;
|
|
||||||
#endif
|
|
||||||
void *acc_malloc (size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_free (void *) __GOACC_NOTHROW;
|
|
||||||
void *acc_copyin (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void *acc_present_or_copyin (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void *acc_pcopyin (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void *acc_create (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void *acc_present_or_create (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void *acc_pcreate (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_copyout (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_delete (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_update_device (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_update_self (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_map_data (void *, void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_unmap_data (void *) __GOACC_NOTHROW;
|
|
||||||
void *acc_deviceptr (void *) __GOACC_NOTHROW;
|
|
||||||
void *acc_hostptr (void *) __GOACC_NOTHROW;
|
|
||||||
int acc_is_present (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_memcpy_to_device (void *, void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_memcpy_from_device (void *, void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_attach (void **) __GOACC_NOTHROW;
|
|
||||||
void acc_attach_async (void **, int) __GOACC_NOTHROW;
|
|
||||||
void acc_detach (void **) __GOACC_NOTHROW;
|
|
||||||
void acc_detach_async (void **, int) __GOACC_NOTHROW;
|
|
||||||
void acc_copyout_finalize (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_copyout_finalize_async (void *, size_t, int) __GOACC_NOTHROW;
|
|
||||||
void acc_delete_finalize (void *, size_t) __GOACC_NOTHROW;
|
|
||||||
void acc_delete_finalize_async (void *, size_t, int) __GOACC_NOTHROW;
|
|
||||||
void acc_detach_finalize (void **) __GOACC_NOTHROW;
|
|
||||||
void acc_detach_finalize_async (void **, int) __GOACC_NOTHROW;
|
|
||||||
void acc_copyin_async (void *, size_t, int) __GOACC_NOTHROW;
|
|
||||||
void acc_create_async (void *, size_t, int) __GOACC_NOTHROW;
|
|
||||||
void acc_copyout_async (void *, size_t, int) __GOACC_NOTHROW;
|
|
||||||
void acc_delete_async (void *, size_t, int) __GOACC_NOTHROW;
|
|
||||||
void acc_update_device_async (void *, size_t, int) __GOACC_NOTHROW;
|
|
||||||
void acc_update_self_async (void *, size_t, int) __GOACC_NOTHROW;
|
|
||||||
void acc_memcpy_to_device_async (void *, void *, size_t, int) __GOACC_NOTHROW;
|
|
||||||
void acc_memcpy_from_device_async (void *, void *, size_t, int) __GOACC_NOTHROW;
|
|
||||||
void *acc_get_current_cuda_device (void) __GOACC_NOTHROW;
|
|
||||||
void *acc_get_current_cuda_context (void) __GOACC_NOTHROW;
|
|
||||||
void *acc_get_cuda_stream (int) __GOACC_NOTHROW;
|
|
||||||
int acc_set_cuda_stream (int, void *) __GOACC_NOTHROW;
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#pragma acc routine seq
|
|
||||||
inline int acc_on_device (acc_device_t __arg) __GOACC_NOTHROW
|
|
||||||
{
|
|
||||||
return acc_on_device ((int) __arg);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
4
third_party/aarch64/upgrade.sh
vendored
4
third_party/aarch64/upgrade.sh
vendored
|
@ -13,17 +13,15 @@
|
||||||
# 3. You should fix up the `#pragma GCC aarch64` things.
|
# 3. You should fix up the `#pragma GCC aarch64` things.
|
||||||
#
|
#
|
||||||
|
|
||||||
s=/opt/goodies/include
|
s=/opt/include
|
||||||
d=third_party/aarch64
|
d=third_party/aarch64
|
||||||
|
|
||||||
FILES='
|
FILES='
|
||||||
acc_prof
|
|
||||||
arm_acle
|
arm_acle
|
||||||
arm_bf16
|
arm_bf16
|
||||||
arm_fp16
|
arm_fp16
|
||||||
arm_neon
|
arm_neon
|
||||||
arm_sve
|
arm_sve
|
||||||
openacc
|
|
||||||
'
|
'
|
||||||
|
|
||||||
strip_c_comments() {
|
strip_c_comments() {
|
||||||
|
|
99
third_party/bash/BUILD.mk
vendored
99
third_party/bash/BUILD.mk
vendored
|
@ -1,99 +0,0 @@
|
||||||
#-*-mode:bashfile-gbash;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
|
||||||
#── vi: set noet ft=bash ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
|
|
||||||
|
|
||||||
PKGS += THIRD_PARTY_BASH
|
|
||||||
|
|
||||||
THIRD_PARTY_BASH_A = o/$(MODE)/third_party/bash/bash.a
|
|
||||||
THIRD_PARTY_BASH_FILES := $(wildcard third_party/bash/*)
|
|
||||||
THIRD_PARTY_BASH_HDRS = $(filter %.h,$(THIRD_PARTY_BASH_FILES))
|
|
||||||
THIRD_PARTY_BASH_INCS = $(filter %.inc,$(THIRD_PARTY_BASH_FILES))
|
|
||||||
THIRD_PARTY_BASH_SRCS = $(filter %.c,$(THIRD_PARTY_BASH_FILES))
|
|
||||||
THIRD_PARTY_BASH_OBJS = $(THIRD_PARTY_BASH_SRCS:%.c=o/$(MODE)/%.o)
|
|
||||||
THIRD_PARTY_BASH_COMS = o/$(MODE)/third_party/bash/bash
|
|
||||||
THIRD_PARTY_BASH_CHECKS = $(THIRD_PARTY_BASH_A).pkg
|
|
||||||
|
|
||||||
THIRD_PARTY_BASH_BINS = \
|
|
||||||
$(THIRD_PARTY_BASH_COMS) \
|
|
||||||
$(THIRD_PARTY_BASH_COMS:%=%.dbg)
|
|
||||||
|
|
||||||
THIRD_PARTY_BASH_DIRECTDEPS = \
|
|
||||||
LIBC_CALLS \
|
|
||||||
LIBC_FMT \
|
|
||||||
LIBC_INTRIN \
|
|
||||||
LIBC_MEM \
|
|
||||||
LIBC_NEXGEN32E \
|
|
||||||
LIBC_PROC \
|
|
||||||
LIBC_RUNTIME \
|
|
||||||
LIBC_SOCK \
|
|
||||||
LIBC_STDIO \
|
|
||||||
LIBC_STR \
|
|
||||||
LIBC_SYSV \
|
|
||||||
LIBC_THREAD \
|
|
||||||
THIRD_PARTY_COMPILER_RT \
|
|
||||||
THIRD_PARTY_GDTOA \
|
|
||||||
THIRD_PARTY_GETOPT \
|
|
||||||
THIRD_PARTY_MUSL \
|
|
||||||
THIRD_PARTY_NCURSES \
|
|
||||||
THIRD_PARTY_READLINE \
|
|
||||||
THIRD_PARTY_REGEX \
|
|
||||||
THIRD_PARTY_TZ
|
|
||||||
|
|
||||||
THIRD_PARTY_BASH_DEPS := \
|
|
||||||
$(call uniq,$(foreach x,$(THIRD_PARTY_BASH_DIRECTDEPS),$($(x))))
|
|
||||||
|
|
||||||
$(THIRD_PARTY_BASH_A).pkg: \
|
|
||||||
$(THIRD_PARTY_BASH_OBJS) \
|
|
||||||
$(foreach x,$(THIRD_PARTY_BASH_DIRECTDEPS),$($(x)_A).pkg)
|
|
||||||
|
|
||||||
$(THIRD_PARTY_BASH_A): \
|
|
||||||
third_party/bash/ \
|
|
||||||
$(THIRD_PARTY_BASH_A).pkg \
|
|
||||||
$(filter-out %main.o,$(THIRD_PARTY_BASH_OBJS))
|
|
||||||
|
|
||||||
o/$(MODE)/third_party/bash/bash.dbg: \
|
|
||||||
$(THIRD_PARTY_BASH_DEPS) \
|
|
||||||
$(THIRD_PARTY_BASH_A) \
|
|
||||||
$(THIRD_PARTY_BASH_A).pkg \
|
|
||||||
o/$(MODE)/third_party/bash/shell.o \
|
|
||||||
$(CRT) \
|
|
||||||
$(APE_NO_MODIFY_SELF)
|
|
||||||
@$(APELINK)
|
|
||||||
|
|
||||||
$(THIRD_PARTY_BASH_OBJS): private \
|
|
||||||
CPPFLAGS += \
|
|
||||||
-DHAVE_CONFIG_H \
|
|
||||||
-DSHELL \
|
|
||||||
-DPACKAGE=\"bash\" \
|
|
||||||
-DLOCALEDIR=\"/zip/usr/share/locale\" \
|
|
||||||
-DCONF_HOSTTYPE=\"unknown\" \
|
|
||||||
-DCONF_OSTYPE=\"linux-cosmo\" \
|
|
||||||
-DCONF_MACHTYPE=\"unknown-pc-unknown-cosmo\" \
|
|
||||||
-DCONF_VENDOR=\"pc\"
|
|
||||||
|
|
||||||
$(THIRD_PARTY_BASH_OBJS): private \
|
|
||||||
CFLAGS += \
|
|
||||||
-Wno-unused-but-set-variable \
|
|
||||||
-Wno-discarded-qualifiers \
|
|
||||||
-Wno-maybe-uninitialized \
|
|
||||||
-Wno-pointer-to-int-cast \
|
|
||||||
-Wno-stringop-truncation \
|
|
||||||
-Wno-format-zero-length \
|
|
||||||
-Wno-format-overflow \
|
|
||||||
-Wno-char-subscripts \
|
|
||||||
-Wno-nonnull-compare \
|
|
||||||
-Wno-unused-variable \
|
|
||||||
-Wno-missing-braces \
|
|
||||||
-Wno-use-after-free \
|
|
||||||
-Wno-unused-label \
|
|
||||||
-Wno-unused-value \
|
|
||||||
-Wno-return-type \
|
|
||||||
-Wno-parentheses \
|
|
||||||
-fportcosmo
|
|
||||||
|
|
||||||
$(THIRD_PARTY_BASH_OBJS): third_party/bash/BUILD.mk
|
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/third_party/bash
|
|
||||||
o/$(MODE)/third_party/bash: \
|
|
||||||
$(THIRD_PARTY_BASH_BINS) \
|
|
||||||
$(THIRD_PARTY_BASH_CHECKS)
|
|
||||||
|
|
674
third_party/bash/LICENSE
vendored
674
third_party/bash/LICENSE
vendored
|
@ -1,674 +0,0 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
|
||||||
software and other kinds of works.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
share and change all versions of a program--to make sure it remains free
|
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
|
||||||
GNU General Public License for most of our software; it applies also to
|
|
||||||
any other work released this way by its authors. You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
|
||||||
or can get the source code. And you must show them these terms so they
|
|
||||||
know their rights.
|
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
|
||||||
that there is no warranty for this free software. For both users' and
|
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
|
||||||
changed, so that their problems will not be attributed erroneously to
|
|
||||||
authors of previous versions.
|
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the special requirements of the GNU Affero General Public License,
|
|
||||||
section 13, concerning interaction through a network will apply to the
|
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
|
||||||
notice like this when it starts in an interactive mode:
|
|
||||||
|
|
||||||
<program> Copyright (C) <year> <name of author>
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
16
third_party/bash/README.cosmo
vendored
16
third_party/bash/README.cosmo
vendored
|
@ -1,16 +0,0 @@
|
||||||
DESCRIPTION
|
|
||||||
|
|
||||||
the bourne again shell
|
|
||||||
|
|
||||||
LICENSE
|
|
||||||
|
|
||||||
GPL v3
|
|
||||||
|
|
||||||
ORIGIN
|
|
||||||
|
|
||||||
https://ftp.gnu.org/gnu/bash/bash-5.2.tar.gz
|
|
||||||
|
|
||||||
LOCAL CHANGES
|
|
||||||
|
|
||||||
- Force disable mkfifo() code
|
|
||||||
- Added runtime check for broken BSD /dev/fd stuff
|
|
594
third_party/bash/alias.c
vendored
594
third_party/bash/alias.c
vendored
|
@ -1,594 +0,0 @@
|
||||||
/* alias.c -- Not a full alias, but just the kind that we use in the
|
|
||||||
shell. Csh style alias is somewhere else (`over there, in a box'). */
|
|
||||||
|
|
||||||
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (ALIAS)
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "chartypes.h"
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "command.h"
|
|
||||||
#include "general.h"
|
|
||||||
#include "externs.h"
|
|
||||||
#include "alias.h"
|
|
||||||
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
# include "pcomplete.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
|
|
||||||
# include <mbstr.h> /* mbschr */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ALIAS_HASH_BUCKETS 64 /* must be power of two */
|
|
||||||
|
|
||||||
typedef int sh_alias_map_func_t PARAMS((alias_t *));
|
|
||||||
|
|
||||||
static void free_alias_data PARAMS((PTR_T));
|
|
||||||
static alias_t **map_over_aliases PARAMS((sh_alias_map_func_t *));
|
|
||||||
static void sort_aliases PARAMS((alias_t **));
|
|
||||||
static int qsort_alias_compare PARAMS((alias_t **, alias_t **));
|
|
||||||
|
|
||||||
#if defined (READLINE)
|
|
||||||
static int skipquotes PARAMS((char *, int));
|
|
||||||
static int skipws PARAMS((char *, int));
|
|
||||||
static int rd_token PARAMS((char *, int));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Non-zero means expand all words on the line. Otherwise, expand
|
|
||||||
after first expansion if the expansion ends in a space. */
|
|
||||||
int alias_expand_all = 0;
|
|
||||||
|
|
||||||
/* The list of aliases that we have. */
|
|
||||||
HASH_TABLE *aliases = (HASH_TABLE *)NULL;
|
|
||||||
|
|
||||||
void
|
|
||||||
initialize_aliases ()
|
|
||||||
{
|
|
||||||
if (aliases == 0)
|
|
||||||
aliases = hash_create (ALIAS_HASH_BUCKETS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scan the list of aliases looking for one with NAME. Return NULL
|
|
||||||
if the alias doesn't exist, else a pointer to the alias_t. */
|
|
||||||
alias_t *
|
|
||||||
find_alias (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
BUCKET_CONTENTS *al;
|
|
||||||
|
|
||||||
if (aliases == 0)
|
|
||||||
return ((alias_t *)NULL);
|
|
||||||
|
|
||||||
al = hash_search (name, aliases, 0);
|
|
||||||
return (al ? (alias_t *)al->data : (alias_t *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the value of the alias for NAME, or NULL if there is none. */
|
|
||||||
char *
|
|
||||||
get_alias_value (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
alias_t *alias;
|
|
||||||
|
|
||||||
if (aliases == 0)
|
|
||||||
return ((char *)NULL);
|
|
||||||
|
|
||||||
alias = find_alias (name);
|
|
||||||
return (alias ? alias->value : (char *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make a new alias from NAME and VALUE. If NAME can be found,
|
|
||||||
then replace its value. */
|
|
||||||
void
|
|
||||||
add_alias (name, value)
|
|
||||||
char *name, *value;
|
|
||||||
{
|
|
||||||
BUCKET_CONTENTS *elt;
|
|
||||||
alias_t *temp;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (aliases == 0)
|
|
||||||
{
|
|
||||||
initialize_aliases ();
|
|
||||||
temp = (alias_t *)NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
temp = find_alias (name);
|
|
||||||
|
|
||||||
if (temp)
|
|
||||||
{
|
|
||||||
free (temp->value);
|
|
||||||
temp->value = savestring (value);
|
|
||||||
temp->flags &= ~AL_EXPANDNEXT;
|
|
||||||
if (value[0])
|
|
||||||
{
|
|
||||||
n = value[strlen (value) - 1];
|
|
||||||
if (n == ' ' || n == '\t')
|
|
||||||
temp->flags |= AL_EXPANDNEXT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
temp = (alias_t *)xmalloc (sizeof (alias_t));
|
|
||||||
temp->name = savestring (name);
|
|
||||||
temp->value = savestring (value);
|
|
||||||
temp->flags = 0;
|
|
||||||
|
|
||||||
if (value[0])
|
|
||||||
{
|
|
||||||
n = value[strlen (value) - 1];
|
|
||||||
if (n == ' ' || n == '\t')
|
|
||||||
temp->flags |= AL_EXPANDNEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
elt = hash_insert (savestring (name), aliases, HASH_NOSRCH);
|
|
||||||
elt->data = temp;
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
set_itemlist_dirty (&it_aliases);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete a single alias structure. */
|
|
||||||
static void
|
|
||||||
free_alias_data (data)
|
|
||||||
PTR_T data;
|
|
||||||
{
|
|
||||||
register alias_t *a;
|
|
||||||
|
|
||||||
a = (alias_t *)data;
|
|
||||||
|
|
||||||
if (a->flags & AL_BEINGEXPANDED)
|
|
||||||
clear_string_list_expander (a); /* call back to the parser */
|
|
||||||
|
|
||||||
free (a->value);
|
|
||||||
free (a->name);
|
|
||||||
free (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the alias with name NAME from the alias table. Returns
|
|
||||||
the number of aliases left in the table, or -1 if the alias didn't
|
|
||||||
exist. */
|
|
||||||
int
|
|
||||||
remove_alias (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
BUCKET_CONTENTS *elt;
|
|
||||||
|
|
||||||
if (aliases == 0)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
elt = hash_remove (name, aliases, 0);
|
|
||||||
if (elt)
|
|
||||||
{
|
|
||||||
free_alias_data (elt->data);
|
|
||||||
free (elt->key); /* alias name */
|
|
||||||
free (elt); /* XXX */
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
set_itemlist_dirty (&it_aliases);
|
|
||||||
#endif
|
|
||||||
return (aliases->nentries);
|
|
||||||
}
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete all aliases. */
|
|
||||||
void
|
|
||||||
delete_all_aliases ()
|
|
||||||
{
|
|
||||||
if (aliases == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
hash_flush (aliases, free_alias_data);
|
|
||||||
hash_dispose (aliases);
|
|
||||||
aliases = (HASH_TABLE *)NULL;
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
set_itemlist_dirty (&it_aliases);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return an array of aliases that satisfy the conditions tested by FUNCTION.
|
|
||||||
If FUNCTION is NULL, return all aliases. */
|
|
||||||
static alias_t **
|
|
||||||
map_over_aliases (function)
|
|
||||||
sh_alias_map_func_t *function;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
register BUCKET_CONTENTS *tlist;
|
|
||||||
alias_t *alias, **list;
|
|
||||||
int list_index;
|
|
||||||
|
|
||||||
i = HASH_ENTRIES (aliases);
|
|
||||||
if (i == 0)
|
|
||||||
return ((alias_t **)NULL);
|
|
||||||
|
|
||||||
list = (alias_t **)xmalloc ((i + 1) * sizeof (alias_t *));
|
|
||||||
for (i = list_index = 0; i < aliases->nbuckets; i++)
|
|
||||||
{
|
|
||||||
for (tlist = hash_items (i, aliases); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
alias = (alias_t *)tlist->data;
|
|
||||||
|
|
||||||
if (!function || (*function) (alias))
|
|
||||||
{
|
|
||||||
list[list_index++] = alias;
|
|
||||||
list[list_index] = (alias_t *)NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (list);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sort_aliases (array)
|
|
||||||
alias_t **array;
|
|
||||||
{
|
|
||||||
qsort (array, strvec_len ((char **)array), sizeof (alias_t *), (QSFUNC *)qsort_alias_compare);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
qsort_alias_compare (as1, as2)
|
|
||||||
alias_t **as1, **as2;
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if ((result = (*as1)->name[0] - (*as2)->name[0]) == 0)
|
|
||||||
result = strcmp ((*as1)->name, (*as2)->name);
|
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a sorted list of all defined aliases */
|
|
||||||
alias_t **
|
|
||||||
all_aliases ()
|
|
||||||
{
|
|
||||||
alias_t **list;
|
|
||||||
|
|
||||||
if (aliases == 0 || HASH_ENTRIES (aliases) == 0)
|
|
||||||
return ((alias_t **)NULL);
|
|
||||||
|
|
||||||
list = map_over_aliases ((sh_alias_map_func_t *)NULL);
|
|
||||||
if (list)
|
|
||||||
sort_aliases (list);
|
|
||||||
return (list);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
alias_expand_word (s)
|
|
||||||
char *s;
|
|
||||||
{
|
|
||||||
alias_t *r;
|
|
||||||
|
|
||||||
r = find_alias (s);
|
|
||||||
return (r ? savestring (r->value) : (char *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Readline support functions -- expand all aliases in a line. */
|
|
||||||
|
|
||||||
#if defined (READLINE)
|
|
||||||
|
|
||||||
/* Return non-zero if CHARACTER is a member of the class of characters
|
|
||||||
that are self-delimiting in the shell (this really means that these
|
|
||||||
characters delimit tokens). */
|
|
||||||
#define self_delimiting(character) (member ((character), " \t\n\r;|&()"))
|
|
||||||
|
|
||||||
/* Return non-zero if CHARACTER is a member of the class of characters
|
|
||||||
that delimit commands in the shell. */
|
|
||||||
#define command_separator(character) (member ((character), "\r\n;|&("))
|
|
||||||
|
|
||||||
/* If this is 1, we are checking the next token read for alias expansion
|
|
||||||
because it is the first word in a command. */
|
|
||||||
static int command_word;
|
|
||||||
|
|
||||||
/* This is for skipping quoted strings in alias expansions. */
|
|
||||||
#define quote_char(c) (((c) == '\'') || ((c) == '"'))
|
|
||||||
|
|
||||||
/* Consume a quoted string from STRING, starting at string[START] (so
|
|
||||||
string[START] is the opening quote character), and return the index
|
|
||||||
of the closing quote character matching the opening quote character.
|
|
||||||
This handles single matching pairs of unquoted quotes; it could afford
|
|
||||||
to be a little smarter... This skips words between balanced pairs of
|
|
||||||
quotes, words where the first character is quoted with a `\', and other
|
|
||||||
backslash-escaped characters. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
skipquotes (string, start)
|
|
||||||
char *string;
|
|
||||||
int start;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
int delimiter = string[start];
|
|
||||||
|
|
||||||
/* i starts at START + 1 because string[START] is the opening quote
|
|
||||||
character. */
|
|
||||||
for (i = start + 1 ; string[i] ; i++)
|
|
||||||
{
|
|
||||||
if (string[i] == '\\')
|
|
||||||
{
|
|
||||||
i++; /* skip backslash-quoted quote characters, too */
|
|
||||||
if (string[i] == 0)
|
|
||||||
break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string[i] == delimiter)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return (i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip the white space and any quoted characters in STRING, starting at
|
|
||||||
START. Return the new index into STRING, after zero or more characters
|
|
||||||
have been skipped. */
|
|
||||||
static int
|
|
||||||
skipws (string, start)
|
|
||||||
char *string;
|
|
||||||
int start;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
int pass_next, backslash_quoted_word;
|
|
||||||
unsigned char peekc;
|
|
||||||
|
|
||||||
/* skip quoted strings, in ' or ", and words in which a character is quoted
|
|
||||||
with a `\'. */
|
|
||||||
i = backslash_quoted_word = pass_next = 0;
|
|
||||||
|
|
||||||
/* Skip leading whitespace (or separator characters), and quoted words.
|
|
||||||
But save it in the output. */
|
|
||||||
|
|
||||||
for (i = start; string[i]; i++)
|
|
||||||
{
|
|
||||||
if (pass_next)
|
|
||||||
{
|
|
||||||
pass_next = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (whitespace (string[i]))
|
|
||||||
{
|
|
||||||
backslash_quoted_word = 0; /* we are no longer in a backslash-quoted word */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string[i] == '\\')
|
|
||||||
{
|
|
||||||
peekc = string[i+1];
|
|
||||||
if (peekc == 0)
|
|
||||||
break;
|
|
||||||
if (ISLETTER (peekc))
|
|
||||||
backslash_quoted_word++; /* this is a backslash-quoted word */
|
|
||||||
else
|
|
||||||
pass_next++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This only handles single pairs of non-escaped quotes. This
|
|
||||||
overloads backslash_quoted_word to also mean that a word like
|
|
||||||
""f is being scanned, so that the quotes will inhibit any expansion
|
|
||||||
of the word. */
|
|
||||||
if (quote_char(string[i]))
|
|
||||||
{
|
|
||||||
i = skipquotes (string, i);
|
|
||||||
/* This could be a line that contains a single quote character,
|
|
||||||
in which case skipquotes () terminates with string[i] == '\0'
|
|
||||||
(the end of the string). Check for that here. */
|
|
||||||
if (string[i] == '\0')
|
|
||||||
break;
|
|
||||||
|
|
||||||
peekc = string[i + 1];
|
|
||||||
if (ISLETTER (peekc))
|
|
||||||
backslash_quoted_word++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we're in the middle of some kind of quoted word, let it
|
|
||||||
pass through. */
|
|
||||||
if (backslash_quoted_word)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* If this character is a shell command separator, then set a hint for
|
|
||||||
alias_expand that the next token is the first word in a command. */
|
|
||||||
|
|
||||||
if (command_separator (string[i]))
|
|
||||||
{
|
|
||||||
command_word++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Characters that may appear in a token. Basically, anything except white
|
|
||||||
space and a token separator. */
|
|
||||||
#define token_char(c) (!((whitespace (string[i]) || self_delimiting (string[i]))))
|
|
||||||
|
|
||||||
/* Read from START in STRING until the next separator character, and return
|
|
||||||
the index of that separator. Skip backslash-quoted characters. Call
|
|
||||||
skipquotes () for quoted strings in the middle or at the end of tokens,
|
|
||||||
so all characters show up (e.g. foo'' and foo""bar) */
|
|
||||||
static int
|
|
||||||
rd_token (string, start)
|
|
||||||
char *string;
|
|
||||||
int start;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
/* From here to next separator character is a token. */
|
|
||||||
for (i = start; string[i] && token_char (string[i]); i++)
|
|
||||||
{
|
|
||||||
if (string[i] == '\\')
|
|
||||||
{
|
|
||||||
i++; /* skip backslash-escaped character */
|
|
||||||
if (string[i] == 0)
|
|
||||||
break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this character is a quote character, we want to call skipquotes
|
|
||||||
to get the whole quoted portion as part of this word. That word
|
|
||||||
will not generally match an alias, even if te unquoted word would
|
|
||||||
have. The presence of the quotes in the token serves then to
|
|
||||||
inhibit expansion. */
|
|
||||||
if (quote_char (string[i]))
|
|
||||||
{
|
|
||||||
i = skipquotes (string, i);
|
|
||||||
/* This could be a line that contains a single quote character,
|
|
||||||
in which case skipquotes () terminates with string[i] == '\0'
|
|
||||||
(the end of the string). Check for that here. */
|
|
||||||
if (string[i] == '\0')
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Now string[i] is the matching quote character, and the
|
|
||||||
quoted portion of the token has been scanned. */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a new line, with any aliases substituted. */
|
|
||||||
char *
|
|
||||||
alias_expand (string)
|
|
||||||
char *string;
|
|
||||||
{
|
|
||||||
register int i, j, start;
|
|
||||||
char *line, *token;
|
|
||||||
int line_len, tl, real_start, expand_next, expand_this_token;
|
|
||||||
alias_t *alias;
|
|
||||||
|
|
||||||
line_len = strlen (string) + 1;
|
|
||||||
line = (char *)xmalloc (line_len);
|
|
||||||
token = (char *)xmalloc (line_len);
|
|
||||||
|
|
||||||
line[0] = i = 0;
|
|
||||||
expand_next = 0;
|
|
||||||
command_word = 1; /* initialized to expand the first word on the line */
|
|
||||||
|
|
||||||
/* Each time through the loop we find the next word in line. If it
|
|
||||||
has an alias, substitute the alias value. If the value ends in ` ',
|
|
||||||
then try again with the next word. Else, if there is no value, or if
|
|
||||||
the value does not end in space, we are done. */
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
|
|
||||||
token[0] = 0;
|
|
||||||
start = i;
|
|
||||||
|
|
||||||
/* Skip white space and quoted characters */
|
|
||||||
i = skipws (string, start);
|
|
||||||
|
|
||||||
if (start == i && string[i] == '\0')
|
|
||||||
{
|
|
||||||
free (token);
|
|
||||||
return (line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy the just-skipped characters into the output string,
|
|
||||||
expanding it if there is not enough room. */
|
|
||||||
j = strlen (line);
|
|
||||||
tl = i - start; /* number of characters just skipped */
|
|
||||||
RESIZE_MALLOCED_BUFFER (line, j, (tl + 1), line_len, (tl + 50));
|
|
||||||
strncpy (line + j, string + start, tl);
|
|
||||||
line[j + tl] = '\0';
|
|
||||||
|
|
||||||
real_start = i;
|
|
||||||
|
|
||||||
command_word = command_word || (command_separator (string[i]));
|
|
||||||
expand_this_token = (command_word || expand_next);
|
|
||||||
expand_next = 0;
|
|
||||||
|
|
||||||
/* Read the next token, and copy it into TOKEN. */
|
|
||||||
start = i;
|
|
||||||
i = rd_token (string, start);
|
|
||||||
|
|
||||||
tl = i - start; /* token length */
|
|
||||||
|
|
||||||
/* If tl == 0, but we're not at the end of the string, then we have a
|
|
||||||
single-character token, probably a delimiter */
|
|
||||||
if (tl == 0 && string[i] != '\0')
|
|
||||||
{
|
|
||||||
tl = 1;
|
|
||||||
i++; /* move past it */
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy (token, string + start, tl);
|
|
||||||
token [tl] = '\0';
|
|
||||||
|
|
||||||
/* If there is a backslash-escaped character quoted in TOKEN,
|
|
||||||
then we don't do alias expansion. This should check for all
|
|
||||||
other quoting characters, too. */
|
|
||||||
if (mbschr (token, '\\'))
|
|
||||||
expand_this_token = 0;
|
|
||||||
|
|
||||||
/* If we should be expanding here, if we are expanding all words, or if
|
|
||||||
we are in a location in the string where an expansion is supposed to
|
|
||||||
take place, see if this word has a substitution. If it does, then do
|
|
||||||
the expansion. Note that we defer the alias value lookup until we
|
|
||||||
are sure we are expanding this token. */
|
|
||||||
|
|
||||||
if ((token[0]) &&
|
|
||||||
(expand_this_token || alias_expand_all) &&
|
|
||||||
(alias = find_alias (token)))
|
|
||||||
{
|
|
||||||
char *v;
|
|
||||||
int vlen, llen;
|
|
||||||
|
|
||||||
v = alias->value;
|
|
||||||
vlen = strlen (v);
|
|
||||||
llen = strlen (line);
|
|
||||||
|
|
||||||
/* +3 because we possibly add one more character below. */
|
|
||||||
RESIZE_MALLOCED_BUFFER (line, llen, (vlen + 3), line_len, (vlen + 50));
|
|
||||||
|
|
||||||
strcpy (line + llen, v);
|
|
||||||
|
|
||||||
if ((expand_this_token && vlen && whitespace (v[vlen - 1])) ||
|
|
||||||
alias_expand_all)
|
|
||||||
expand_next = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int llen, tlen;
|
|
||||||
|
|
||||||
llen = strlen (line);
|
|
||||||
tlen = i - real_start; /* tlen == strlen(token) */
|
|
||||||
|
|
||||||
RESIZE_MALLOCED_BUFFER (line, llen, (tlen + 1), line_len, (llen + tlen + 50));
|
|
||||||
|
|
||||||
strncpy (line + llen, string + real_start, tlen);
|
|
||||||
line[llen + tlen] = '\0';
|
|
||||||
}
|
|
||||||
command_word = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* READLINE */
|
|
||||||
#endif /* ALIAS */
|
|
73
third_party/bash/alias.h
vendored
73
third_party/bash/alias.h
vendored
|
@ -1,73 +0,0 @@
|
||||||
/* alias.h -- structure definitions. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined (_ALIAS_H_)
|
|
||||||
#define _ALIAS_H_
|
|
||||||
|
|
||||||
#include "stdc.h"
|
|
||||||
|
|
||||||
#include "hashlib.h"
|
|
||||||
|
|
||||||
typedef struct alias {
|
|
||||||
char *name;
|
|
||||||
char *value;
|
|
||||||
char flags;
|
|
||||||
} alias_t;
|
|
||||||
|
|
||||||
/* Values for `flags' member of struct alias. */
|
|
||||||
#define AL_EXPANDNEXT 0x1
|
|
||||||
#define AL_BEINGEXPANDED 0x2
|
|
||||||
|
|
||||||
/* The list of known aliases. */
|
|
||||||
extern HASH_TABLE *aliases;
|
|
||||||
|
|
||||||
extern void initialize_aliases PARAMS((void));
|
|
||||||
|
|
||||||
/* Scan the list of aliases looking for one with NAME. Return NULL
|
|
||||||
if the alias doesn't exist, else a pointer to the alias. */
|
|
||||||
extern alias_t *find_alias PARAMS((char *));
|
|
||||||
|
|
||||||
/* Return the value of the alias for NAME, or NULL if there is none. */
|
|
||||||
extern char *get_alias_value PARAMS((char *));
|
|
||||||
|
|
||||||
/* Make a new alias from NAME and VALUE. If NAME can be found,
|
|
||||||
then replace its value. */
|
|
||||||
extern void add_alias PARAMS((char *, char *));
|
|
||||||
|
|
||||||
/* Remove the alias with name NAME from the alias list. Returns
|
|
||||||
the index of the removed alias, or -1 if the alias didn't exist. */
|
|
||||||
extern int remove_alias PARAMS((char *));
|
|
||||||
|
|
||||||
/* Remove all aliases. */
|
|
||||||
extern void delete_all_aliases PARAMS((void));
|
|
||||||
|
|
||||||
/* Return an array of all defined aliases. */
|
|
||||||
extern alias_t **all_aliases PARAMS((void));
|
|
||||||
|
|
||||||
/* Expand a single word for aliases. */
|
|
||||||
extern char *alias_expand_word PARAMS((char *));
|
|
||||||
|
|
||||||
/* Return a new line, with any aliases expanded. */
|
|
||||||
extern char *alias_expand PARAMS((char *));
|
|
||||||
|
|
||||||
/* Helper definition for the parser */
|
|
||||||
extern void clear_string_list_expander PARAMS((alias_t *));
|
|
||||||
|
|
||||||
#endif /* _ALIAS_H_ */
|
|
54
third_party/bash/ansi_stdlib.h
vendored
54
third_party/bash/ansi_stdlib.h
vendored
|
@ -1,54 +0,0 @@
|
||||||
/* ansi_stdlib.h -- An ANSI Standard stdlib.h. */
|
|
||||||
/* A minimal stdlib.h containing extern declarations for those functions
|
|
||||||
that bash uses. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1993 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined (_STDLIB_H_)
|
|
||||||
#define _STDLIB_H_ 1
|
|
||||||
|
|
||||||
/* String conversion functions. */
|
|
||||||
extern int atoi ();
|
|
||||||
|
|
||||||
extern double atof ();
|
|
||||||
extern double strtod ();
|
|
||||||
|
|
||||||
/* Memory allocation functions. */
|
|
||||||
/* Generic pointer type. */
|
|
||||||
#ifndef PTR_T
|
|
||||||
|
|
||||||
#if defined (__STDC__)
|
|
||||||
# define PTR_T void *
|
|
||||||
#else
|
|
||||||
# define PTR_T char *
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* PTR_T */
|
|
||||||
|
|
||||||
extern PTR_T malloc ();
|
|
||||||
extern PTR_T realloc ();
|
|
||||||
extern void free ();
|
|
||||||
|
|
||||||
/* Other miscellaneous functions. */
|
|
||||||
extern void abort ();
|
|
||||||
extern void exit ();
|
|
||||||
extern char *getenv ();
|
|
||||||
extern void qsort ();
|
|
||||||
|
|
||||||
#endif /* _STDLIB_H */
|
|
1303
third_party/bash/array.c
vendored
1303
third_party/bash/array.c
vendored
File diff suppressed because it is too large
Load diff
182
third_party/bash/array.h
vendored
182
third_party/bash/array.h
vendored
|
@ -1,182 +0,0 @@
|
||||||
/* array.h -- definitions for the interface exported by array.c that allows
|
|
||||||
the rest of the shell to manipulate array variables. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1997-2021 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _ARRAY_H_
|
|
||||||
#define _ARRAY_H_
|
|
||||||
|
|
||||||
#include "stdc.h"
|
|
||||||
|
|
||||||
typedef intmax_t arrayind_t;
|
|
||||||
|
|
||||||
typedef struct array {
|
|
||||||
arrayind_t max_index;
|
|
||||||
arrayind_t num_elements;
|
|
||||||
#ifdef ALT_ARRAY_IMPLEMENTATION
|
|
||||||
arrayind_t first_index;
|
|
||||||
arrayind_t alloc_size;
|
|
||||||
struct array_element **elements;
|
|
||||||
#else
|
|
||||||
struct array_element *head;
|
|
||||||
struct array_element *lastref;
|
|
||||||
#endif
|
|
||||||
} ARRAY;
|
|
||||||
|
|
||||||
typedef struct array_element {
|
|
||||||
arrayind_t ind;
|
|
||||||
char *value;
|
|
||||||
#ifndef ALT_ARRAY_IMPLEMENTATION
|
|
||||||
struct array_element *next, *prev;
|
|
||||||
#endif
|
|
||||||
} ARRAY_ELEMENT;
|
|
||||||
|
|
||||||
#define ARRAY_DEFAULT_SIZE 1024
|
|
||||||
|
|
||||||
typedef int sh_ae_map_func_t PARAMS((ARRAY_ELEMENT *, void *));
|
|
||||||
|
|
||||||
/* Basic operations on entire arrays */
|
|
||||||
#ifdef ALT_ARRAY_IMPLEMENTATION
|
|
||||||
extern void array_alloc PARAMS((ARRAY *, arrayind_t));
|
|
||||||
extern void array_resize PARAMS((ARRAY *, arrayind_t));
|
|
||||||
extern void array_expand PARAMS((ARRAY *, arrayind_t));
|
|
||||||
extern void array_dispose_elements PARAMS((ARRAY_ELEMENT **));
|
|
||||||
#endif
|
|
||||||
extern ARRAY *array_create PARAMS((void));
|
|
||||||
extern void array_flush PARAMS((ARRAY *));
|
|
||||||
extern void array_dispose PARAMS((ARRAY *));
|
|
||||||
extern ARRAY *array_copy PARAMS((ARRAY *));
|
|
||||||
#ifndef ALT_ARRAY_IMPLEMENTATION
|
|
||||||
extern ARRAY *array_slice PARAMS((ARRAY *, ARRAY_ELEMENT *, ARRAY_ELEMENT *));
|
|
||||||
#else
|
|
||||||
extern ARRAY *array_slice PARAMS((ARRAY *, arrayind_t, arrayind_t));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void array_walk PARAMS((ARRAY *, sh_ae_map_func_t *, void *));
|
|
||||||
|
|
||||||
#ifndef ALT_ARRAY_IMPLEMENTATION
|
|
||||||
extern ARRAY_ELEMENT *array_shift PARAMS((ARRAY *, int, int));
|
|
||||||
#else
|
|
||||||
extern ARRAY_ELEMENT **array_shift PARAMS((ARRAY *, int, int));
|
|
||||||
#endif
|
|
||||||
extern int array_rshift PARAMS((ARRAY *, int, char *));
|
|
||||||
extern ARRAY_ELEMENT *array_unshift_element PARAMS((ARRAY *));
|
|
||||||
extern int array_shift_element PARAMS((ARRAY *, char *));
|
|
||||||
|
|
||||||
extern ARRAY *array_quote PARAMS((ARRAY *));
|
|
||||||
extern ARRAY *array_quote_escapes PARAMS((ARRAY *));
|
|
||||||
extern ARRAY *array_dequote PARAMS((ARRAY *));
|
|
||||||
extern ARRAY *array_dequote_escapes PARAMS((ARRAY *));
|
|
||||||
extern ARRAY *array_remove_quoted_nulls PARAMS((ARRAY *));
|
|
||||||
|
|
||||||
extern char *array_subrange PARAMS((ARRAY *, arrayind_t, arrayind_t, int, int, int));
|
|
||||||
extern char *array_patsub PARAMS((ARRAY *, char *, char *, int));
|
|
||||||
extern char *array_modcase PARAMS((ARRAY *, char *, int, int));
|
|
||||||
|
|
||||||
/* Basic operations on array elements. */
|
|
||||||
extern ARRAY_ELEMENT *array_create_element PARAMS((arrayind_t, char *));
|
|
||||||
extern ARRAY_ELEMENT *array_copy_element PARAMS((ARRAY_ELEMENT *));
|
|
||||||
extern void array_dispose_element PARAMS((ARRAY_ELEMENT *));
|
|
||||||
|
|
||||||
extern int array_insert PARAMS((ARRAY *, arrayind_t, char *));
|
|
||||||
extern ARRAY_ELEMENT *array_remove PARAMS((ARRAY *, arrayind_t));
|
|
||||||
extern char *array_reference PARAMS((ARRAY *, arrayind_t));
|
|
||||||
|
|
||||||
/* Converting to and from arrays */
|
|
||||||
extern WORD_LIST *array_to_word_list PARAMS((ARRAY *));
|
|
||||||
extern ARRAY *array_from_word_list PARAMS((WORD_LIST *));
|
|
||||||
extern WORD_LIST *array_keys_to_word_list PARAMS((ARRAY *));
|
|
||||||
extern WORD_LIST *array_to_kvpair_list PARAMS((ARRAY *));
|
|
||||||
|
|
||||||
extern ARRAY *array_assign_list PARAMS((ARRAY *, WORD_LIST *));
|
|
||||||
|
|
||||||
extern char **array_to_argv PARAMS((ARRAY *, int *));
|
|
||||||
extern ARRAY *array_from_argv PARAMS((ARRAY *, char **, int));
|
|
||||||
|
|
||||||
extern char *array_to_kvpair PARAMS((ARRAY *, int));
|
|
||||||
extern char *array_to_assign PARAMS((ARRAY *, int));
|
|
||||||
extern char *array_to_string PARAMS((ARRAY *, char *, int));
|
|
||||||
extern ARRAY *array_from_string PARAMS((char *, char *));
|
|
||||||
|
|
||||||
/* Flags for array_shift */
|
|
||||||
#define AS_DISPOSE 0x01
|
|
||||||
|
|
||||||
#define array_num_elements(a) ((a)->num_elements)
|
|
||||||
#define array_max_index(a) ((a)->max_index)
|
|
||||||
#ifndef ALT_ARRAY_IMPLEMENTATION
|
|
||||||
#define array_first_index(a) ((a)->head->next->ind)
|
|
||||||
#define array_head(a) ((a)->head)
|
|
||||||
#define array_alloc_size(a) ((a)->alloc_size)
|
|
||||||
#else
|
|
||||||
#define array_first_index(a) ((a)->first_index)
|
|
||||||
#define array_head(a) ((a)->elements)
|
|
||||||
#endif
|
|
||||||
#define array_empty(a) ((a)->num_elements == 0)
|
|
||||||
|
|
||||||
#define element_value(ae) ((ae)->value)
|
|
||||||
#define element_index(ae) ((ae)->ind)
|
|
||||||
|
|
||||||
#ifndef ALT_ARRAY_IMPLEMENTATION
|
|
||||||
#define element_forw(ae) ((ae)->next)
|
|
||||||
#define element_back(ae) ((ae)->prev)
|
|
||||||
#else
|
|
||||||
extern arrayind_t element_forw PARAMS((ARRAY *, arrayind_t));
|
|
||||||
extern arrayind_t element_back PARAMS((ARRAY *, arrayind_t));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define set_element_value(ae, val) ((ae)->value = (val))
|
|
||||||
|
|
||||||
#ifdef ALT_ARRAY_IMPLEMENTATION
|
|
||||||
#define set_first_index(a, i) ((a)->first_index = (i))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define set_max_index(a, i) ((a)->max_index = (i))
|
|
||||||
#define set_num_elements(a, n) ((a)->num_elements = (n))
|
|
||||||
|
|
||||||
/* Convenience */
|
|
||||||
#define array_push(a,v) \
|
|
||||||
do { array_rshift ((a), 1, (v)); } while (0)
|
|
||||||
#define array_pop(a) \
|
|
||||||
do { array_shift ((a), 1, AS_DISPOSE); } while (0)
|
|
||||||
|
|
||||||
#define GET_ARRAY_FROM_VAR(n, v, a) \
|
|
||||||
do { \
|
|
||||||
(v) = find_variable (n); \
|
|
||||||
(a) = ((v) && array_p ((v))) ? array_cell (v) : (ARRAY *)0; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define ARRAY_ELEMENT_REPLACE(ae, v) \
|
|
||||||
do { \
|
|
||||||
free ((ae)->value); \
|
|
||||||
(ae)->value = (v); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#ifdef ALT_ARRAY_IMPLEMENTATION
|
|
||||||
#define ARRAY_VALUE_REPLACE(a, i, v) \
|
|
||||||
ARRAY_ELEMENT_REPLACE((a)->elements[(i)], (v))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ALL_ELEMENT_SUB(c) ((c) == '@' || (c) == '*')
|
|
||||||
|
|
||||||
/* In eval.c, but uses ARRAY * */
|
|
||||||
extern int execute_array_command PARAMS((ARRAY *, void *));
|
|
||||||
|
|
||||||
#endif /* _ARRAY_H_ */
|
|
1699
third_party/bash/arrayfunc.c
vendored
1699
third_party/bash/arrayfunc.c
vendored
File diff suppressed because it is too large
Load diff
140
third_party/bash/arrayfunc.h
vendored
140
third_party/bash/arrayfunc.h
vendored
|
@ -1,140 +0,0 @@
|
||||||
/* arrayfunc.h -- declarations for miscellaneous array functions in arrayfunc.c */
|
|
||||||
|
|
||||||
/* Copyright (C) 2001-2021 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined (_ARRAYFUNC_H_)
|
|
||||||
#define _ARRAYFUNC_H_
|
|
||||||
|
|
||||||
/* Must include variables.h before including this file. */
|
|
||||||
|
|
||||||
/* An object to encapsulate the state of an array element. It can describe
|
|
||||||
an array assignment A[KEY]=VALUE or a[IND]=VALUE depending on TYPE, or
|
|
||||||
for passing array subscript references around, where VALUE would be
|
|
||||||
${a[IND]} or ${A[KEY]}. This is not dependent on ARRAY_VARS so we can
|
|
||||||
use it in function parameters. */
|
|
||||||
|
|
||||||
/* values for `type' field */
|
|
||||||
#define ARRAY_INVALID -1
|
|
||||||
#define ARRAY_SCALAR 0
|
|
||||||
#define ARRAY_INDEXED 1
|
|
||||||
#define ARRAY_ASSOC 2
|
|
||||||
|
|
||||||
/* KEY will contain allocated memory if called through the assign_array_element
|
|
||||||
code path because of how assoc_insert works. */
|
|
||||||
typedef struct element_state
|
|
||||||
{
|
|
||||||
short type; /* assoc or indexed, says which fields are valid */
|
|
||||||
short subtype; /* `*', `@', or something else */
|
|
||||||
arrayind_t ind;
|
|
||||||
char *key; /* can be allocated memory */
|
|
||||||
char *value;
|
|
||||||
} array_eltstate_t;
|
|
||||||
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
|
|
||||||
/* This variable means to not expand associative array subscripts more than
|
|
||||||
once, when performing variable expansion. */
|
|
||||||
extern int assoc_expand_once;
|
|
||||||
|
|
||||||
/* The analog for indexed array subscripts */
|
|
||||||
extern int array_expand_once;
|
|
||||||
|
|
||||||
/* Flags for array_value_internal and callers array_value/get_array_value; also
|
|
||||||
used by array_variable_name and array_variable_part. */
|
|
||||||
#define AV_ALLOWALL 0x001 /* treat a[@] like $@ and a[*] like $* */
|
|
||||||
#define AV_QUOTED 0x002
|
|
||||||
#define AV_USEIND 0x004
|
|
||||||
#define AV_USEVAL 0x008 /* XXX - should move this */
|
|
||||||
#define AV_ASSIGNRHS 0x010 /* no splitting, special case ${a[@]} */
|
|
||||||
#define AV_NOEXPAND 0x020 /* don't run assoc subscripts through word expansion */
|
|
||||||
#define AV_ONEWORD 0x040 /* not used yet */
|
|
||||||
#define AV_ATSTARKEYS 0x080 /* accept a[@] and a[*] but use them as keys, not special values */
|
|
||||||
|
|
||||||
/* Flags for valid_array_reference. Value 1 is reserved for skipsubscript().
|
|
||||||
Also used by unbind_array_element, which is currently the only function
|
|
||||||
that uses VA_ALLOWALL. */
|
|
||||||
#define VA_NOEXPAND 0x001
|
|
||||||
#define VA_ONEWORD 0x002
|
|
||||||
#define VA_ALLOWALL 0x004 /* allow @ to mean all elements of the array */
|
|
||||||
|
|
||||||
extern SHELL_VAR *convert_var_to_array PARAMS((SHELL_VAR *));
|
|
||||||
extern SHELL_VAR *convert_var_to_assoc PARAMS((SHELL_VAR *));
|
|
||||||
|
|
||||||
extern char *make_array_variable_value PARAMS((SHELL_VAR *, arrayind_t, char *, char *, int));
|
|
||||||
|
|
||||||
extern SHELL_VAR *bind_array_variable PARAMS((char *, arrayind_t, char *, int));
|
|
||||||
extern SHELL_VAR *bind_array_element PARAMS((SHELL_VAR *, arrayind_t, char *, int));
|
|
||||||
extern SHELL_VAR *assign_array_element PARAMS((char *, char *, int, array_eltstate_t *));
|
|
||||||
|
|
||||||
extern SHELL_VAR *bind_assoc_variable PARAMS((SHELL_VAR *, char *, char *, char *, int));
|
|
||||||
|
|
||||||
extern SHELL_VAR *find_or_make_array_variable PARAMS((char *, int));
|
|
||||||
|
|
||||||
extern SHELL_VAR *assign_array_from_string PARAMS((char *, char *, int));
|
|
||||||
extern SHELL_VAR *assign_array_var_from_word_list PARAMS((SHELL_VAR *, WORD_LIST *, int));
|
|
||||||
|
|
||||||
extern WORD_LIST *expand_compound_array_assignment PARAMS((SHELL_VAR *, char *, int));
|
|
||||||
extern void assign_compound_array_list PARAMS((SHELL_VAR *, WORD_LIST *, int));
|
|
||||||
extern SHELL_VAR *assign_array_var_from_string PARAMS((SHELL_VAR *, char *, int));
|
|
||||||
|
|
||||||
extern char *expand_and_quote_assoc_word PARAMS((char *, int));
|
|
||||||
extern void quote_compound_array_list PARAMS((WORD_LIST *, int));
|
|
||||||
|
|
||||||
extern int kvpair_assignment_p PARAMS((WORD_LIST *));
|
|
||||||
extern char *expand_and_quote_kvpair_word PARAMS((char *));
|
|
||||||
|
|
||||||
extern int unbind_array_element PARAMS((SHELL_VAR *, char *, int));
|
|
||||||
extern int skipsubscript PARAMS((const char *, int, int));
|
|
||||||
|
|
||||||
extern void print_array_assignment PARAMS((SHELL_VAR *, int));
|
|
||||||
extern void print_assoc_assignment PARAMS((SHELL_VAR *, int));
|
|
||||||
|
|
||||||
extern arrayind_t array_expand_index PARAMS((SHELL_VAR *, char *, int, int));
|
|
||||||
extern int valid_array_reference PARAMS((const char *, int));
|
|
||||||
extern int tokenize_array_reference PARAMS((char *, int, char **));
|
|
||||||
|
|
||||||
extern char *array_value PARAMS((const char *, int, int, array_eltstate_t *));
|
|
||||||
extern char *get_array_value PARAMS((const char *, int, array_eltstate_t *));
|
|
||||||
|
|
||||||
extern char *array_keys PARAMS((char *, int, int));
|
|
||||||
|
|
||||||
extern char *array_variable_name PARAMS((const char *, int, char **, int *));
|
|
||||||
extern SHELL_VAR *array_variable_part PARAMS((const char *, int, char **, int *));
|
|
||||||
|
|
||||||
extern void init_eltstate (array_eltstate_t *);
|
|
||||||
extern void flush_eltstate (array_eltstate_t *);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define AV_ALLOWALL 0
|
|
||||||
#define AV_QUOTED 0
|
|
||||||
#define AV_USEIND 0
|
|
||||||
#define AV_USEVAL 0
|
|
||||||
#define AV_ASSIGNRHS 0
|
|
||||||
#define AV_NOEXPAND 0
|
|
||||||
#define AV_ONEWORD 0
|
|
||||||
#define AV_ATSTARKEYS 0
|
|
||||||
|
|
||||||
#define VA_NOEXPAND 0
|
|
||||||
#define VA_ONEWORD 0
|
|
||||||
#define VA_ALLOWALL 0
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !_ARRAYFUNC_H_ */
|
|
611
third_party/bash/assoc.c
vendored
611
third_party/bash/assoc.c
vendored
|
@ -1,611 +0,0 @@
|
||||||
/*
|
|
||||||
* assoc.c - functions to manipulate associative arrays
|
|
||||||
*
|
|
||||||
* Associative arrays are standard shell hash tables.
|
|
||||||
*
|
|
||||||
* Chet Ramey
|
|
||||||
* chet@ins.cwru.edu
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Copyright (C) 2008,2009,2011-2021 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "bashansi.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "array.h"
|
|
||||||
#include "assoc.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
static WORD_LIST *assoc_to_word_list_internal PARAMS((HASH_TABLE *, int));
|
|
||||||
|
|
||||||
/* assoc_create == hash_create */
|
|
||||||
|
|
||||||
void
|
|
||||||
assoc_dispose (hash)
|
|
||||||
HASH_TABLE *hash;
|
|
||||||
{
|
|
||||||
if (hash)
|
|
||||||
{
|
|
||||||
hash_flush (hash, 0);
|
|
||||||
hash_dispose (hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
assoc_flush (hash)
|
|
||||||
HASH_TABLE *hash;
|
|
||||||
{
|
|
||||||
hash_flush (hash, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
assoc_insert (hash, key, value)
|
|
||||||
HASH_TABLE *hash;
|
|
||||||
char *key;
|
|
||||||
char *value;
|
|
||||||
{
|
|
||||||
BUCKET_CONTENTS *b;
|
|
||||||
|
|
||||||
b = hash_search (key, hash, HASH_CREATE);
|
|
||||||
if (b == 0)
|
|
||||||
return -1;
|
|
||||||
/* If we are overwriting an existing element's value, we're not going to
|
|
||||||
use the key. Nothing in the array assignment code path frees the key
|
|
||||||
string, so we can free it here to avoid a memory leak. */
|
|
||||||
if (b->key != key)
|
|
||||||
free (key);
|
|
||||||
FREE (b->data);
|
|
||||||
b->data = value ? savestring (value) : (char *)0;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Like assoc_insert, but returns b->data instead of freeing it */
|
|
||||||
PTR_T
|
|
||||||
assoc_replace (hash, key, value)
|
|
||||||
HASH_TABLE *hash;
|
|
||||||
char *key;
|
|
||||||
char *value;
|
|
||||||
{
|
|
||||||
BUCKET_CONTENTS *b;
|
|
||||||
PTR_T t;
|
|
||||||
|
|
||||||
b = hash_search (key, hash, HASH_CREATE);
|
|
||||||
if (b == 0)
|
|
||||||
return (PTR_T)0;
|
|
||||||
/* If we are overwriting an existing element's value, we're not going to
|
|
||||||
use the key. Nothing in the array assignment code path frees the key
|
|
||||||
string, so we can free it here to avoid a memory leak. */
|
|
||||||
if (b->key != key)
|
|
||||||
free (key);
|
|
||||||
t = b->data;
|
|
||||||
b->data = value ? savestring (value) : (char *)0;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
assoc_remove (hash, string)
|
|
||||||
HASH_TABLE *hash;
|
|
||||||
char *string;
|
|
||||||
{
|
|
||||||
BUCKET_CONTENTS *b;
|
|
||||||
|
|
||||||
b = hash_remove (string, hash, 0);
|
|
||||||
if (b)
|
|
||||||
{
|
|
||||||
free ((char *)b->data);
|
|
||||||
free (b->key);
|
|
||||||
free (b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
assoc_reference (hash, string)
|
|
||||||
HASH_TABLE *hash;
|
|
||||||
char *string;
|
|
||||||
{
|
|
||||||
BUCKET_CONTENTS *b;
|
|
||||||
|
|
||||||
if (hash == 0)
|
|
||||||
return (char *)0;
|
|
||||||
|
|
||||||
b = hash_search (string, hash, 0);
|
|
||||||
return (b ? (char *)b->data : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Quote the data associated with each element of the hash table ASSOC,
|
|
||||||
using quote_string */
|
|
||||||
HASH_TABLE *
|
|
||||||
assoc_quote (h)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
BUCKET_CONTENTS *tlist;
|
|
||||||
char *t;
|
|
||||||
|
|
||||||
if (h == 0 || assoc_empty (h))
|
|
||||||
return ((HASH_TABLE *)NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < h->nbuckets; i++)
|
|
||||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
t = quote_string ((char *)tlist->data);
|
|
||||||
FREE (tlist->data);
|
|
||||||
tlist->data = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Quote escape characters in the data associated with each element
|
|
||||||
of the hash table ASSOC, using quote_escapes */
|
|
||||||
HASH_TABLE *
|
|
||||||
assoc_quote_escapes (h)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
BUCKET_CONTENTS *tlist;
|
|
||||||
char *t;
|
|
||||||
|
|
||||||
if (h == 0 || assoc_empty (h))
|
|
||||||
return ((HASH_TABLE *)NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < h->nbuckets; i++)
|
|
||||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
t = quote_escapes ((char *)tlist->data);
|
|
||||||
FREE (tlist->data);
|
|
||||||
tlist->data = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
HASH_TABLE *
|
|
||||||
assoc_dequote (h)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
BUCKET_CONTENTS *tlist;
|
|
||||||
char *t;
|
|
||||||
|
|
||||||
if (h == 0 || assoc_empty (h))
|
|
||||||
return ((HASH_TABLE *)NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < h->nbuckets; i++)
|
|
||||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
t = dequote_string ((char *)tlist->data);
|
|
||||||
FREE (tlist->data);
|
|
||||||
tlist->data = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
HASH_TABLE *
|
|
||||||
assoc_dequote_escapes (h)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
BUCKET_CONTENTS *tlist;
|
|
||||||
char *t;
|
|
||||||
|
|
||||||
if (h == 0 || assoc_empty (h))
|
|
||||||
return ((HASH_TABLE *)NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < h->nbuckets; i++)
|
|
||||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
t = dequote_escapes ((char *)tlist->data);
|
|
||||||
FREE (tlist->data);
|
|
||||||
tlist->data = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
HASH_TABLE *
|
|
||||||
assoc_remove_quoted_nulls (h)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
BUCKET_CONTENTS *tlist;
|
|
||||||
char *t;
|
|
||||||
|
|
||||||
if (h == 0 || assoc_empty (h))
|
|
||||||
return ((HASH_TABLE *)NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < h->nbuckets; i++)
|
|
||||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
t = remove_quoted_nulls ((char *)tlist->data);
|
|
||||||
tlist->data = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a string whose elements are the members of array H beginning at
|
|
||||||
* the STARTth element and spanning NELEM members. Null elements are counted.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
assoc_subrange (hash, start, nelem, starsub, quoted, pflags)
|
|
||||||
HASH_TABLE *hash;
|
|
||||||
arrayind_t start, nelem;
|
|
||||||
int starsub, quoted, pflags;
|
|
||||||
{
|
|
||||||
WORD_LIST *l, *save, *h, *t;
|
|
||||||
int i, j;
|
|
||||||
char *ret;
|
|
||||||
|
|
||||||
if (assoc_empty (hash))
|
|
||||||
return ((char *)NULL);
|
|
||||||
|
|
||||||
save = l = assoc_to_word_list (hash);
|
|
||||||
if (save == 0)
|
|
||||||
return ((char *)NULL);
|
|
||||||
|
|
||||||
for (i = 1; l && i < start; i++)
|
|
||||||
l = l->next;
|
|
||||||
if (l == 0)
|
|
||||||
{
|
|
||||||
dispose_words (save);
|
|
||||||
return ((char *)NULL);
|
|
||||||
}
|
|
||||||
for (j = 0,h = t = l; l && j < nelem; j++)
|
|
||||||
{
|
|
||||||
t = l;
|
|
||||||
l = l->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
t->next = (WORD_LIST *)NULL;
|
|
||||||
|
|
||||||
ret = string_list_pos_params (starsub ? '*' : '@', h, quoted, pflags);
|
|
||||||
|
|
||||||
if (t != l)
|
|
||||||
t->next = l;
|
|
||||||
|
|
||||||
dispose_words (save);
|
|
||||||
return (ret);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
assoc_patsub (h, pat, rep, mflags)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
char *pat, *rep;
|
|
||||||
int mflags;
|
|
||||||
{
|
|
||||||
char *t;
|
|
||||||
int pchar, qflags, pflags;
|
|
||||||
WORD_LIST *wl, *save;
|
|
||||||
|
|
||||||
if (h == 0 || assoc_empty (h))
|
|
||||||
return ((char *)NULL);
|
|
||||||
|
|
||||||
wl = assoc_to_word_list (h);
|
|
||||||
if (wl == 0)
|
|
||||||
return (char *)NULL;
|
|
||||||
|
|
||||||
for (save = wl; wl; wl = wl->next)
|
|
||||||
{
|
|
||||||
t = pat_subst (wl->word->word, pat, rep, mflags);
|
|
||||||
FREE (wl->word->word);
|
|
||||||
wl->word->word = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
|
|
||||||
qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
|
|
||||||
pflags = (mflags & MATCH_ASSIGNRHS) == MATCH_ASSIGNRHS ? PF_ASSIGNRHS : 0;
|
|
||||||
|
|
||||||
t = string_list_pos_params (pchar, save, qflags, pflags);
|
|
||||||
dispose_words (save);
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
assoc_modcase (h, pat, modop, mflags)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
char *pat;
|
|
||||||
int modop;
|
|
||||||
int mflags;
|
|
||||||
{
|
|
||||||
char *t;
|
|
||||||
int pchar, qflags, pflags;
|
|
||||||
WORD_LIST *wl, *save;
|
|
||||||
|
|
||||||
if (h == 0 || assoc_empty (h))
|
|
||||||
return ((char *)NULL);
|
|
||||||
|
|
||||||
wl = assoc_to_word_list (h);
|
|
||||||
if (wl == 0)
|
|
||||||
return ((char *)NULL);
|
|
||||||
|
|
||||||
for (save = wl; wl; wl = wl->next)
|
|
||||||
{
|
|
||||||
t = sh_modcase (wl->word->word, pat, modop);
|
|
||||||
FREE (wl->word->word);
|
|
||||||
wl->word->word = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
|
|
||||||
qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
|
|
||||||
pflags = (mflags & MATCH_ASSIGNRHS) == MATCH_ASSIGNRHS ? PF_ASSIGNRHS : 0;
|
|
||||||
|
|
||||||
t = string_list_pos_params (pchar, save, qflags, pflags);
|
|
||||||
dispose_words (save);
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
assoc_to_kvpair (hash, quoted)
|
|
||||||
HASH_TABLE *hash;
|
|
||||||
int quoted;
|
|
||||||
{
|
|
||||||
char *ret;
|
|
||||||
char *istr, *vstr;
|
|
||||||
int i, rsize, rlen, elen;
|
|
||||||
BUCKET_CONTENTS *tlist;
|
|
||||||
|
|
||||||
if (hash == 0 || assoc_empty (hash))
|
|
||||||
return (char *)0;
|
|
||||||
|
|
||||||
ret = xmalloc (rsize = 128);
|
|
||||||
ret[rlen = 0] = '\0';
|
|
||||||
|
|
||||||
for (i = 0; i < hash->nbuckets; i++)
|
|
||||||
for (tlist = hash_items (i, hash); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
if (ansic_shouldquote (tlist->key))
|
|
||||||
istr = ansic_quote (tlist->key, 0, (int *)0);
|
|
||||||
else if (sh_contains_shell_metas (tlist->key))
|
|
||||||
istr = sh_double_quote (tlist->key);
|
|
||||||
else if (ALL_ELEMENT_SUB (tlist->key[0]) && tlist->key[1] == '\0')
|
|
||||||
istr = sh_double_quote (tlist->key);
|
|
||||||
else
|
|
||||||
istr = tlist->key;
|
|
||||||
|
|
||||||
vstr = tlist->data ? (ansic_shouldquote ((char *)tlist->data) ?
|
|
||||||
ansic_quote ((char *)tlist->data, 0, (int *)0) :
|
|
||||||
sh_double_quote ((char *)tlist->data))
|
|
||||||
: (char *)0;
|
|
||||||
|
|
||||||
elen = STRLEN (istr) + 4 + STRLEN (vstr);
|
|
||||||
RESIZE_MALLOCED_BUFFER (ret, rlen, (elen+1), rsize, rsize);
|
|
||||||
|
|
||||||
strcpy (ret+rlen, istr);
|
|
||||||
rlen += STRLEN (istr);
|
|
||||||
ret[rlen++] = ' ';
|
|
||||||
if (vstr)
|
|
||||||
{
|
|
||||||
strcpy (ret + rlen, vstr);
|
|
||||||
rlen += STRLEN (vstr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strcpy (ret + rlen, "\"\"");
|
|
||||||
rlen += 2;
|
|
||||||
}
|
|
||||||
ret[rlen++] = ' ';
|
|
||||||
|
|
||||||
if (istr != tlist->key)
|
|
||||||
FREE (istr);
|
|
||||||
|
|
||||||
FREE (vstr);
|
|
||||||
}
|
|
||||||
|
|
||||||
RESIZE_MALLOCED_BUFFER (ret, rlen, 1, rsize, 8);
|
|
||||||
ret[rlen] = '\0';
|
|
||||||
|
|
||||||
if (quoted)
|
|
||||||
{
|
|
||||||
vstr = sh_single_quote (ret);
|
|
||||||
free (ret);
|
|
||||||
ret = vstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
assoc_to_assign (hash, quoted)
|
|
||||||
HASH_TABLE *hash;
|
|
||||||
int quoted;
|
|
||||||
{
|
|
||||||
char *ret;
|
|
||||||
char *istr, *vstr;
|
|
||||||
int i, rsize, rlen, elen;
|
|
||||||
BUCKET_CONTENTS *tlist;
|
|
||||||
|
|
||||||
if (hash == 0 || assoc_empty (hash))
|
|
||||||
return (char *)0;
|
|
||||||
|
|
||||||
ret = xmalloc (rsize = 128);
|
|
||||||
ret[0] = '(';
|
|
||||||
rlen = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < hash->nbuckets; i++)
|
|
||||||
for (tlist = hash_items (i, hash); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
if (ansic_shouldquote (tlist->key))
|
|
||||||
istr = ansic_quote (tlist->key, 0, (int *)0);
|
|
||||||
else if (sh_contains_shell_metas (tlist->key))
|
|
||||||
istr = sh_double_quote (tlist->key);
|
|
||||||
else if (ALL_ELEMENT_SUB (tlist->key[0]) && tlist->key[1] == '\0')
|
|
||||||
istr = sh_double_quote (tlist->key);
|
|
||||||
else
|
|
||||||
istr = tlist->key;
|
|
||||||
|
|
||||||
vstr = tlist->data ? (ansic_shouldquote ((char *)tlist->data) ?
|
|
||||||
ansic_quote ((char *)tlist->data, 0, (int *)0) :
|
|
||||||
sh_double_quote ((char *)tlist->data))
|
|
||||||
: (char *)0;
|
|
||||||
|
|
||||||
elen = STRLEN (istr) + 8 + STRLEN (vstr);
|
|
||||||
RESIZE_MALLOCED_BUFFER (ret, rlen, (elen+1), rsize, rsize);
|
|
||||||
|
|
||||||
ret[rlen++] = '[';
|
|
||||||
strcpy (ret+rlen, istr);
|
|
||||||
rlen += STRLEN (istr);
|
|
||||||
ret[rlen++] = ']';
|
|
||||||
ret[rlen++] = '=';
|
|
||||||
if (vstr)
|
|
||||||
{
|
|
||||||
strcpy (ret + rlen, vstr);
|
|
||||||
rlen += STRLEN (vstr);
|
|
||||||
}
|
|
||||||
ret[rlen++] = ' ';
|
|
||||||
|
|
||||||
if (istr != tlist->key)
|
|
||||||
FREE (istr);
|
|
||||||
|
|
||||||
FREE (vstr);
|
|
||||||
}
|
|
||||||
|
|
||||||
RESIZE_MALLOCED_BUFFER (ret, rlen, 1, rsize, 8);
|
|
||||||
ret[rlen++] = ')';
|
|
||||||
ret[rlen] = '\0';
|
|
||||||
|
|
||||||
if (quoted)
|
|
||||||
{
|
|
||||||
vstr = sh_single_quote (ret);
|
|
||||||
free (ret);
|
|
||||||
ret = vstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static WORD_LIST *
|
|
||||||
assoc_to_word_list_internal (h, t)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
int t;
|
|
||||||
{
|
|
||||||
WORD_LIST *list;
|
|
||||||
int i;
|
|
||||||
BUCKET_CONTENTS *tlist;
|
|
||||||
char *w;
|
|
||||||
|
|
||||||
if (h == 0 || assoc_empty (h))
|
|
||||||
return((WORD_LIST *)NULL);
|
|
||||||
list = (WORD_LIST *)NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < h->nbuckets; i++)
|
|
||||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
w = (t == 0) ? (char *)tlist->data : (char *)tlist->key;
|
|
||||||
list = make_word_list (make_bare_word(w), list);
|
|
||||||
}
|
|
||||||
return (REVERSE_LIST(list, WORD_LIST *));
|
|
||||||
}
|
|
||||||
|
|
||||||
WORD_LIST *
|
|
||||||
assoc_to_word_list (h)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
{
|
|
||||||
return (assoc_to_word_list_internal (h, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
WORD_LIST *
|
|
||||||
assoc_keys_to_word_list (h)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
{
|
|
||||||
return (assoc_to_word_list_internal (h, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
WORD_LIST *
|
|
||||||
assoc_to_kvpair_list (h)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
{
|
|
||||||
WORD_LIST *list;
|
|
||||||
int i;
|
|
||||||
BUCKET_CONTENTS *tlist;
|
|
||||||
char *k, *v;
|
|
||||||
|
|
||||||
if (h == 0 || assoc_empty (h))
|
|
||||||
return((WORD_LIST *)NULL);
|
|
||||||
list = (WORD_LIST *)NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < h->nbuckets; i++)
|
|
||||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
k = (char *)tlist->key;
|
|
||||||
v = (char *)tlist->data;
|
|
||||||
list = make_word_list (make_bare_word (k), list);
|
|
||||||
list = make_word_list (make_bare_word (v), list);
|
|
||||||
}
|
|
||||||
return (REVERSE_LIST(list, WORD_LIST *));
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
assoc_to_string (h, sep, quoted)
|
|
||||||
HASH_TABLE *h;
|
|
||||||
char *sep;
|
|
||||||
int quoted;
|
|
||||||
{
|
|
||||||
BUCKET_CONTENTS *tlist;
|
|
||||||
int i;
|
|
||||||
char *result, *t, *w;
|
|
||||||
WORD_LIST *list, *l;
|
|
||||||
|
|
||||||
if (h == 0)
|
|
||||||
return ((char *)NULL);
|
|
||||||
if (assoc_empty (h))
|
|
||||||
return (savestring (""));
|
|
||||||
|
|
||||||
result = NULL;
|
|
||||||
l = list = NULL;
|
|
||||||
/* This might be better implemented directly, but it's simple to implement
|
|
||||||
by converting to a word list first, possibly quoting the data, then
|
|
||||||
using list_string */
|
|
||||||
for (i = 0; i < h->nbuckets; i++)
|
|
||||||
for (tlist = hash_items (i, h); tlist; tlist = tlist->next)
|
|
||||||
{
|
|
||||||
w = (char *)tlist->data;
|
|
||||||
if (w == 0)
|
|
||||||
continue;
|
|
||||||
t = quoted ? quote_string (w) : savestring (w);
|
|
||||||
list = make_word_list (make_bare_word(t), list);
|
|
||||||
FREE (t);
|
|
||||||
}
|
|
||||||
|
|
||||||
l = REVERSE_LIST(list, WORD_LIST *);
|
|
||||||
|
|
||||||
result = l ? string_list_internal (l, sep) : savestring ("");
|
|
||||||
dispose_words (l);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ARRAY_VARS */
|
|
66
third_party/bash/assoc.h
vendored
66
third_party/bash/assoc.h
vendored
|
@ -1,66 +0,0 @@
|
||||||
/* assoc.h -- definitions for the interface exported by assoc.c that allows
|
|
||||||
the rest of the shell to manipulate associative array variables. */
|
|
||||||
|
|
||||||
/* Copyright (C) 2008,2009-2021 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _ASSOC_H_
|
|
||||||
#define _ASSOC_H_
|
|
||||||
|
|
||||||
#include "stdc.h"
|
|
||||||
#include "hashlib.h"
|
|
||||||
|
|
||||||
#define ASSOC_HASH_BUCKETS 1024
|
|
||||||
|
|
||||||
#define assoc_empty(h) ((h)->nentries == 0)
|
|
||||||
#define assoc_num_elements(h) ((h)->nentries)
|
|
||||||
|
|
||||||
#define assoc_create(n) (hash_create((n)))
|
|
||||||
|
|
||||||
#define assoc_copy(h) (hash_copy((h), 0))
|
|
||||||
|
|
||||||
#define assoc_walk(h, f) (hash_walk((h), (f))
|
|
||||||
|
|
||||||
extern void assoc_dispose PARAMS((HASH_TABLE *));
|
|
||||||
extern void assoc_flush PARAMS((HASH_TABLE *));
|
|
||||||
|
|
||||||
extern int assoc_insert PARAMS((HASH_TABLE *, char *, char *));
|
|
||||||
extern PTR_T assoc_replace PARAMS((HASH_TABLE *, char *, char *));
|
|
||||||
extern void assoc_remove PARAMS((HASH_TABLE *, char *));
|
|
||||||
|
|
||||||
extern char *assoc_reference PARAMS((HASH_TABLE *, char *));
|
|
||||||
|
|
||||||
extern char *assoc_subrange PARAMS((HASH_TABLE *, arrayind_t, arrayind_t, int, int, int));
|
|
||||||
extern char *assoc_patsub PARAMS((HASH_TABLE *, char *, char *, int));
|
|
||||||
extern char *assoc_modcase PARAMS((HASH_TABLE *, char *, int, int));
|
|
||||||
|
|
||||||
extern HASH_TABLE *assoc_quote PARAMS((HASH_TABLE *));
|
|
||||||
extern HASH_TABLE *assoc_quote_escapes PARAMS((HASH_TABLE *));
|
|
||||||
extern HASH_TABLE *assoc_dequote PARAMS((HASH_TABLE *));
|
|
||||||
extern HASH_TABLE *assoc_dequote_escapes PARAMS((HASH_TABLE *));
|
|
||||||
extern HASH_TABLE *assoc_remove_quoted_nulls PARAMS((HASH_TABLE *));
|
|
||||||
|
|
||||||
extern char *assoc_to_kvpair PARAMS((HASH_TABLE *, int));
|
|
||||||
extern char *assoc_to_assign PARAMS((HASH_TABLE *, int));
|
|
||||||
|
|
||||||
extern WORD_LIST *assoc_to_word_list PARAMS((HASH_TABLE *));
|
|
||||||
extern WORD_LIST *assoc_keys_to_word_list PARAMS((HASH_TABLE *));
|
|
||||||
extern WORD_LIST *assoc_to_kvpair_list PARAMS((HASH_TABLE *));
|
|
||||||
|
|
||||||
extern char *assoc_to_string PARAMS((HASH_TABLE *, char *, int));
|
|
||||||
#endif /* _ASSOC_H_ */
|
|
38
third_party/bash/bashansi.h
vendored
38
third_party/bash/bashansi.h
vendored
|
@ -1,38 +0,0 @@
|
||||||
/* bashansi.h -- Typically included information required by picky compilers. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1993-2021 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined (_BASHANSI_H_)
|
|
||||||
#define _BASHANSI_H_
|
|
||||||
|
|
||||||
#if defined (HAVE_STRING_H)
|
|
||||||
# include <string.h>
|
|
||||||
#endif /* !HAVE_STRING_H */
|
|
||||||
|
|
||||||
#if defined (HAVE_STRINGS_H)
|
|
||||||
# include <strings.h>
|
|
||||||
#endif /* !HAVE_STRINGS_H */
|
|
||||||
|
|
||||||
#if defined (HAVE_STDLIB_H)
|
|
||||||
# include <stdlib.h>
|
|
||||||
#else
|
|
||||||
# include "ansi_stdlib.h"
|
|
||||||
#endif /* !HAVE_STDLIB_H */
|
|
||||||
|
|
||||||
#endif /* !_BASHANSI_H_ */
|
|
194
third_party/bash/bashgetopt.c
vendored
194
third_party/bash/bashgetopt.c
vendored
|
@ -1,194 +0,0 @@
|
||||||
/* bashgetopt.c -- `getopt' for use by the builtins. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1992-2021 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "chartypes.h"
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
|
|
||||||
#define ISOPT(s) (((*(s) == '-') || (plus && *(s) == '+')) && (s)[1])
|
|
||||||
#define NOTOPT(s) (((*(s) != '-') && (!plus || *(s) != '+')) || (s)[1] == '\0')
|
|
||||||
|
|
||||||
static int sp;
|
|
||||||
|
|
||||||
char *list_optarg;
|
|
||||||
int list_optflags;
|
|
||||||
int list_optopt;
|
|
||||||
int list_opttype;
|
|
||||||
|
|
||||||
static WORD_LIST *lhead = (WORD_LIST *)NULL;
|
|
||||||
WORD_LIST *lcurrent = (WORD_LIST *)NULL;
|
|
||||||
WORD_LIST *loptend; /* Points to the first non-option argument in the list */
|
|
||||||
|
|
||||||
int
|
|
||||||
internal_getopt(list, opts)
|
|
||||||
WORD_LIST *list;
|
|
||||||
char *opts;
|
|
||||||
{
|
|
||||||
register int c;
|
|
||||||
register char *cp;
|
|
||||||
int plus; /* nonzero means to handle +option */
|
|
||||||
static char errstr[3] = { '-', '\0', '\0' };
|
|
||||||
|
|
||||||
plus = *opts == '+';
|
|
||||||
if (plus)
|
|
||||||
opts++;
|
|
||||||
|
|
||||||
if (list == 0) {
|
|
||||||
list_optarg = (char *)NULL;
|
|
||||||
list_optflags = 0;
|
|
||||||
loptend = (WORD_LIST *)NULL; /* No non-option arguments */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list != lhead || lhead == 0) {
|
|
||||||
/* Hmmm.... called with a different word list. Reset. */
|
|
||||||
sp = 1;
|
|
||||||
lcurrent = lhead = list;
|
|
||||||
loptend = (WORD_LIST *)NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sp == 1) {
|
|
||||||
if (lcurrent == 0 || NOTOPT(lcurrent->word->word)) {
|
|
||||||
lhead = (WORD_LIST *)NULL;
|
|
||||||
loptend = lcurrent;
|
|
||||||
return(-1);
|
|
||||||
} else if (ISHELP (lcurrent->word->word)) {
|
|
||||||
lhead = (WORD_LIST *)NULL;
|
|
||||||
loptend = lcurrent;
|
|
||||||
return (GETOPT_HELP);
|
|
||||||
} else if (lcurrent->word->word[0] == '-' &&
|
|
||||||
lcurrent->word->word[1] == '-' &&
|
|
||||||
lcurrent->word->word[2] == 0) {
|
|
||||||
lhead = (WORD_LIST *)NULL;
|
|
||||||
loptend = lcurrent->next;
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
errstr[0] = list_opttype = lcurrent->word->word[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
list_optopt = c = lcurrent->word->word[sp];
|
|
||||||
|
|
||||||
if (c == ':' || (cp = strchr(opts, c)) == NULL) {
|
|
||||||
errstr[1] = c;
|
|
||||||
sh_invalidopt (errstr);
|
|
||||||
if (lcurrent->word->word[++sp] == '\0') {
|
|
||||||
lcurrent = lcurrent->next;
|
|
||||||
sp = 1;
|
|
||||||
}
|
|
||||||
list_optarg = NULL;
|
|
||||||
list_optflags = 0;
|
|
||||||
if (lcurrent)
|
|
||||||
loptend = lcurrent->next;
|
|
||||||
return('?');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*++cp == ':' || *cp == ';') {
|
|
||||||
/* `:': Option requires an argument. */
|
|
||||||
/* `;': option argument may be missing */
|
|
||||||
/* We allow -l2 as equivalent to -l 2 */
|
|
||||||
if (lcurrent->word->word[sp+1]) {
|
|
||||||
list_optarg = lcurrent->word->word + sp + 1;
|
|
||||||
list_optflags = 0;
|
|
||||||
lcurrent = lcurrent->next;
|
|
||||||
/* If the specifier is `;', don't set optarg if the next
|
|
||||||
argument looks like another option. */
|
|
||||||
#if 0
|
|
||||||
} else if (lcurrent->next && (*cp == ':' || lcurrent->next->word->word[0] != '-')) {
|
|
||||||
#else
|
|
||||||
} else if (lcurrent->next && (*cp == ':' || NOTOPT(lcurrent->next->word->word))) {
|
|
||||||
#endif
|
|
||||||
lcurrent = lcurrent->next;
|
|
||||||
list_optarg = lcurrent->word->word;
|
|
||||||
list_optflags = lcurrent->word->flags;
|
|
||||||
lcurrent = lcurrent->next;
|
|
||||||
} else if (*cp == ';') {
|
|
||||||
list_optarg = (char *)NULL;
|
|
||||||
list_optflags = 0;
|
|
||||||
lcurrent = lcurrent->next;
|
|
||||||
} else { /* lcurrent->next == NULL */
|
|
||||||
errstr[1] = c;
|
|
||||||
sh_needarg (errstr);
|
|
||||||
sp = 1;
|
|
||||||
list_optarg = (char *)NULL;
|
|
||||||
list_optflags = 0;
|
|
||||||
return('?');
|
|
||||||
}
|
|
||||||
sp = 1;
|
|
||||||
} else if (*cp == '#') {
|
|
||||||
/* option requires a numeric argument */
|
|
||||||
if (lcurrent->word->word[sp+1]) {
|
|
||||||
if (DIGIT(lcurrent->word->word[sp+1])) {
|
|
||||||
list_optarg = lcurrent->word->word + sp + 1;
|
|
||||||
list_optflags = 0;
|
|
||||||
lcurrent = lcurrent->next;
|
|
||||||
} else {
|
|
||||||
list_optarg = (char *)NULL;
|
|
||||||
list_optflags = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (lcurrent->next && legal_number(lcurrent->next->word->word, (intmax_t *)0)) {
|
|
||||||
lcurrent = lcurrent->next;
|
|
||||||
list_optarg = lcurrent->word->word;
|
|
||||||
list_optflags = lcurrent->word->flags;
|
|
||||||
lcurrent = lcurrent->next;
|
|
||||||
} else {
|
|
||||||
errstr[1] = c;
|
|
||||||
sh_neednumarg (errstr);
|
|
||||||
sp = 1;
|
|
||||||
list_optarg = (char *)NULL;
|
|
||||||
list_optflags = 0;
|
|
||||||
return ('?');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* No argument, just return the option. */
|
|
||||||
if (lcurrent->word->word[++sp] == '\0') {
|
|
||||||
sp = 1;
|
|
||||||
lcurrent = lcurrent->next;
|
|
||||||
}
|
|
||||||
list_optarg = (char *)NULL;
|
|
||||||
list_optflags = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* reset_internal_getopt -- force the in[ft]ernal getopt to reset
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
reset_internal_getopt ()
|
|
||||||
{
|
|
||||||
lhead = lcurrent = loptend = (WORD_LIST *)NULL;
|
|
||||||
sp = 1;
|
|
||||||
}
|
|
43
third_party/bash/bashgetopt.h
vendored
43
third_party/bash/bashgetopt.h
vendored
|
@ -1,43 +0,0 @@
|
||||||
/* bashgetopt.h -- extern declarations for stuff defined in bashgetopt.c. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1993-2021 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* See getopt.h for the explanation of these variables. */
|
|
||||||
|
|
||||||
#if !defined (__BASH_GETOPT_H)
|
|
||||||
# define __BASH_GETOPT_H
|
|
||||||
|
|
||||||
#include "stdc.h"
|
|
||||||
|
|
||||||
#define GETOPT_EOF -1
|
|
||||||
#define GETOPT_HELP -99
|
|
||||||
|
|
||||||
extern char *list_optarg;
|
|
||||||
extern int list_optflags;
|
|
||||||
|
|
||||||
extern int list_optopt;
|
|
||||||
extern int list_opttype;
|
|
||||||
|
|
||||||
extern WORD_LIST *lcurrent;
|
|
||||||
extern WORD_LIST *loptend;
|
|
||||||
|
|
||||||
extern int internal_getopt PARAMS((WORD_LIST *, char *));
|
|
||||||
extern void reset_internal_getopt PARAMS((void));
|
|
||||||
|
|
||||||
#endif /* !__BASH_GETOPT_H */
|
|
1079
third_party/bash/bashhist.c
vendored
1079
third_party/bash/bashhist.c
vendored
File diff suppressed because it is too large
Load diff
89
third_party/bash/bashhist.h
vendored
89
third_party/bash/bashhist.h
vendored
|
@ -1,89 +0,0 @@
|
||||||
/* bashhist.h -- interface to the bash history functions in bashhist.c. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1993-2020 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined (_BASHHIST_H_)
|
|
||||||
#define _BASHHIST_H_
|
|
||||||
|
|
||||||
#include "stdc.h"
|
|
||||||
|
|
||||||
/* Flag values for history_control */
|
|
||||||
#define HC_IGNSPACE 0x01
|
|
||||||
#define HC_IGNDUPS 0x02
|
|
||||||
#define HC_ERASEDUPS 0x04
|
|
||||||
|
|
||||||
#define HC_IGNBOTH (HC_IGNSPACE|HC_IGNDUPS)
|
|
||||||
|
|
||||||
#if defined (STRICT_POSIX)
|
|
||||||
# undef HISTEXPAND_DEFAULT
|
|
||||||
# define HISTEXPAND_DEFAULT 0
|
|
||||||
#else
|
|
||||||
# if !defined (HISTEXPAND_DEFAULT)
|
|
||||||
# define HISTEXPAND_DEFAULT 1
|
|
||||||
# endif /* !HISTEXPAND_DEFAULT */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int remember_on_history;
|
|
||||||
extern int enable_history_list; /* value for `set -o history' */
|
|
||||||
extern int literal_history; /* controlled by `shopt lithist' */
|
|
||||||
extern int force_append_history;
|
|
||||||
extern int history_lines_this_session;
|
|
||||||
extern int history_lines_in_file;
|
|
||||||
extern int history_expansion;
|
|
||||||
extern int history_control;
|
|
||||||
extern int command_oriented_history;
|
|
||||||
extern int current_command_first_line_saved;
|
|
||||||
extern int current_command_first_line_comment;
|
|
||||||
extern int hist_last_line_added;
|
|
||||||
extern int hist_last_line_pushed;
|
|
||||||
|
|
||||||
extern int dont_save_function_defs;
|
|
||||||
|
|
||||||
# if defined (READLINE)
|
|
||||||
extern int hist_verify;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if defined (BANG_HISTORY)
|
|
||||||
extern int history_expansion_inhibited;
|
|
||||||
extern int double_quotes_inhibit_history_expansion;
|
|
||||||
# endif /* BANG_HISTORY */
|
|
||||||
|
|
||||||
extern void bash_initialize_history PARAMS((void));
|
|
||||||
extern void bash_history_reinit PARAMS((int));
|
|
||||||
extern void bash_history_disable PARAMS((void));
|
|
||||||
extern void bash_history_enable PARAMS((void));
|
|
||||||
extern void bash_clear_history PARAMS((void));
|
|
||||||
extern int bash_delete_histent PARAMS((int));
|
|
||||||
extern int bash_delete_history_range PARAMS((int, int));
|
|
||||||
extern int bash_delete_last_history PARAMS((void));
|
|
||||||
extern void load_history PARAMS((void));
|
|
||||||
extern void save_history PARAMS((void));
|
|
||||||
extern int maybe_append_history PARAMS((char *));
|
|
||||||
extern int maybe_save_shell_history PARAMS((void));
|
|
||||||
extern char *pre_process_line PARAMS((char *, int, int));
|
|
||||||
extern void maybe_add_history PARAMS((char *));
|
|
||||||
extern void bash_add_history PARAMS((char *));
|
|
||||||
extern int check_add_history PARAMS((char *, int));
|
|
||||||
extern int history_number PARAMS((void));
|
|
||||||
|
|
||||||
extern void setup_history_ignore PARAMS((char *));
|
|
||||||
|
|
||||||
extern char *last_history_line PARAMS((void));
|
|
||||||
|
|
||||||
#endif /* _BASHHIST_H_ */
|
|
54
third_party/bash/bashintl.h
vendored
54
third_party/bash/bashintl.h
vendored
|
@ -1,54 +0,0 @@
|
||||||
/* bashintl.h -- Internationalization functions and defines. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1996-2009 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined (_BASHINTL_H_)
|
|
||||||
#define _BASHINTL_H_
|
|
||||||
|
|
||||||
#if defined (BUILDTOOL)
|
|
||||||
# undef ENABLE_NLS
|
|
||||||
# define ENABLE_NLS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Include this *after* config.h */
|
|
||||||
#include "gettext.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_LOCALE_H)
|
|
||||||
# include <locale.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _(msgid) gettext(msgid)
|
|
||||||
#define N_(msgid) msgid
|
|
||||||
#define D_(d, msgid) dgettext(d, msgid)
|
|
||||||
|
|
||||||
#define P_(m1, m2, n) ngettext(m1, m2, n)
|
|
||||||
|
|
||||||
#if defined (HAVE_SETLOCALE) && !defined (LC_ALL)
|
|
||||||
# undef HAVE_SETLOCALE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined (HAVE_SETLOCALE)
|
|
||||||
# define setlocale(cat, loc)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined (HAVE_LOCALE_H) || !defined (HAVE_LOCALECONV)
|
|
||||||
# define locale_decpoint() '.'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !_BASHINTL_H_ */
|
|
47
third_party/bash/bashjmp.h
vendored
47
third_party/bash/bashjmp.h
vendored
|
@ -1,47 +0,0 @@
|
||||||
/* bashjmp.h -- wrapper for setjmp.h with necessary bash definitions. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BASHJMP_H_
|
|
||||||
#define _BASHJMP_H_
|
|
||||||
|
|
||||||
#include "posixjmp.h"
|
|
||||||
|
|
||||||
extern procenv_t top_level;
|
|
||||||
extern procenv_t subshell_top_level;
|
|
||||||
extern procenv_t return_catch; /* used by `return' builtin */
|
|
||||||
extern procenv_t wait_intr_buf;
|
|
||||||
|
|
||||||
extern int no_longjmp_on_fatal_error;
|
|
||||||
|
|
||||||
#define SHFUNC_RETURN() sh_longjmp (return_catch, 1)
|
|
||||||
|
|
||||||
#define COPY_PROCENV(old, save) \
|
|
||||||
xbcopy ((char *)old, (char *)save, sizeof (procenv_t));
|
|
||||||
|
|
||||||
/* Values for the second argument to longjmp/siglongjmp. */
|
|
||||||
#define NOT_JUMPED 0 /* Not returning from a longjmp. */
|
|
||||||
#define FORCE_EOF 1 /* We want to stop parsing. */
|
|
||||||
#define DISCARD 2 /* Discard current command. */
|
|
||||||
#define EXITPROG 3 /* Unconditionally exit the program now. */
|
|
||||||
#define ERREXIT 4 /* Exit due to error condition */
|
|
||||||
#define SIGEXIT 5 /* Exit due to fatal terminating signal */
|
|
||||||
#define EXITBLTIN 6 /* Exit due to the exit builtin. */
|
|
||||||
|
|
||||||
#endif /* _BASHJMP_H_ */
|
|
4839
third_party/bash/bashline.c
vendored
4839
third_party/bash/bashline.c
vendored
File diff suppressed because it is too large
Load diff
69
third_party/bash/bashline.h
vendored
69
third_party/bash/bashline.h
vendored
|
@ -1,69 +0,0 @@
|
||||||
/* bashline.h -- interface to the bash readline functions in bashline.c. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1993-2019 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined (_BASHLINE_H_)
|
|
||||||
#define _BASHLINE_H_
|
|
||||||
|
|
||||||
#include "stdc.h"
|
|
||||||
|
|
||||||
extern int bash_readline_initialized;
|
|
||||||
extern int hostname_list_initialized;
|
|
||||||
|
|
||||||
/* these are controlled via shopt */
|
|
||||||
extern int perform_hostname_completion;
|
|
||||||
extern int no_empty_command_completion;
|
|
||||||
extern int force_fignore;
|
|
||||||
extern int dircomplete_spelling;
|
|
||||||
extern int dircomplete_expand;
|
|
||||||
extern int dircomplete_expand_relpath;
|
|
||||||
extern int complete_fullquote;
|
|
||||||
|
|
||||||
extern void posix_readline_initialize PARAMS((int));
|
|
||||||
extern void reset_completer_word_break_chars PARAMS((void));
|
|
||||||
extern int enable_hostname_completion PARAMS((int));
|
|
||||||
extern void initialize_readline PARAMS((void));
|
|
||||||
extern void bashline_reset PARAMS((void));
|
|
||||||
extern void bashline_reinitialize PARAMS((void));
|
|
||||||
extern int bash_re_edit PARAMS((char *));
|
|
||||||
|
|
||||||
extern void bashline_set_event_hook PARAMS((void));
|
|
||||||
extern void bashline_reset_event_hook PARAMS((void));
|
|
||||||
|
|
||||||
extern int bind_keyseq_to_unix_command PARAMS((char *));
|
|
||||||
extern int bash_execute_unix_command PARAMS((int, int));
|
|
||||||
extern int print_unix_command_map PARAMS((void));
|
|
||||||
extern int unbind_unix_command PARAMS((char *));
|
|
||||||
|
|
||||||
extern char **bash_default_completion PARAMS((const char *, int, int, int, int));
|
|
||||||
|
|
||||||
extern void set_directory_hook PARAMS((void));
|
|
||||||
|
|
||||||
/* Used by programmable completion code. */
|
|
||||||
extern char *command_word_completion_function PARAMS((const char *, int));
|
|
||||||
extern char *bash_groupname_completion_function PARAMS((const char *, int));
|
|
||||||
extern char *bash_servicename_completion_function PARAMS((const char *, int));
|
|
||||||
|
|
||||||
extern char **get_hostname_list PARAMS((void));
|
|
||||||
extern void clear_hostname_list PARAMS((void));
|
|
||||||
|
|
||||||
extern char **bash_directory_completion_matches PARAMS((const char *));
|
|
||||||
extern char *bash_dequote_text PARAMS((const char *));
|
|
||||||
|
|
||||||
#endif /* _BASHLINE_H_ */
|
|
42
third_party/bash/bashtypes.h
vendored
42
third_party/bash/bashtypes.h
vendored
|
@ -1,42 +0,0 @@
|
||||||
/* bashtypes.h -- Bash system types. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined (_BASHTYPES_H_)
|
|
||||||
# define _BASHTYPES_H_
|
|
||||||
|
|
||||||
#if defined (CRAY)
|
|
||||||
# define word __word
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#if defined (CRAY)
|
|
||||||
# undef word
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (HAVE_INTTYPES_H)
|
|
||||||
# include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_STDINT_H
|
|
||||||
# include <stdint.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _BASHTYPES_H_ */
|
|
221
third_party/bash/bracecomp.c
vendored
221
third_party/bash/bracecomp.c
vendored
|
@ -1,221 +0,0 @@
|
||||||
/* bracecomp.c -- Complete a filename with the possible completions enclosed
|
|
||||||
in csh-style braces such that the list of completions is available to the
|
|
||||||
shell. */
|
|
||||||
|
|
||||||
/* Original version by tromey@cns.caltech.edu, Fri Feb 7 1992. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1993-2020 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (BRACE_EXPANSION) && defined (READLINE)
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "shmbutil.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "third_party/readline/readline.h"
|
|
||||||
|
|
||||||
static int _strcompare PARAMS((char **, char **));
|
|
||||||
|
|
||||||
/* Find greatest common prefix of two strings. */
|
|
||||||
static int
|
|
||||||
string_gcd (s1, s2)
|
|
||||||
char *s1, *s2;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
if (s1 == NULL || s2 == NULL)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
for (i = 0; *s1 && *s2; ++s1, ++s2, ++i)
|
|
||||||
{
|
|
||||||
if (*s1 != *s2)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
really_munge_braces (array, real_start, real_end, gcd_zero)
|
|
||||||
char **array;
|
|
||||||
int real_start, real_end, gcd_zero;
|
|
||||||
{
|
|
||||||
int start, end, gcd;
|
|
||||||
char *result, *subterm, *x;
|
|
||||||
int result_size, flag, tlen;
|
|
||||||
|
|
||||||
flag = 0;
|
|
||||||
|
|
||||||
if (real_start == real_end)
|
|
||||||
{
|
|
||||||
x = array[real_start] ? sh_backslash_quote (array[real_start] + gcd_zero, 0, 0)
|
|
||||||
: sh_backslash_quote (array[0], 0, 0);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = (char *)xmalloc (result_size = 16);
|
|
||||||
*result = '\0';
|
|
||||||
|
|
||||||
for (start = real_start; start < real_end; start = end + 1)
|
|
||||||
{
|
|
||||||
gcd = strlen (array[start]);
|
|
||||||
for (end = start + 1; end < real_end; end++)
|
|
||||||
{
|
|
||||||
int temp;
|
|
||||||
|
|
||||||
temp = string_gcd (array[start], array[end]);
|
|
||||||
|
|
||||||
if (temp <= gcd_zero)
|
|
||||||
break;
|
|
||||||
|
|
||||||
gcd = temp;
|
|
||||||
}
|
|
||||||
end--;
|
|
||||||
|
|
||||||
if (gcd_zero == 0 && start == real_start && end != (real_end - 1))
|
|
||||||
{
|
|
||||||
/* In this case, add in a leading '{', because we are at
|
|
||||||
top level, and there isn't a consistent prefix. */
|
|
||||||
result_size += 1;
|
|
||||||
result = (char *)xrealloc (result, result_size);
|
|
||||||
result[0] = '{'; result[1] = '\0';
|
|
||||||
flag++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure we backslash quote every substring we insert into the
|
|
||||||
resultant brace expression. This is so the default filename
|
|
||||||
quoting function won't inappropriately quote the braces. */
|
|
||||||
if (start == end)
|
|
||||||
{
|
|
||||||
x = savestring (array[start] + gcd_zero);
|
|
||||||
subterm = sh_backslash_quote (x, 0, 0);
|
|
||||||
free (x);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If there is more than one element in the subarray,
|
|
||||||
insert the (quoted) prefix and an opening brace. */
|
|
||||||
tlen = gcd - gcd_zero;
|
|
||||||
x = (char *)xmalloc (tlen + 1);
|
|
||||||
strncpy (x, array[start] + gcd_zero, tlen);
|
|
||||||
x[tlen] = '\0';
|
|
||||||
subterm = sh_backslash_quote (x, 0, 0);
|
|
||||||
free (x);
|
|
||||||
result_size += strlen (subterm) + 1;
|
|
||||||
result = (char *)xrealloc (result, result_size);
|
|
||||||
strcat (result, subterm);
|
|
||||||
free (subterm);
|
|
||||||
strcat (result, "{");
|
|
||||||
subterm = really_munge_braces (array, start, end + 1, gcd);
|
|
||||||
subterm[strlen (subterm) - 1] = '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
result_size += strlen (subterm) + 1;
|
|
||||||
result = (char *)xrealloc (result, result_size);
|
|
||||||
strcat (result, subterm);
|
|
||||||
strcat (result, ",");
|
|
||||||
free (subterm);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gcd_zero == 0)
|
|
||||||
result[strlen (result) - 1] = flag ? '}' : '\0';
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
_strcompare (s1, s2)
|
|
||||||
char **s1, **s2;
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
result = **s1 - **s2;
|
|
||||||
if (result == 0)
|
|
||||||
result = strcmp (*s1, *s2);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
hack_braces_completion (names)
|
|
||||||
char **names;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
char *temp;
|
|
||||||
|
|
||||||
i = strvec_len (names);
|
|
||||||
if (MB_CUR_MAX > 1 && i > 2)
|
|
||||||
qsort (names+1, i-1, sizeof (char *), (QSFUNC *)_strcompare);
|
|
||||||
|
|
||||||
temp = really_munge_braces (names, 1, i, 0);
|
|
||||||
|
|
||||||
for (i = 0; names[i]; ++i)
|
|
||||||
{
|
|
||||||
free (names[i]);
|
|
||||||
names[i] = NULL;
|
|
||||||
}
|
|
||||||
names[0] = temp;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We handle quoting ourselves within hack_braces_completion, so we turn off
|
|
||||||
rl_filename_quoting_desired and rl_filename_quoting_function. */
|
|
||||||
int
|
|
||||||
bash_brace_completion (count, ignore)
|
|
||||||
int count, ignore;
|
|
||||||
{
|
|
||||||
rl_compignore_func_t *orig_ignore_func;
|
|
||||||
rl_compentry_func_t *orig_entry_func;
|
|
||||||
rl_quote_func_t *orig_quoting_func;
|
|
||||||
rl_completion_func_t *orig_attempt_func;
|
|
||||||
int orig_quoting_desired, r;
|
|
||||||
|
|
||||||
orig_ignore_func = rl_ignore_some_completions_function;
|
|
||||||
orig_attempt_func = rl_attempted_completion_function;
|
|
||||||
orig_entry_func = rl_completion_entry_function;
|
|
||||||
orig_quoting_func = rl_filename_quoting_function;
|
|
||||||
orig_quoting_desired = rl_filename_quoting_desired;
|
|
||||||
|
|
||||||
rl_completion_entry_function = rl_filename_completion_function;
|
|
||||||
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
|
||||||
rl_ignore_some_completions_function = hack_braces_completion;
|
|
||||||
rl_filename_quoting_function = (rl_quote_func_t *)NULL;
|
|
||||||
rl_filename_quoting_desired = 0;
|
|
||||||
|
|
||||||
r = rl_complete_internal (TAB);
|
|
||||||
|
|
||||||
rl_ignore_some_completions_function = orig_ignore_func;
|
|
||||||
rl_attempted_completion_function = orig_attempt_func;
|
|
||||||
rl_completion_entry_function = orig_entry_func;
|
|
||||||
rl_filename_quoting_function = orig_quoting_func;
|
|
||||||
rl_filename_quoting_desired = orig_quoting_desired;
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
#endif /* BRACE_EXPANSION && READLINE */
|
|
843
third_party/bash/braces.c
vendored
843
third_party/bash/braces.c
vendored
|
@ -1,843 +0,0 @@
|
||||||
/* braces.c -- code for doing word expansion in curly braces. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Stuff in curly braces gets expanded before all other shell expansions. */
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (BRACE_EXPANSION)
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#if defined (SHELL)
|
|
||||||
# include "shell.h"
|
|
||||||
#else
|
|
||||||
# if defined (TEST)
|
|
||||||
typedef char *WORD_DESC;
|
|
||||||
typedef char **WORD_LIST;
|
|
||||||
#define _(X) X
|
|
||||||
# endif /* TEST */
|
|
||||||
#endif /* SHELL */
|
|
||||||
|
|
||||||
#include "typemax.h" /* INTMAX_MIN, INTMAX_MAX */
|
|
||||||
#include "general.h"
|
|
||||||
#include "shmbutil.h"
|
|
||||||
#include "chartypes.h"
|
|
||||||
|
|
||||||
#ifndef errno
|
|
||||||
extern int errno;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
|
|
||||||
|
|
||||||
#define BRACE_SEQ_SPECIFIER ".."
|
|
||||||
|
|
||||||
extern int asprintf PARAMS((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
|
|
||||||
|
|
||||||
/* Basic idea:
|
|
||||||
|
|
||||||
Segregate the text into 3 sections: preamble (stuff before an open brace),
|
|
||||||
postamble (stuff after the matching close brace) and amble (stuff after
|
|
||||||
preamble, and before postamble). Expand amble, and then tack on the
|
|
||||||
expansions to preamble. Expand postamble, and tack on the expansions to
|
|
||||||
the result so far.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* The character which is used to separate arguments. */
|
|
||||||
static const int brace_arg_separator = ',';
|
|
||||||
|
|
||||||
#if defined (PARAMS)
|
|
||||||
static int brace_gobbler PARAMS((char *, size_t, int *, int));
|
|
||||||
static char **expand_amble PARAMS((char *, size_t, int));
|
|
||||||
static char **expand_seqterm PARAMS((char *, size_t));
|
|
||||||
static char **mkseq PARAMS((intmax_t, intmax_t, intmax_t, int, int));
|
|
||||||
static char **array_concat PARAMS((char **, char **));
|
|
||||||
#else
|
|
||||||
static int brace_gobbler ();
|
|
||||||
static char **expand_amble ();
|
|
||||||
static char **expand_seqterm ();
|
|
||||||
static char **mkseq();
|
|
||||||
static char **array_concat ();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void
|
|
||||||
dump_result (a)
|
|
||||||
char **a;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; a[i]; i++)
|
|
||||||
printf ("dump_result: a[%d] = -%s-\n", i, a[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return an array of strings; the brace expansion of TEXT. */
|
|
||||||
char **
|
|
||||||
brace_expand (text)
|
|
||||||
char *text;
|
|
||||||
{
|
|
||||||
register int start;
|
|
||||||
size_t tlen;
|
|
||||||
char *preamble, *postamble, *amble;
|
|
||||||
size_t alen;
|
|
||||||
char **tack, **result;
|
|
||||||
int i, j, c, c1;
|
|
||||||
|
|
||||||
DECLARE_MBSTATE;
|
|
||||||
|
|
||||||
/* Find the text of the preamble. */
|
|
||||||
tlen = strlen (text);
|
|
||||||
i = 0;
|
|
||||||
#if defined (CSH_BRACE_COMPAT)
|
|
||||||
c = brace_gobbler (text, tlen, &i, '{'); /* } */
|
|
||||||
#else
|
|
||||||
/* Make sure that when we exit this loop, c == 0 or text[i] begins a
|
|
||||||
valid brace expansion sequence. */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
c = brace_gobbler (text, tlen, &i, '{'); /* } */
|
|
||||||
c1 = c;
|
|
||||||
/* Verify that c begins a valid brace expansion word. If it doesn't, we
|
|
||||||
go on. Loop stops when there are no more open braces in the word. */
|
|
||||||
if (c)
|
|
||||||
{
|
|
||||||
start = j = i + 1; /* { */
|
|
||||||
c = brace_gobbler (text, tlen, &j, '}');
|
|
||||||
if (c == 0) /* it's not */
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
c = c1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else /* it is */
|
|
||||||
{
|
|
||||||
c = c1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (c);
|
|
||||||
#endif /* !CSH_BRACE_COMPAT */
|
|
||||||
|
|
||||||
preamble = (char *)xmalloc (i + 1);
|
|
||||||
if (i > 0)
|
|
||||||
strncpy (preamble, text, i);
|
|
||||||
preamble[i] = '\0';
|
|
||||||
|
|
||||||
result = (char **)xmalloc (2 * sizeof (char *));
|
|
||||||
result[0] = preamble;
|
|
||||||
result[1] = (char *)NULL;
|
|
||||||
|
|
||||||
/* Special case. If we never found an exciting character, then
|
|
||||||
the preamble is all of the text, so just return that. */
|
|
||||||
if (c != '{')
|
|
||||||
return (result);
|
|
||||||
|
|
||||||
/* Find the amble. This is the stuff inside this set of braces. */
|
|
||||||
start = ++i;
|
|
||||||
c = brace_gobbler (text, tlen, &i, '}');
|
|
||||||
|
|
||||||
/* What if there isn't a matching close brace? */
|
|
||||||
if (c == 0)
|
|
||||||
{
|
|
||||||
#if defined (NOTDEF)
|
|
||||||
/* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
|
|
||||||
and I, then this should be an error. Otherwise, it isn't. */
|
|
||||||
j = start;
|
|
||||||
while (j < i)
|
|
||||||
{
|
|
||||||
if (text[j] == '\\')
|
|
||||||
{
|
|
||||||
j++;
|
|
||||||
ADVANCE_CHAR (text, tlen, j);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (text[j] == brace_arg_separator)
|
|
||||||
{ /* { */
|
|
||||||
strvec_dispose (result);
|
|
||||||
set_exit_status (EXECUTION_FAILURE);
|
|
||||||
report_error ("no closing `%c' in %s", '}', text);
|
|
||||||
throw_to_top_level ();
|
|
||||||
}
|
|
||||||
ADVANCE_CHAR (text, tlen, j);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
free (preamble); /* Same as result[0]; see initialization. */
|
|
||||||
result[0] = savestring (text);
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (SHELL)
|
|
||||||
amble = substring (text, start, i);
|
|
||||||
alen = i - start;
|
|
||||||
#else
|
|
||||||
amble = (char *)xmalloc (1 + (i - start));
|
|
||||||
strncpy (amble, &text[start], (i - start));
|
|
||||||
alen = i - start;
|
|
||||||
amble[alen] = '\0';
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (SHELL)
|
|
||||||
INITIALIZE_MBSTATE;
|
|
||||||
|
|
||||||
/* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
|
|
||||||
just return without doing any expansion. */
|
|
||||||
j = 0;
|
|
||||||
while (amble[j])
|
|
||||||
{
|
|
||||||
if (amble[j] == '\\')
|
|
||||||
{
|
|
||||||
j++;
|
|
||||||
ADVANCE_CHAR (amble, alen, j);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amble[j] == brace_arg_separator)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ADVANCE_CHAR (amble, alen, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amble[j] == 0)
|
|
||||||
{
|
|
||||||
tack = expand_seqterm (amble, alen);
|
|
||||||
if (tack)
|
|
||||||
goto add_tack;
|
|
||||||
else if (text[i + 1])
|
|
||||||
{
|
|
||||||
/* If the sequence expansion fails (e.g., because the integers
|
|
||||||
overflow), but there is more in the string, try and process
|
|
||||||
the rest of the string, which may contain additional brace
|
|
||||||
expansions. Treat the unexpanded sequence term as a simple
|
|
||||||
string (including the braces). */
|
|
||||||
tack = strvec_create (2);
|
|
||||||
tack[0] = savestring (text+start-1);
|
|
||||||
tack[0][i-start+2] = '\0';
|
|
||||||
tack[1] = (char *)0;
|
|
||||||
goto add_tack;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
free (amble);
|
|
||||||
free (preamble);
|
|
||||||
result[0] = savestring (text);
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SHELL */
|
|
||||||
|
|
||||||
tack = expand_amble (amble, alen, 0);
|
|
||||||
add_tack:
|
|
||||||
result = array_concat (result, tack);
|
|
||||||
free (amble);
|
|
||||||
if (tack != result)
|
|
||||||
strvec_dispose (tack);
|
|
||||||
|
|
||||||
postamble = text + i + 1;
|
|
||||||
|
|
||||||
if (postamble && *postamble)
|
|
||||||
{
|
|
||||||
tack = brace_expand (postamble);
|
|
||||||
result = array_concat (result, tack);
|
|
||||||
if (tack != result)
|
|
||||||
strvec_dispose (tack);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expand the text found inside of braces. We simply try to split the
|
|
||||||
text at BRACE_ARG_SEPARATORs into separate strings. We then brace
|
|
||||||
expand each slot which needs it, until there are no more slots which
|
|
||||||
need it. */
|
|
||||||
static char **
|
|
||||||
expand_amble (text, tlen, flags)
|
|
||||||
char *text;
|
|
||||||
size_t tlen;
|
|
||||||
int flags;
|
|
||||||
{
|
|
||||||
char **result, **partial, **tresult;
|
|
||||||
char *tem;
|
|
||||||
int start, i, c;
|
|
||||||
|
|
||||||
#if defined (SHELL)
|
|
||||||
DECLARE_MBSTATE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
result = (char **)NULL;
|
|
||||||
|
|
||||||
start = i = 0;
|
|
||||||
c = 1;
|
|
||||||
while (c)
|
|
||||||
{
|
|
||||||
c = brace_gobbler (text, tlen, &i, brace_arg_separator);
|
|
||||||
#if defined (SHELL)
|
|
||||||
tem = substring (text, start, i);
|
|
||||||
#else
|
|
||||||
tem = (char *)xmalloc (1 + (i - start));
|
|
||||||
strncpy (tem, &text[start], (i - start));
|
|
||||||
tem[i - start] = '\0';
|
|
||||||
#endif
|
|
||||||
|
|
||||||
partial = brace_expand (tem);
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
result = partial;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
register int lr, lp, j;
|
|
||||||
|
|
||||||
lr = strvec_len (result);
|
|
||||||
lp = strvec_len (partial);
|
|
||||||
|
|
||||||
tresult = strvec_mresize (result, lp + lr + 1);
|
|
||||||
if (tresult == 0)
|
|
||||||
{
|
|
||||||
internal_error (_("brace expansion: cannot allocate memory for %s"), tem);
|
|
||||||
free (tem);
|
|
||||||
strvec_dispose (partial);
|
|
||||||
strvec_dispose (result);
|
|
||||||
result = (char **)NULL;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result = tresult;
|
|
||||||
|
|
||||||
for (j = 0; j < lp; j++)
|
|
||||||
result[lr + j] = partial[j];
|
|
||||||
|
|
||||||
result[lr + j] = (char *)NULL;
|
|
||||||
free (partial);
|
|
||||||
}
|
|
||||||
free (tem);
|
|
||||||
#if defined (SHELL)
|
|
||||||
ADVANCE_CHAR (text, tlen, i);
|
|
||||||
#else
|
|
||||||
i++;
|
|
||||||
#endif
|
|
||||||
start = i;
|
|
||||||
}
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ST_BAD 0
|
|
||||||
#define ST_INT 1
|
|
||||||
#define ST_CHAR 2
|
|
||||||
#define ST_ZINT 3
|
|
||||||
|
|
||||||
static char **
|
|
||||||
mkseq (start, end, incr, type, width)
|
|
||||||
intmax_t start, end, incr;
|
|
||||||
int type, width;
|
|
||||||
{
|
|
||||||
intmax_t n, prevn;
|
|
||||||
int i, nelem;
|
|
||||||
char **result, *t;
|
|
||||||
|
|
||||||
if (incr == 0)
|
|
||||||
incr = 1;
|
|
||||||
|
|
||||||
if (start > end && incr > 0)
|
|
||||||
incr = -incr;
|
|
||||||
else if (start < end && incr < 0)
|
|
||||||
{
|
|
||||||
if (incr == INTMAX_MIN) /* Don't use -INTMAX_MIN */
|
|
||||||
return ((char **)NULL);
|
|
||||||
incr = -incr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that end-start will not overflow INTMAX_MIN, INTMAX_MAX. The +3
|
|
||||||
and -2, not strictly necessary, are there because of the way the number
|
|
||||||
of elements and value passed to strvec_create() are calculated below. */
|
|
||||||
if (SUBOVERFLOW (end, start, INTMAX_MIN+3, INTMAX_MAX-2))
|
|
||||||
return ((char **)NULL);
|
|
||||||
|
|
||||||
prevn = sh_imaxabs (end - start);
|
|
||||||
/* Need to check this way in case INT_MAX == INTMAX_MAX */
|
|
||||||
if (INT_MAX == INTMAX_MAX && (ADDOVERFLOW (prevn, 2, INT_MIN, INT_MAX)))
|
|
||||||
return ((char **)NULL);
|
|
||||||
/* Make sure the assignment to nelem below doesn't end up <= 0 due to
|
|
||||||
intmax_t overflow */
|
|
||||||
else if (ADDOVERFLOW ((prevn/sh_imaxabs(incr)), 1, INTMAX_MIN, INTMAX_MAX))
|
|
||||||
return ((char **)NULL);
|
|
||||||
|
|
||||||
/* XXX - TOFIX: potentially allocating a lot of extra memory if
|
|
||||||
imaxabs(incr) != 1 */
|
|
||||||
/* Instead of a simple nelem = prevn + 1, something like:
|
|
||||||
nelem = (prevn / imaxabs(incr)) + 1;
|
|
||||||
would work */
|
|
||||||
if ((prevn / sh_imaxabs (incr)) > INT_MAX - 3) /* check int overflow */
|
|
||||||
return ((char **)NULL);
|
|
||||||
nelem = (prevn / sh_imaxabs(incr)) + 1;
|
|
||||||
result = strvec_mcreate (nelem + 1);
|
|
||||||
if (result == 0)
|
|
||||||
{
|
|
||||||
internal_error (_("brace expansion: failed to allocate memory for %u elements"), (unsigned int)nelem);
|
|
||||||
return ((char **)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure we go through the loop at least once, so {3..3} prints `3' */
|
|
||||||
i = 0;
|
|
||||||
n = start;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#if defined (SHELL)
|
|
||||||
if (ISINTERRUPT)
|
|
||||||
{
|
|
||||||
result[i] = (char *)NULL;
|
|
||||||
strvec_dispose (result);
|
|
||||||
result = (char **)NULL;
|
|
||||||
}
|
|
||||||
QUIT;
|
|
||||||
#endif
|
|
||||||
if (type == ST_INT)
|
|
||||||
result[i++] = t = itos (n);
|
|
||||||
else if (type == ST_ZINT)
|
|
||||||
{
|
|
||||||
int len, arg;
|
|
||||||
arg = n;
|
|
||||||
len = asprintf (&t, "%0*d", width, arg);
|
|
||||||
result[i++] = t;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (t = (char *)malloc (2))
|
|
||||||
{
|
|
||||||
t[0] = n;
|
|
||||||
t[1] = '\0';
|
|
||||||
}
|
|
||||||
result[i++] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We failed to allocate memory for this number, so we bail. */
|
|
||||||
if (t == 0)
|
|
||||||
{
|
|
||||||
char *p, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
|
|
||||||
|
|
||||||
/* Easier to do this than mess around with various intmax_t printf
|
|
||||||
formats (%ld? %lld? %jd?) and PRIdMAX. */
|
|
||||||
p = inttostr (n, lbuf, sizeof (lbuf));
|
|
||||||
internal_error (_("brace expansion: failed to allocate memory for `%s'"), p);
|
|
||||||
strvec_dispose (result);
|
|
||||||
return ((char **)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle overflow and underflow of n+incr */
|
|
||||||
if (ADDOVERFLOW (n, incr, INTMAX_MIN, INTMAX_MAX))
|
|
||||||
break;
|
|
||||||
|
|
||||||
n += incr;
|
|
||||||
|
|
||||||
if ((incr < 0 && n < end) || (incr > 0 && n > end))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (1);
|
|
||||||
|
|
||||||
result[i] = (char *)0;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char **
|
|
||||||
expand_seqterm (text, tlen)
|
|
||||||
char *text;
|
|
||||||
size_t tlen;
|
|
||||||
{
|
|
||||||
char *t, *lhs, *rhs;
|
|
||||||
int lhs_t, rhs_t, lhs_l, rhs_l, width;
|
|
||||||
intmax_t lhs_v, rhs_v, incr;
|
|
||||||
intmax_t tl, tr;
|
|
||||||
char **result, *ep, *oep;
|
|
||||||
|
|
||||||
t = strstr (text, BRACE_SEQ_SPECIFIER);
|
|
||||||
if (t == 0)
|
|
||||||
return ((char **)NULL);
|
|
||||||
|
|
||||||
lhs_l = t - text; /* index of start of BRACE_SEQ_SPECIFIER */
|
|
||||||
lhs = substring (text, 0, lhs_l);
|
|
||||||
rhs = substring (text, lhs_l + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
|
|
||||||
|
|
||||||
if (lhs[0] == 0 || rhs[0] == 0)
|
|
||||||
{
|
|
||||||
free (lhs);
|
|
||||||
free (rhs);
|
|
||||||
return ((char **)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now figure out whether LHS and RHS are integers or letters. Both
|
|
||||||
sides have to match. */
|
|
||||||
lhs_t = (legal_number (lhs, &tl)) ? ST_INT :
|
|
||||||
((ISALPHA (lhs[0]) && lhs[1] == 0) ? ST_CHAR : ST_BAD);
|
|
||||||
|
|
||||||
/* Decide on rhs and whether or not it looks like the user specified
|
|
||||||
an increment */
|
|
||||||
ep = 0;
|
|
||||||
if (ISDIGIT (rhs[0]) || ((rhs[0] == '+' || rhs[0] == '-') && ISDIGIT (rhs[1])))
|
|
||||||
{
|
|
||||||
rhs_t = ST_INT;
|
|
||||||
errno = 0;
|
|
||||||
tr = strtoimax (rhs, &ep, 10);
|
|
||||||
if (errno == ERANGE || (ep && *ep != 0 && *ep != '.'))
|
|
||||||
rhs_t = ST_BAD; /* invalid */
|
|
||||||
}
|
|
||||||
else if (ISALPHA (rhs[0]) && (rhs[1] == 0 || rhs[1] == '.'))
|
|
||||||
{
|
|
||||||
rhs_t = ST_CHAR;
|
|
||||||
ep = rhs + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rhs_t = ST_BAD;
|
|
||||||
ep = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
incr = 1;
|
|
||||||
if (rhs_t != ST_BAD)
|
|
||||||
{
|
|
||||||
oep = ep;
|
|
||||||
errno = 0;
|
|
||||||
if (ep && *ep == '.' && ep[1] == '.' && ep[2])
|
|
||||||
incr = strtoimax (ep + 2, &ep, 10);
|
|
||||||
if (*ep != 0 || errno == ERANGE)
|
|
||||||
rhs_t = ST_BAD; /* invalid incr or overflow */
|
|
||||||
tlen -= ep - oep;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lhs_t != rhs_t || lhs_t == ST_BAD || rhs_t == ST_BAD)
|
|
||||||
{
|
|
||||||
free (lhs);
|
|
||||||
free (rhs);
|
|
||||||
return ((char **)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK, we have something. It's either a sequence of integers, ascending
|
|
||||||
or descending, or a sequence or letters, ditto. Generate the sequence,
|
|
||||||
put it into a string vector, and return it. */
|
|
||||||
|
|
||||||
if (lhs_t == ST_CHAR)
|
|
||||||
{
|
|
||||||
lhs_v = (unsigned char)lhs[0];
|
|
||||||
rhs_v = (unsigned char)rhs[0];
|
|
||||||
width = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lhs_v = tl; /* integer truncation */
|
|
||||||
rhs_v = tr;
|
|
||||||
|
|
||||||
/* Decide whether or not the terms need zero-padding */
|
|
||||||
rhs_l = tlen - lhs_l - sizeof (BRACE_SEQ_SPECIFIER) + 1;
|
|
||||||
width = 0;
|
|
||||||
if (lhs_l > 1 && lhs[0] == '0')
|
|
||||||
width = lhs_l, lhs_t = ST_ZINT;
|
|
||||||
if (lhs_l > 2 && lhs[0] == '-' && lhs[1] == '0')
|
|
||||||
width = lhs_l, lhs_t = ST_ZINT;
|
|
||||||
if (rhs_l > 1 && rhs[0] == '0' && width < rhs_l)
|
|
||||||
width = rhs_l, lhs_t = ST_ZINT;
|
|
||||||
if (rhs_l > 2 && rhs[0] == '-' && rhs[1] == '0' && width < rhs_l)
|
|
||||||
width = rhs_l, lhs_t = ST_ZINT;
|
|
||||||
|
|
||||||
if (width < lhs_l && lhs_t == ST_ZINT)
|
|
||||||
width = lhs_l;
|
|
||||||
if (width < rhs_l && lhs_t == ST_ZINT)
|
|
||||||
width = rhs_l;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = mkseq (lhs_v, rhs_v, incr, lhs_t, width);
|
|
||||||
|
|
||||||
free (lhs);
|
|
||||||
free (rhs);
|
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start at INDEX, and skip characters in TEXT. Set INDEX to the
|
|
||||||
index of the character matching SATISFY. This understands about
|
|
||||||
quoting. Return the character that caused us to stop searching;
|
|
||||||
this is either the same as SATISFY, or 0. */
|
|
||||||
/* If SATISFY is `}', we are looking for a brace expression, so we
|
|
||||||
should enforce the rules that govern valid brace expansions:
|
|
||||||
1) to count as an arg separator, a comma or `..' has to be outside
|
|
||||||
an inner set of braces.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
brace_gobbler (text, tlen, indx, satisfy)
|
|
||||||
char *text;
|
|
||||||
size_t tlen;
|
|
||||||
int *indx;
|
|
||||||
int satisfy;
|
|
||||||
{
|
|
||||||
register int i, c, quoted, level, commas, pass_next;
|
|
||||||
#if defined (SHELL)
|
|
||||||
int si;
|
|
||||||
char *t;
|
|
||||||
#endif
|
|
||||||
DECLARE_MBSTATE;
|
|
||||||
|
|
||||||
level = quoted = pass_next = 0;
|
|
||||||
#if defined (CSH_BRACE_COMPAT)
|
|
||||||
commas = 1;
|
|
||||||
#else
|
|
||||||
commas = (satisfy == '}') ? 0 : 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
i = *indx;
|
|
||||||
while (c = text[i])
|
|
||||||
{
|
|
||||||
if (pass_next)
|
|
||||||
{
|
|
||||||
pass_next = 0;
|
|
||||||
#if defined (SHELL)
|
|
||||||
ADVANCE_CHAR (text, tlen, i);
|
|
||||||
#else
|
|
||||||
i++;
|
|
||||||
#endif
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A backslash escapes the next character. This allows backslash to
|
|
||||||
escape the quote character in a double-quoted string. */
|
|
||||||
if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
|
|
||||||
{
|
|
||||||
pass_next = 1;
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (SHELL)
|
|
||||||
/* If compiling for the shell, treat ${...} like \{...} */
|
|
||||||
if (c == '$' && text[i+1] == '{' && quoted != '\'') /* } */
|
|
||||||
{
|
|
||||||
pass_next = 1;
|
|
||||||
i++;
|
|
||||||
if (quoted == 0)
|
|
||||||
level++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (quoted)
|
|
||||||
{
|
|
||||||
if (c == quoted)
|
|
||||||
quoted = 0;
|
|
||||||
#if defined (SHELL)
|
|
||||||
/* The shell allows quoted command substitutions */
|
|
||||||
if (quoted == '"' && c == '$' && text[i+1] == '(') /*)*/
|
|
||||||
goto comsub;
|
|
||||||
#endif
|
|
||||||
#if defined (SHELL)
|
|
||||||
ADVANCE_CHAR (text, tlen, i);
|
|
||||||
#else
|
|
||||||
i++;
|
|
||||||
#endif
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '"' || c == '\'' || c == '`')
|
|
||||||
{
|
|
||||||
quoted = c;
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (SHELL)
|
|
||||||
/* Pass new-style command and process substitutions through unchanged. */
|
|
||||||
if ((c == '$' || c == '<' || c == '>') && text[i+1] == '(') /* ) */
|
|
||||||
{
|
|
||||||
comsub:
|
|
||||||
si = i + 2;
|
|
||||||
t = extract_command_subst (text, &si, 0);
|
|
||||||
i = si;
|
|
||||||
free (t);
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (c == satisfy && level == 0 && quoted == 0 && commas > 0)
|
|
||||||
{
|
|
||||||
/* We ignore an open brace surrounded by whitespace, and also
|
|
||||||
an open brace followed immediately by a close brace preceded
|
|
||||||
by whitespace. */
|
|
||||||
if (c == '{' &&
|
|
||||||
((!i || brace_whitespace (text[i - 1])) &&
|
|
||||||
(brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '{')
|
|
||||||
level++;
|
|
||||||
else if (c == '}' && level)
|
|
||||||
level--;
|
|
||||||
#if !defined (CSH_BRACE_COMPAT)
|
|
||||||
else if (satisfy == '}' && c == brace_arg_separator && level == 0)
|
|
||||||
commas++;
|
|
||||||
else if (satisfy == '}' && STREQN (text+i, BRACE_SEQ_SPECIFIER, 2) &&
|
|
||||||
text[i+2] != satisfy && level == 0)
|
|
||||||
commas++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (SHELL)
|
|
||||||
ADVANCE_CHAR (text, tlen, i);
|
|
||||||
#else
|
|
||||||
i++;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
*indx = i;
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a new array of strings which is the result of appending each
|
|
||||||
string in ARR2 to each string in ARR1. The resultant array is
|
|
||||||
len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
|
|
||||||
are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
|
|
||||||
is returned. */
|
|
||||||
static char **
|
|
||||||
array_concat (arr1, arr2)
|
|
||||||
char **arr1, **arr2;
|
|
||||||
{
|
|
||||||
register int i, j, len, len1, len2;
|
|
||||||
register char **result;
|
|
||||||
|
|
||||||
if (arr1 == 0)
|
|
||||||
return (arr2); /* XXX - see if we can get away without copying? */
|
|
||||||
|
|
||||||
if (arr2 == 0)
|
|
||||||
return (arr1); /* XXX - caller expects us to free arr1 */
|
|
||||||
|
|
||||||
/* We can only short-circuit if the array consists of a single null element;
|
|
||||||
otherwise we need to replicate the contents of the other array and
|
|
||||||
prefix (or append, below) an empty element to each one. */
|
|
||||||
if (arr1[0] && arr1[0][0] == 0 && arr1[1] == 0)
|
|
||||||
{
|
|
||||||
strvec_dispose (arr1);
|
|
||||||
return (arr2); /* XXX - use flags to see if we can avoid copying here */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arr2[0] && arr2[0][0] == 0 && arr2[1] == 0)
|
|
||||||
return (arr1); /* XXX - rather than copying and freeing it */
|
|
||||||
|
|
||||||
len1 = strvec_len (arr1);
|
|
||||||
len2 = strvec_len (arr2);
|
|
||||||
|
|
||||||
result = (char **)malloc ((1 + (len1 * len2)) * sizeof (char *));
|
|
||||||
if (result == 0)
|
|
||||||
return (result);
|
|
||||||
|
|
||||||
len = 0;
|
|
||||||
for (i = 0; i < len1; i++)
|
|
||||||
{
|
|
||||||
int strlen_1 = strlen (arr1[i]);
|
|
||||||
|
|
||||||
for (j = 0; j < len2; j++)
|
|
||||||
{
|
|
||||||
result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
|
|
||||||
strcpy (result[len], arr1[i]);
|
|
||||||
strcpy (result[len] + strlen_1, arr2[j]);
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
free (arr1[i]);
|
|
||||||
}
|
|
||||||
free (arr1);
|
|
||||||
|
|
||||||
result[len] = (char *)NULL;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (TEST)
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
void *
|
|
||||||
xmalloc(n)
|
|
||||||
size_t n;
|
|
||||||
{
|
|
||||||
return (malloc (n));
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
xrealloc(p, n)
|
|
||||||
void *p;
|
|
||||||
size_t n;
|
|
||||||
{
|
|
||||||
return (realloc (p, n));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
internal_error (format, arg1, arg2)
|
|
||||||
char *format, *arg1, *arg2;
|
|
||||||
{
|
|
||||||
fprintf (stderr, format, arg1, arg2);
|
|
||||||
fprintf (stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
char example[256];
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
char **result;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
fprintf (stderr, "brace_expand> ");
|
|
||||||
|
|
||||||
if ((!fgets (example, 256, stdin)) ||
|
|
||||||
(strncmp (example, "quit", 4) == 0))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (strlen (example))
|
|
||||||
example[strlen (example) - 1] = '\0';
|
|
||||||
|
|
||||||
result = brace_expand (example);
|
|
||||||
|
|
||||||
for (i = 0; result[i]; i++)
|
|
||||||
printf ("%s\n", result[i]);
|
|
||||||
|
|
||||||
strvec_dispose (result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
|
|
||||||
* end:
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif /* TEST */
|
|
||||||
#endif /* BRACE_EXPANSION */
|
|
104
third_party/bash/break.c
vendored
104
third_party/bash/break.c
vendored
|
@ -1,104 +0,0 @@
|
||||||
/* break.c, created from break.def. */
|
|
||||||
#line 22 "./break.def"
|
|
||||||
|
|
||||||
#line 34 "./break.def"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
static int check_loop_level PARAMS((void));
|
|
||||||
|
|
||||||
/* The depth of while's and until's. */
|
|
||||||
int loop_level = 0;
|
|
||||||
|
|
||||||
/* Non-zero when a "break" instruction is encountered. */
|
|
||||||
int breaking = 0;
|
|
||||||
|
|
||||||
/* Non-zero when we have encountered a continue instruction. */
|
|
||||||
int continuing = 0;
|
|
||||||
|
|
||||||
/* Set up to break x levels, where x defaults to 1, but can be specified
|
|
||||||
as the first argument. */
|
|
||||||
int
|
|
||||||
break_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
intmax_t newbreak;
|
|
||||||
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
if (check_loop_level () == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
(void)get_numeric_arg (list, 1, &newbreak);
|
|
||||||
|
|
||||||
if (newbreak <= 0)
|
|
||||||
{
|
|
||||||
sh_erange (list->word->word, _("loop count"));
|
|
||||||
breaking = loop_level;
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newbreak > loop_level)
|
|
||||||
newbreak = loop_level;
|
|
||||||
|
|
||||||
breaking = newbreak;
|
|
||||||
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
#line 101 "./break.def"
|
|
||||||
|
|
||||||
/* Set up to continue x levels, where x defaults to 1, but can be specified
|
|
||||||
as the first argument. */
|
|
||||||
int
|
|
||||||
continue_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
intmax_t newcont;
|
|
||||||
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
if (check_loop_level () == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
(void)get_numeric_arg (list, 1, &newcont);
|
|
||||||
|
|
||||||
if (newcont <= 0)
|
|
||||||
{
|
|
||||||
sh_erange (list->word->word, _("loop count"));
|
|
||||||
breaking = loop_level;
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newcont > loop_level)
|
|
||||||
newcont = loop_level;
|
|
||||||
|
|
||||||
continuing = newcont;
|
|
||||||
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return non-zero if a break or continue command would be okay.
|
|
||||||
Print an error message if break or continue is meaningless here. */
|
|
||||||
static int
|
|
||||||
check_loop_level ()
|
|
||||||
{
|
|
||||||
#if defined (BREAK_COMPLAINS)
|
|
||||||
if (loop_level == 0 && posixly_correct == 0)
|
|
||||||
builtin_error (_("only meaningful in a `for', `while', or `until' loop"));
|
|
||||||
#endif /* BREAK_COMPLAINS */
|
|
||||||
|
|
||||||
return (loop_level);
|
|
||||||
}
|
|
188
third_party/bash/builtext.h
vendored
188
third_party/bash/builtext.h
vendored
|
@ -1,188 +0,0 @@
|
||||||
/* builtext.h - The list of builtins found in libbuiltins.a. */
|
|
||||||
#if defined (ALIAS)
|
|
||||||
extern int alias_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const alias_doc[];
|
|
||||||
#endif /* ALIAS */
|
|
||||||
#if defined (ALIAS)
|
|
||||||
extern int unalias_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const unalias_doc[];
|
|
||||||
#endif /* ALIAS */
|
|
||||||
#if defined (READLINE)
|
|
||||||
extern int bind_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const bind_doc[];
|
|
||||||
#endif /* READLINE */
|
|
||||||
extern int break_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const break_doc[];
|
|
||||||
extern int continue_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const continue_doc[];
|
|
||||||
extern int builtin_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const builtin_doc[];
|
|
||||||
#if defined (DEBUGGER)
|
|
||||||
extern int caller_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const caller_doc[];
|
|
||||||
#endif /* DEBUGGER */
|
|
||||||
extern int cd_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const cd_doc[];
|
|
||||||
extern int pwd_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const pwd_doc[];
|
|
||||||
extern int colon_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const colon_doc[];
|
|
||||||
extern int colon_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const true_doc[];
|
|
||||||
extern int false_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const false_doc[];
|
|
||||||
extern int command_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const command_doc[];
|
|
||||||
extern int declare_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const declare_doc[];
|
|
||||||
extern int declare_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const typeset_doc[];
|
|
||||||
extern int local_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const local_doc[];
|
|
||||||
#if defined (V9_ECHO)
|
|
||||||
extern int echo_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const echo_doc[];
|
|
||||||
#endif /* V9_ECHO */
|
|
||||||
#if !defined (V9_ECHO)
|
|
||||||
extern int echo_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const echo_doc[];
|
|
||||||
#endif /* !V9_ECHO */
|
|
||||||
extern int enable_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const enable_doc[];
|
|
||||||
extern int eval_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const eval_doc[];
|
|
||||||
extern int getopts_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const getopts_doc[];
|
|
||||||
extern int exec_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const exec_doc[];
|
|
||||||
extern int exit_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const exit_doc[];
|
|
||||||
extern int logout_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const logout_doc[];
|
|
||||||
#if defined (HISTORY)
|
|
||||||
extern int fc_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const fc_doc[];
|
|
||||||
#endif /* HISTORY */
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
extern int fg_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const fg_doc[];
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
extern int bg_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const bg_doc[];
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
extern int hash_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const hash_doc[];
|
|
||||||
#if defined (HELP_BUILTIN)
|
|
||||||
extern int help_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const help_doc[];
|
|
||||||
#endif /* HELP_BUILTIN */
|
|
||||||
#if defined (HISTORY)
|
|
||||||
extern int history_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const history_doc[];
|
|
||||||
#endif /* HISTORY */
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
extern int jobs_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const jobs_doc[];
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
extern int disown_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const disown_doc[];
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
extern int kill_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const kill_doc[];
|
|
||||||
extern int let_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const let_doc[];
|
|
||||||
extern int read_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const read_doc[];
|
|
||||||
extern int return_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const return_doc[];
|
|
||||||
extern int set_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const set_doc[];
|
|
||||||
extern int unset_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const unset_doc[];
|
|
||||||
extern int export_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const export_doc[];
|
|
||||||
extern int readonly_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const readonly_doc[];
|
|
||||||
extern int shift_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const shift_doc[];
|
|
||||||
extern int source_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const source_doc[];
|
|
||||||
extern int source_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const dot_doc[];
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
extern int suspend_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const suspend_doc[];
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
extern int test_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const test_doc[];
|
|
||||||
extern int test_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const test_bracket_doc[];
|
|
||||||
extern int times_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const times_doc[];
|
|
||||||
extern int trap_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const trap_doc[];
|
|
||||||
extern int type_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const type_doc[];
|
|
||||||
#if !defined (_MINIX)
|
|
||||||
extern int ulimit_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const ulimit_doc[];
|
|
||||||
#endif /* !_MINIX */
|
|
||||||
extern int umask_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const umask_doc[];
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
extern int wait_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const wait_doc[];
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
#if !defined (JOB_CONTROL)
|
|
||||||
extern int wait_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const wait_doc[];
|
|
||||||
#endif /* !JOB_CONTROL */
|
|
||||||
extern char * const for_doc[];
|
|
||||||
extern char * const arith_for_doc[];
|
|
||||||
extern char * const select_doc[];
|
|
||||||
extern char * const time_doc[];
|
|
||||||
extern char * const case_doc[];
|
|
||||||
extern char * const if_doc[];
|
|
||||||
extern char * const while_doc[];
|
|
||||||
extern char * const until_doc[];
|
|
||||||
extern char * const coproc_doc[];
|
|
||||||
extern char * const function_doc[];
|
|
||||||
extern char * const grouping_braces_doc[];
|
|
||||||
extern char * const fg_percent_doc[];
|
|
||||||
extern char * const arith_doc[];
|
|
||||||
extern char * const conditional_doc[];
|
|
||||||
extern char * const variable_help_doc[];
|
|
||||||
#if defined (PUSHD_AND_POPD)
|
|
||||||
extern int pushd_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const pushd_doc[];
|
|
||||||
#endif /* PUSHD_AND_POPD */
|
|
||||||
#if defined (PUSHD_AND_POPD)
|
|
||||||
extern int popd_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const popd_doc[];
|
|
||||||
#endif /* PUSHD_AND_POPD */
|
|
||||||
#if defined (PUSHD_AND_POPD)
|
|
||||||
extern int dirs_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const dirs_doc[];
|
|
||||||
#endif /* PUSHD_AND_POPD */
|
|
||||||
extern int shopt_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const shopt_doc[];
|
|
||||||
extern int printf_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const printf_doc[];
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
extern int complete_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const complete_doc[];
|
|
||||||
#endif /* PROGRAMMABLE_COMPLETION */
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
extern int compgen_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const compgen_doc[];
|
|
||||||
#endif /* PROGRAMMABLE_COMPLETION */
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
extern int compopt_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const compopt_doc[];
|
|
||||||
#endif /* PROGRAMMABLE_COMPLETION */
|
|
||||||
extern int mapfile_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const mapfile_doc[];
|
|
||||||
extern int mapfile_builtin PARAMS((WORD_LIST *));
|
|
||||||
extern char * const readarray_doc[];
|
|
2093
third_party/bash/builtins.c
vendored
2093
third_party/bash/builtins.c
vendored
File diff suppressed because it is too large
Load diff
68
third_party/bash/builtins.h
vendored
68
third_party/bash/builtins.h
vendored
|
@ -1,68 +0,0 @@
|
||||||
/* builtins.h -- What a builtin looks like, and where to find them. */
|
|
||||||
|
|
||||||
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GNU Bash, the Bourne Again SHell.
|
|
||||||
|
|
||||||
Bash 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BUILTINS_H
|
|
||||||
#define BUILTINS_H
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "command.h"
|
|
||||||
#include "general.h"
|
|
||||||
|
|
||||||
#if defined (ALIAS)
|
|
||||||
#include "alias.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Flags describing various things about a builtin. */
|
|
||||||
#define BUILTIN_ENABLED 0x01 /* This builtin is enabled. */
|
|
||||||
#define BUILTIN_DELETED 0x02 /* This has been deleted with enable -d. */
|
|
||||||
#define STATIC_BUILTIN 0x04 /* This builtin is not dynamically loaded. */
|
|
||||||
#define SPECIAL_BUILTIN 0x08 /* This is a Posix `special' builtin. */
|
|
||||||
#define ASSIGNMENT_BUILTIN 0x10 /* This builtin takes assignment statements. */
|
|
||||||
#define POSIX_BUILTIN 0x20 /* This builtins is special in the Posix command search order. */
|
|
||||||
#define LOCALVAR_BUILTIN 0x40 /* This builtin creates local variables */
|
|
||||||
#define ARRAYREF_BUILTIN 0x80 /* This builtin takes array references as arguments */
|
|
||||||
|
|
||||||
#define BASE_INDENT 4
|
|
||||||
|
|
||||||
/* The thing that we build the array of builtins out of. */
|
|
||||||
struct builtin {
|
|
||||||
char *name; /* The name that the user types. */
|
|
||||||
sh_builtin_func_t *function; /* The address of the invoked function. */
|
|
||||||
int flags; /* One of the #defines above. */
|
|
||||||
char * const *long_doc; /* NULL terminated array of strings. */
|
|
||||||
const char *short_doc; /* Short version of documentation. */
|
|
||||||
char *handle; /* for future use */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Found in builtins.c, created by builtins/mkbuiltins. */
|
|
||||||
extern int num_shell_builtins; /* Number of shell builtins. */
|
|
||||||
extern struct builtin static_shell_builtins[];
|
|
||||||
extern struct builtin *shell_builtins;
|
|
||||||
extern struct builtin *current_builtin;
|
|
||||||
|
|
||||||
#endif /* BUILTINS_H */
|
|
192
third_party/bash/builtins_alias.c
vendored
192
third_party/bash/builtins_alias.c
vendored
|
@ -1,192 +0,0 @@
|
||||||
/* alias.c, created from alias.def. */
|
|
||||||
#line 42 "./alias.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (ALIAS)
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# include "bashansi.h"
|
|
||||||
# include "bashintl.h"
|
|
||||||
|
|
||||||
# include <stdio.h>
|
|
||||||
# include "shell.h"
|
|
||||||
# include "alias.h"
|
|
||||||
# include "common.h"
|
|
||||||
# include "bashgetopt.h"
|
|
||||||
|
|
||||||
/* Flags for print_alias */
|
|
||||||
#define AL_REUSABLE 0x01
|
|
||||||
|
|
||||||
static void print_alias PARAMS((alias_t *, int));
|
|
||||||
|
|
||||||
/* Hack the alias command in a Korn shell way. */
|
|
||||||
int
|
|
||||||
alias_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int any_failed, offset, pflag, dflags;
|
|
||||||
alias_t **alias_list, *t;
|
|
||||||
char *name, *value;
|
|
||||||
|
|
||||||
dflags = posixly_correct ? 0 : AL_REUSABLE;
|
|
||||||
pflag = 0;
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((offset = internal_getopt (list, "p")) != -1)
|
|
||||||
{
|
|
||||||
switch (offset)
|
|
||||||
{
|
|
||||||
case 'p':
|
|
||||||
pflag = 1;
|
|
||||||
dflags |= AL_REUSABLE;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
if (list == 0 || pflag)
|
|
||||||
{
|
|
||||||
if (aliases == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
alias_list = all_aliases ();
|
|
||||||
|
|
||||||
if (alias_list == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
for (offset = 0; alias_list[offset]; offset++)
|
|
||||||
print_alias (alias_list[offset], dflags);
|
|
||||||
|
|
||||||
free (alias_list); /* XXX - Do not free the strings. */
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
|
||||||
}
|
|
||||||
|
|
||||||
any_failed = 0;
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
name = list->word->word;
|
|
||||||
|
|
||||||
for (offset = 0; name[offset] && name[offset] != '='; offset++)
|
|
||||||
;
|
|
||||||
|
|
||||||
if (offset && name[offset] == '=')
|
|
||||||
{
|
|
||||||
name[offset] = '\0';
|
|
||||||
value = name + offset + 1;
|
|
||||||
|
|
||||||
if (legal_alias_name (name, 0) == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("`%s': invalid alias name"), name);
|
|
||||||
any_failed++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
add_alias (name, value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t = find_alias (name);
|
|
||||||
if (t)
|
|
||||||
print_alias (t, dflags);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_notfound (name);
|
|
||||||
any_failed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
#endif /* ALIAS */
|
|
||||||
|
|
||||||
#line 166 "./alias.def"
|
|
||||||
|
|
||||||
#if defined (ALIAS)
|
|
||||||
/* Remove aliases named in LIST from the aliases database. */
|
|
||||||
int
|
|
||||||
unalias_builtin (list)
|
|
||||||
register WORD_LIST *list;
|
|
||||||
{
|
|
||||||
register alias_t *alias;
|
|
||||||
int opt, aflag;
|
|
||||||
|
|
||||||
aflag = 0;
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "a")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'a':
|
|
||||||
aflag = 1;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
if (aflag)
|
|
||||||
{
|
|
||||||
delete_all_aliases ();
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
{
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
aflag = 0;
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
alias = find_alias (list->word->word);
|
|
||||||
|
|
||||||
if (alias)
|
|
||||||
remove_alias (alias->name);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_notfound (list->word->word);
|
|
||||||
aflag++;
|
|
||||||
}
|
|
||||||
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (aflag ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Output ALIAS in such a way as to allow it to be read back in. */
|
|
||||||
static void
|
|
||||||
print_alias (alias, flags)
|
|
||||||
alias_t *alias;
|
|
||||||
int flags;
|
|
||||||
{
|
|
||||||
char *value;
|
|
||||||
|
|
||||||
value = sh_single_quote (alias->value);
|
|
||||||
if (flags & AL_REUSABLE)
|
|
||||||
printf ("alias %s", (alias->name && alias->name[0] == '-') ? "-- " : "");
|
|
||||||
printf ("%s=%s\n", alias->name, value);
|
|
||||||
free (value);
|
|
||||||
|
|
||||||
fflush (stdout);
|
|
||||||
}
|
|
||||||
#endif /* ALIAS */
|
|
349
third_party/bash/builtins_bind.c
vendored
349
third_party/bash/builtins_bind.c
vendored
|
@ -1,349 +0,0 @@
|
||||||
/* bind.c, created from bind.def. */
|
|
||||||
#line 22 "./bind.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#line 63 "./bind.def"
|
|
||||||
|
|
||||||
#if defined (READLINE)
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#if !defined (errno)
|
|
||||||
extern int errno;
|
|
||||||
#endif /* !errno */
|
|
||||||
|
|
||||||
#include "third_party/readline/readline.h"
|
|
||||||
#include "third_party/readline/history.h"
|
|
||||||
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "bashline.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
static int query_bindings PARAMS((char *));
|
|
||||||
static int unbind_command PARAMS((char *));
|
|
||||||
static int unbind_keyseq PARAMS((char *));
|
|
||||||
|
|
||||||
#define BIND_RETURN(x) do { return_code = x; goto bind_exit; } while (0)
|
|
||||||
|
|
||||||
#define LFLAG 0x0001
|
|
||||||
#define PFLAG 0x0002
|
|
||||||
#define FFLAG 0x0004
|
|
||||||
#define VFLAG 0x0008
|
|
||||||
#define QFLAG 0x0010
|
|
||||||
#define MFLAG 0x0020
|
|
||||||
#define RFLAG 0x0040
|
|
||||||
#define PPFLAG 0x0080
|
|
||||||
#define VVFLAG 0x0100
|
|
||||||
#define SFLAG 0x0200
|
|
||||||
#define SSFLAG 0x0400
|
|
||||||
#define UFLAG 0x0800
|
|
||||||
#define XFLAG 0x1000
|
|
||||||
#define XXFLAG 0x2000
|
|
||||||
|
|
||||||
int
|
|
||||||
bind_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int return_code;
|
|
||||||
Keymap kmap, saved_keymap;
|
|
||||||
int flags, opt;
|
|
||||||
char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq, *cmd_seq, *t;
|
|
||||||
|
|
||||||
if (no_line_editing)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
builtin_error (_("line editing not enabled"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
#else
|
|
||||||
builtin_warning (_("line editing not enabled"));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
kmap = saved_keymap = (Keymap) NULL;
|
|
||||||
flags = 0;
|
|
||||||
initfile = map_name = fun_name = unbind_name = remove_seq = cmd_seq = (char *)NULL;
|
|
||||||
return_code = EXECUTION_SUCCESS;
|
|
||||||
|
|
||||||
if (bash_readline_initialized == 0)
|
|
||||||
initialize_readline ();
|
|
||||||
|
|
||||||
begin_unwind_frame ("bind_builtin");
|
|
||||||
unwind_protect_var (rl_outstream);
|
|
||||||
|
|
||||||
rl_outstream = stdout;
|
|
||||||
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "lvpVPsSXf:q:u:m:r:x:")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'l':
|
|
||||||
flags |= LFLAG;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
flags |= VFLAG;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
flags |= PFLAG;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
flags |= FFLAG;
|
|
||||||
initfile = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
flags |= MFLAG;
|
|
||||||
map_name = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'q':
|
|
||||||
flags |= QFLAG;
|
|
||||||
fun_name = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
flags |= UFLAG;
|
|
||||||
unbind_name = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
flags |= RFLAG;
|
|
||||||
remove_seq = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
flags |= VVFLAG;
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
flags |= PPFLAG;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
flags |= SFLAG;
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
flags |= SSFLAG;
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
flags |= XFLAG;
|
|
||||||
cmd_seq = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'X':
|
|
||||||
flags |= XXFLAG;
|
|
||||||
break;
|
|
||||||
case GETOPT_HELP:
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
BIND_RETURN (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
/* First, see if we need to install a special keymap for this
|
|
||||||
command. Then start on the arguments. */
|
|
||||||
|
|
||||||
if ((flags & MFLAG) && map_name)
|
|
||||||
{
|
|
||||||
kmap = rl_get_keymap_by_name (map_name);
|
|
||||||
if (kmap == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("`%s': invalid keymap name"), map_name);
|
|
||||||
BIND_RETURN (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kmap)
|
|
||||||
{
|
|
||||||
saved_keymap = rl_get_keymap ();
|
|
||||||
rl_set_keymap (kmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX - we need to add exclusive use tests here. It doesn't make sense
|
|
||||||
to use some of these options together. */
|
|
||||||
/* Now hack the option arguments */
|
|
||||||
if (flags & LFLAG)
|
|
||||||
rl_list_funmap_names ();
|
|
||||||
|
|
||||||
if (flags & PFLAG)
|
|
||||||
rl_function_dumper (1);
|
|
||||||
|
|
||||||
if (flags & PPFLAG)
|
|
||||||
rl_function_dumper (0);
|
|
||||||
|
|
||||||
if (flags & SFLAG)
|
|
||||||
rl_macro_dumper (1);
|
|
||||||
|
|
||||||
if (flags & SSFLAG)
|
|
||||||
rl_macro_dumper (0);
|
|
||||||
|
|
||||||
if (flags & VFLAG)
|
|
||||||
rl_variable_dumper (1);
|
|
||||||
|
|
||||||
if (flags & VVFLAG)
|
|
||||||
rl_variable_dumper (0);
|
|
||||||
|
|
||||||
if ((flags & FFLAG) && initfile)
|
|
||||||
{
|
|
||||||
if (rl_read_init_file (initfile) != 0)
|
|
||||||
{
|
|
||||||
t = printable_filename (initfile, 0);
|
|
||||||
builtin_error (_("%s: cannot read: %s"), t, strerror (errno));
|
|
||||||
if (t != initfile)
|
|
||||||
free (t);
|
|
||||||
BIND_RETURN (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & QFLAG) && fun_name)
|
|
||||||
return_code = query_bindings (fun_name);
|
|
||||||
|
|
||||||
if ((flags & UFLAG) && unbind_name)
|
|
||||||
return_code = unbind_command (unbind_name);
|
|
||||||
|
|
||||||
if ((flags & RFLAG) && remove_seq)
|
|
||||||
{
|
|
||||||
opt = unbind_keyseq (remove_seq);
|
|
||||||
BIND_RETURN (opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & XFLAG)
|
|
||||||
return_code = bind_keyseq_to_unix_command (cmd_seq);
|
|
||||||
|
|
||||||
if (flags & XXFLAG)
|
|
||||||
return_code = print_unix_command_map ();
|
|
||||||
|
|
||||||
/* Process the rest of the arguments as binding specifications. */
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
int olen, nlen, d, i;
|
|
||||||
char **obindings, **nbindings;
|
|
||||||
|
|
||||||
obindings = rl_invoking_keyseqs (bash_execute_unix_command);
|
|
||||||
olen = obindings ? strvec_len (obindings) : 0;
|
|
||||||
|
|
||||||
rl_parse_and_bind (list->word->word);
|
|
||||||
|
|
||||||
nbindings = rl_invoking_keyseqs (bash_execute_unix_command);
|
|
||||||
nlen = nbindings ? strvec_len (nbindings) : 0;
|
|
||||||
|
|
||||||
if (nlen < olen) /* fewer bind -x bindings */
|
|
||||||
for (d = olen - nlen, i = 0; i < olen && d > 0; i++)
|
|
||||||
if (nlen == 0 || strvec_search (nbindings, obindings[i]) < 0)
|
|
||||||
{
|
|
||||||
unbind_unix_command (obindings[i]);
|
|
||||||
d--;
|
|
||||||
}
|
|
||||||
|
|
||||||
strvec_dispose (obindings);
|
|
||||||
strvec_dispose (nbindings);
|
|
||||||
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
bind_exit:
|
|
||||||
if (saved_keymap)
|
|
||||||
rl_set_keymap (saved_keymap);
|
|
||||||
|
|
||||||
run_unwind_frame ("bind_builtin");
|
|
||||||
|
|
||||||
if (return_code < 0)
|
|
||||||
return_code = EXECUTION_FAILURE;
|
|
||||||
|
|
||||||
return (sh_chkwrite (return_code));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
query_bindings (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
rl_command_func_t *function;
|
|
||||||
char **keyseqs;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
function = rl_named_function (name);
|
|
||||||
if (function == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("`%s': unknown function name"), name);
|
|
||||||
return EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
keyseqs = rl_invoking_keyseqs (function);
|
|
||||||
|
|
||||||
if (!keyseqs)
|
|
||||||
{
|
|
||||||
printf (_("%s is not bound to any keys.\n"), name);
|
|
||||||
return EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf (_("%s can be invoked via "), name);
|
|
||||||
for (j = 0; j < 5 && keyseqs[j]; j++)
|
|
||||||
printf ("\"%s\"%s", keyseqs[j], keyseqs[j + 1] ? ", " : ".\n");
|
|
||||||
if (keyseqs[j])
|
|
||||||
printf ("...\n");
|
|
||||||
strvec_dispose (keyseqs);
|
|
||||||
return EXECUTION_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
unbind_command (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
rl_command_func_t *function;
|
|
||||||
|
|
||||||
function = rl_named_function (name);
|
|
||||||
if (function == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("`%s': unknown function name"), name);
|
|
||||||
return EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rl_unbind_function_in_map (function, rl_get_keymap ());
|
|
||||||
return EXECUTION_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
unbind_keyseq (seq)
|
|
||||||
char *seq;
|
|
||||||
{
|
|
||||||
char *kseq;
|
|
||||||
int kslen, type;
|
|
||||||
rl_command_func_t *f;
|
|
||||||
|
|
||||||
kseq = (char *)xmalloc ((2 * strlen (seq)) + 1);
|
|
||||||
if (rl_translate_keyseq (seq, kseq, &kslen))
|
|
||||||
{
|
|
||||||
free (kseq);
|
|
||||||
builtin_error (_("`%s': cannot unbind"), seq);
|
|
||||||
return EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
if ((f = rl_function_of_keyseq_len (kseq, kslen, (Keymap)0, &type)) == 0)
|
|
||||||
{
|
|
||||||
free (kseq);
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
if (type == ISKMAP)
|
|
||||||
f = ((Keymap) f)[ANYOTHERKEY].function;
|
|
||||||
|
|
||||||
/* I wish this didn't have to translate the key sequence again, but readline
|
|
||||||
doesn't have a binding function that takes a translated key sequence as
|
|
||||||
an argument. */
|
|
||||||
if (rl_bind_keyseq (seq, (rl_command_func_t *)NULL) != 0)
|
|
||||||
{
|
|
||||||
free (kseq);
|
|
||||||
builtin_error (_("`%s': cannot unbind"), seq);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f == bash_execute_unix_command)
|
|
||||||
unbind_unix_command (seq);
|
|
||||||
|
|
||||||
free (kseq);
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
#endif /* READLINE */
|
|
104
third_party/bash/builtins_break.c
vendored
104
third_party/bash/builtins_break.c
vendored
|
@ -1,104 +0,0 @@
|
||||||
/* break.c, created from break.def. */
|
|
||||||
#line 22 "./break.def"
|
|
||||||
|
|
||||||
#line 34 "./break.def"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
static int check_loop_level PARAMS((void));
|
|
||||||
|
|
||||||
/* The depth of while's and until's. */
|
|
||||||
int loop_level = 0;
|
|
||||||
|
|
||||||
/* Non-zero when a "break" instruction is encountered. */
|
|
||||||
int breaking = 0;
|
|
||||||
|
|
||||||
/* Non-zero when we have encountered a continue instruction. */
|
|
||||||
int continuing = 0;
|
|
||||||
|
|
||||||
/* Set up to break x levels, where x defaults to 1, but can be specified
|
|
||||||
as the first argument. */
|
|
||||||
int
|
|
||||||
break_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
intmax_t newbreak;
|
|
||||||
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
if (check_loop_level () == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
(void)get_numeric_arg (list, 1, &newbreak);
|
|
||||||
|
|
||||||
if (newbreak <= 0)
|
|
||||||
{
|
|
||||||
sh_erange (list->word->word, _("loop count"));
|
|
||||||
breaking = loop_level;
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newbreak > loop_level)
|
|
||||||
newbreak = loop_level;
|
|
||||||
|
|
||||||
breaking = newbreak;
|
|
||||||
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
#line 101 "./break.def"
|
|
||||||
|
|
||||||
/* Set up to continue x levels, where x defaults to 1, but can be specified
|
|
||||||
as the first argument. */
|
|
||||||
int
|
|
||||||
continue_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
intmax_t newcont;
|
|
||||||
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
if (check_loop_level () == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
(void)get_numeric_arg (list, 1, &newcont);
|
|
||||||
|
|
||||||
if (newcont <= 0)
|
|
||||||
{
|
|
||||||
sh_erange (list->word->word, _("loop count"));
|
|
||||||
breaking = loop_level;
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newcont > loop_level)
|
|
||||||
newcont = loop_level;
|
|
||||||
|
|
||||||
continuing = newcont;
|
|
||||||
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return non-zero if a break or continue command would be okay.
|
|
||||||
Print an error message if break or continue is meaningless here. */
|
|
||||||
static int
|
|
||||||
check_loop_level ()
|
|
||||||
{
|
|
||||||
#if defined (BREAK_COMPLAINS)
|
|
||||||
if (loop_level == 0 && posixly_correct == 0)
|
|
||||||
builtin_error (_("only meaningful in a `for', `while', or `until' loop"));
|
|
||||||
#endif /* BREAK_COMPLAINS */
|
|
||||||
|
|
||||||
return (loop_level);
|
|
||||||
}
|
|
54
third_party/bash/builtins_builtin.c
vendored
54
third_party/bash/builtins_builtin.c
vendored
|
@ -1,54 +0,0 @@
|
||||||
/* builtin.c, created from builtin.def. */
|
|
||||||
#line 22 "./builtin.def"
|
|
||||||
|
|
||||||
#line 36 "./builtin.def"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
|
|
||||||
/* Run the command mentioned in list directly, without going through the
|
|
||||||
normal alias/function/builtin/filename lookup process. */
|
|
||||||
int
|
|
||||||
builtin_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
sh_builtin_func_t *function;
|
|
||||||
register char *command;
|
|
||||||
|
|
||||||
if (no_options (list))
|
|
||||||
return (EX_USAGE);
|
|
||||||
list = loptend; /* skip over possible `--' */
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
command = list->word->word;
|
|
||||||
#if defined (DISABLED_BUILTINS)
|
|
||||||
function = builtin_address (command);
|
|
||||||
#else /* !DISABLED_BUILTINS */
|
|
||||||
function = find_shell_builtin (command);
|
|
||||||
#endif /* !DISABLED_BUILTINS */
|
|
||||||
|
|
||||||
if (function == 0)
|
|
||||||
{
|
|
||||||
sh_notbuiltin (command);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this_command_name = command;
|
|
||||||
this_shell_builtin = function; /* overwrite "builtin" as this builtin */
|
|
||||||
list = list->next;
|
|
||||||
return ((*function) (list));
|
|
||||||
}
|
|
||||||
}
|
|
120
third_party/bash/builtins_caller.c
vendored
120
third_party/bash/builtins_caller.c
vendored
|
@ -1,120 +0,0 @@
|
||||||
/* caller.c, created from caller.def. */
|
|
||||||
#line 23 "./caller.def"
|
|
||||||
|
|
||||||
#line 41 "./caller.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "chartypes.h"
|
|
||||||
#include "bashtypes.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "builtext.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
|
|
||||||
#ifdef LOADABLE_BUILTIN
|
|
||||||
# include "builtins.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined (errno)
|
|
||||||
extern int errno;
|
|
||||||
#endif /* !errno */
|
|
||||||
|
|
||||||
int
|
|
||||||
caller_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
#if !defined (ARRAY_VARS)
|
|
||||||
printf ("1 NULL\n");
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
#else
|
|
||||||
SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v;
|
|
||||||
ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
|
|
||||||
char *funcname_s, *source_s, *lineno_s;
|
|
||||||
intmax_t num;
|
|
||||||
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
|
|
||||||
GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
|
|
||||||
GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
|
|
||||||
|
|
||||||
if (bash_lineno_a == 0 || array_empty (bash_lineno_a))
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
|
|
||||||
if (bash_source_a == 0 || array_empty (bash_source_a))
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
|
|
||||||
if (no_options (list))
|
|
||||||
return (EX_USAGE);
|
|
||||||
list = loptend; /* skip over possible `--' */
|
|
||||||
|
|
||||||
/* If there is no argument list, then give short form: line filename. */
|
|
||||||
if (list == 0)
|
|
||||||
{
|
|
||||||
lineno_s = array_reference (bash_lineno_a, 0);
|
|
||||||
source_s = array_reference (bash_source_a, 1);
|
|
||||||
printf("%s %s\n", lineno_s ? lineno_s : "NULL", source_s ? source_s : "NULL");
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (funcname_a == 0 || array_empty (funcname_a))
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
|
|
||||||
if (legal_number (list->word->word, &num))
|
|
||||||
{
|
|
||||||
lineno_s = array_reference (bash_lineno_a, num);
|
|
||||||
source_s = array_reference (bash_source_a, num+1);
|
|
||||||
funcname_s = array_reference (funcname_a, num+1);
|
|
||||||
|
|
||||||
if (lineno_s == NULL|| source_s == NULL || funcname_s == NULL)
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
|
|
||||||
printf("%s %s %s\n", lineno_s, funcname_s, source_s);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_invalidnum (list->word->word);
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LOADABLE_BUILTIN
|
|
||||||
static char *caller_doc[] = {
|
|
||||||
N_("Returns the context of the current subroutine call.\n\
|
|
||||||
\n\
|
|
||||||
Without EXPR, returns \"$line $filename\". With EXPR, returns\n\
|
|
||||||
\"$line $subroutine $filename\"; this extra information can be used to\n\
|
|
||||||
provide a stack trace.\n\
|
|
||||||
\n\
|
|
||||||
The value of EXPR indicates how many call frames to go back before the\n\
|
|
||||||
current one; the top frame is frame 0."),
|
|
||||||
(char *)NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
struct builtin caller_struct = {
|
|
||||||
"caller",
|
|
||||||
caller_builtin,
|
|
||||||
BUILTIN_ENABLED,
|
|
||||||
caller_doc,
|
|
||||||
"caller [EXPR]",
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* LOADABLE_BUILTIN */
|
|
613
third_party/bash/builtins_cd.c
vendored
613
third_party/bash/builtins_cd.c
vendored
|
@ -1,613 +0,0 @@
|
||||||
/* cd.c, created from cd.def. */
|
|
||||||
#line 22 "./cd.def"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashtypes.h"
|
|
||||||
#include "posixdir.h"
|
|
||||||
#include "posixstat.h"
|
|
||||||
#if defined (HAVE_SYS_PARAM_H)
|
|
||||||
#include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include "tilde.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "flags.h"
|
|
||||||
#include "maxpath.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
|
|
||||||
#if !defined (errno)
|
|
||||||
extern int errno;
|
|
||||||
#endif /* !errno */
|
|
||||||
|
|
||||||
extern const char * const bash_getcwd_errstr;
|
|
||||||
|
|
||||||
static int bindpwd PARAMS((int));
|
|
||||||
static int setpwd PARAMS((char *));
|
|
||||||
static char *resetpwd PARAMS((char *));
|
|
||||||
static int change_to_directory PARAMS((char *, int, int));
|
|
||||||
|
|
||||||
static int cdxattr PARAMS((char *, char **));
|
|
||||||
static void resetxattr PARAMS((void));
|
|
||||||
|
|
||||||
/* Change this to 1 to get cd spelling correction by default. */
|
|
||||||
int cdspelling = 0;
|
|
||||||
|
|
||||||
int cdable_vars;
|
|
||||||
|
|
||||||
static int eflag; /* file scope so bindpwd() can see it */
|
|
||||||
static int xattrflag; /* O_XATTR support for openat */
|
|
||||||
static int xattrfd = -1;
|
|
||||||
|
|
||||||
#line 115 "./cd.def"
|
|
||||||
|
|
||||||
/* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
|
|
||||||
static int
|
|
||||||
setpwd (dirname)
|
|
||||||
char *dirname;
|
|
||||||
{
|
|
||||||
int old_anm;
|
|
||||||
SHELL_VAR *tvar;
|
|
||||||
|
|
||||||
old_anm = array_needs_making;
|
|
||||||
tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
|
|
||||||
if (tvar && readonly_p (tvar))
|
|
||||||
return EXECUTION_FAILURE;
|
|
||||||
if (tvar && old_anm == 0 && array_needs_making && exported_p (tvar))
|
|
||||||
{
|
|
||||||
update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
|
|
||||||
array_needs_making = 0;
|
|
||||||
}
|
|
||||||
return EXECUTION_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
bindpwd (no_symlinks)
|
|
||||||
int no_symlinks;
|
|
||||||
{
|
|
||||||
char *dirname, *pwdvar;
|
|
||||||
int old_anm, r, canon_failed;
|
|
||||||
SHELL_VAR *tvar;
|
|
||||||
|
|
||||||
r = sh_chkwrite (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
#define tcwd the_current_working_directory
|
|
||||||
dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
|
|
||||||
: get_working_directory ("cd");
|
|
||||||
#undef tcwd
|
|
||||||
|
|
||||||
/* If canonicalization fails, reset dirname to the_current_working_directory */
|
|
||||||
canon_failed = 0;
|
|
||||||
if (dirname == 0)
|
|
||||||
{
|
|
||||||
canon_failed = 1;
|
|
||||||
dirname = the_current_working_directory;
|
|
||||||
}
|
|
||||||
|
|
||||||
old_anm = array_needs_making;
|
|
||||||
pwdvar = get_string_value ("PWD");
|
|
||||||
|
|
||||||
tvar = bind_variable ("OLDPWD", pwdvar, 0);
|
|
||||||
if (tvar && readonly_p (tvar))
|
|
||||||
r = EXECUTION_FAILURE;
|
|
||||||
|
|
||||||
if (old_anm == 0 && array_needs_making && exported_p (tvar))
|
|
||||||
{
|
|
||||||
update_export_env_inplace ("OLDPWD=", 7, pwdvar);
|
|
||||||
array_needs_making = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setpwd (dirname) == EXECUTION_FAILURE)
|
|
||||||
r = EXECUTION_FAILURE;
|
|
||||||
if (canon_failed && eflag)
|
|
||||||
r = EXECUTION_FAILURE;
|
|
||||||
|
|
||||||
if (dirname && dirname != the_current_working_directory)
|
|
||||||
free (dirname);
|
|
||||||
|
|
||||||
return (r);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call get_working_directory to reset the value of
|
|
||||||
the_current_working_directory () */
|
|
||||||
static char *
|
|
||||||
resetpwd (caller)
|
|
||||||
char *caller;
|
|
||||||
{
|
|
||||||
char *tdir;
|
|
||||||
|
|
||||||
FREE (the_current_working_directory);
|
|
||||||
the_current_working_directory = (char *)NULL;
|
|
||||||
tdir = get_working_directory (caller);
|
|
||||||
return (tdir);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
cdxattr (dir, ndirp)
|
|
||||||
char *dir; /* don't assume we can always free DIR */
|
|
||||||
char **ndirp; /* return new constructed directory name */
|
|
||||||
{
|
|
||||||
#if defined (O_XATTR)
|
|
||||||
int apfd, fd, r, e;
|
|
||||||
char buf[11+40+40]; /* construct new `fake' path for pwd */
|
|
||||||
|
|
||||||
apfd = openat (AT_FDCWD, dir, O_RDONLY|O_NONBLOCK);
|
|
||||||
if (apfd < 0)
|
|
||||||
return -1;
|
|
||||||
fd = openat (apfd, ".", O_XATTR);
|
|
||||||
e = errno;
|
|
||||||
close (apfd); /* ignore close error for now */
|
|
||||||
errno = e;
|
|
||||||
if (fd < 0)
|
|
||||||
return -1;
|
|
||||||
r = fchdir (fd); /* assume fchdir exists everywhere with O_XATTR */
|
|
||||||
if (r < 0)
|
|
||||||
{
|
|
||||||
close (fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* NFSv4 and ZFS extended attribute directories do not have names which are
|
|
||||||
visible in the standard Unix directory tree structure. To ensure we have
|
|
||||||
a valid name for $PWD, we synthesize one under /proc, but to keep that
|
|
||||||
path valid, we need to keep the file descriptor open as long as we are in
|
|
||||||
this directory. This imposes a certain structure on /proc. */
|
|
||||||
if (ndirp)
|
|
||||||
{
|
|
||||||
sprintf (buf, "/proc/%d/fd/%d", getpid(), fd);
|
|
||||||
*ndirp = savestring (buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xattrfd >= 0)
|
|
||||||
close (xattrfd);
|
|
||||||
xattrfd = fd;
|
|
||||||
|
|
||||||
return r;
|
|
||||||
#else
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean up the O_XATTR baggage. Currently only closes xattrfd */
|
|
||||||
static void
|
|
||||||
resetxattr ()
|
|
||||||
{
|
|
||||||
#if defined (O_XATTR)
|
|
||||||
if (xattrfd >= 0)
|
|
||||||
{
|
|
||||||
close (xattrfd);
|
|
||||||
xattrfd = -1;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
xattrfd = -1; /* not strictly necessary */
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LCD_DOVARS 0x001
|
|
||||||
#define LCD_DOSPELL 0x002
|
|
||||||
#define LCD_PRINTPATH 0x004
|
|
||||||
#define LCD_FREEDIRNAME 0x008
|
|
||||||
|
|
||||||
/* This builtin is ultimately the way that all user-visible commands should
|
|
||||||
change the current working directory. It is called by cd_to_string (),
|
|
||||||
so the programming interface is simple, and it handles errors and
|
|
||||||
restrictions properly. */
|
|
||||||
int
|
|
||||||
cd_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
char *dirname, *cdpath, *path, *temp;
|
|
||||||
int path_index, no_symlinks, opt, lflag, e;
|
|
||||||
|
|
||||||
#if defined (RESTRICTED_SHELL)
|
|
||||||
if (restricted)
|
|
||||||
{
|
|
||||||
sh_restricted ((char *)NULL);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
#endif /* RESTRICTED_SHELL */
|
|
||||||
|
|
||||||
eflag = 0;
|
|
||||||
no_symlinks = no_symbolic_links;
|
|
||||||
xattrflag = 0;
|
|
||||||
reset_internal_getopt ();
|
|
||||||
#if defined (O_XATTR)
|
|
||||||
while ((opt = internal_getopt (list, "eLP@")) != -1)
|
|
||||||
#else
|
|
||||||
while ((opt = internal_getopt (list, "eLP")) != -1)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'P':
|
|
||||||
no_symlinks = 1;
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
no_symlinks = 0;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
eflag = 1;
|
|
||||||
break;
|
|
||||||
#if defined (O_XATTR)
|
|
||||||
case '@':
|
|
||||||
xattrflag = 1;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
lflag = (cdable_vars ? LCD_DOVARS : 0) |
|
|
||||||
((interactive && cdspelling) ? LCD_DOSPELL : 0);
|
|
||||||
if (eflag && no_symlinks == 0)
|
|
||||||
eflag = 0;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
{
|
|
||||||
/* `cd' without arguments is equivalent to `cd $HOME' */
|
|
||||||
dirname = get_string_value ("HOME");
|
|
||||||
|
|
||||||
if (dirname == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("HOME not set"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
lflag = 0;
|
|
||||||
}
|
|
||||||
#if defined (CD_COMPLAINS)
|
|
||||||
else if (list->next)
|
|
||||||
{
|
|
||||||
builtin_error (_("too many arguments"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
else if (list->word->word[0] == '\0')
|
|
||||||
{
|
|
||||||
builtin_error (_("null directory"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
|
|
||||||
{
|
|
||||||
/* This is `cd -', equivalent to `cd $OLDPWD' */
|
|
||||||
dirname = get_string_value ("OLDPWD");
|
|
||||||
|
|
||||||
if (dirname == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("OLDPWD not set"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
lflag = interactive ? LCD_PRINTPATH : 0;
|
|
||||||
#else
|
|
||||||
lflag = LCD_PRINTPATH; /* According to SUSv3 */
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if (absolute_pathname (list->word->word))
|
|
||||||
dirname = list->word->word;
|
|
||||||
else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
|
|
||||||
{
|
|
||||||
dirname = list->word->word;
|
|
||||||
|
|
||||||
/* Find directory in $CDPATH. */
|
|
||||||
path_index = 0;
|
|
||||||
while (path = extract_colon_unit (cdpath, &path_index))
|
|
||||||
{
|
|
||||||
/* OPT is 1 if the path element is non-empty */
|
|
||||||
opt = path[0] != '\0';
|
|
||||||
temp = sh_makepath (path, dirname, MP_DOTILDE);
|
|
||||||
free (path);
|
|
||||||
|
|
||||||
if (change_to_directory (temp, no_symlinks, xattrflag))
|
|
||||||
{
|
|
||||||
/* POSIX.2 says that if a nonempty directory from CDPATH
|
|
||||||
is used to find the directory to change to, the new
|
|
||||||
directory name is echoed to stdout, whether or not
|
|
||||||
the shell is interactive. */
|
|
||||||
if (opt && (path = no_symlinks ? temp : the_current_working_directory))
|
|
||||||
printf ("%s\n", path);
|
|
||||||
|
|
||||||
free (temp);
|
|
||||||
#if 0
|
|
||||||
/* Posix.2 says that after using CDPATH, the resultant
|
|
||||||
value of $PWD will not contain `.' or `..'. */
|
|
||||||
return (bindpwd (posixly_correct || no_symlinks));
|
|
||||||
#else
|
|
||||||
return (bindpwd (no_symlinks));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
free (temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* changed for bash-4.2 Posix cd description steps 5-6 */
|
|
||||||
/* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
|
|
||||||
try the current directory, so we just punt now with an error
|
|
||||||
message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
|
|
||||||
is so we don't mistakenly treat a CDPATH value of "" as not
|
|
||||||
specifying the current directory. */
|
|
||||||
if (posixly_correct && cdpath[0])
|
|
||||||
{
|
|
||||||
builtin_error ("%s: %s", dirname, strerror (ENOENT));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
dirname = list->word->word;
|
|
||||||
|
|
||||||
/* When we get here, DIRNAME is the directory to change to. If we
|
|
||||||
chdir successfully, just return. */
|
|
||||||
if (change_to_directory (dirname, no_symlinks, xattrflag))
|
|
||||||
{
|
|
||||||
if (lflag & LCD_PRINTPATH)
|
|
||||||
printf ("%s\n", dirname);
|
|
||||||
return (bindpwd (no_symlinks));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the user requests it, then perhaps this is the name of
|
|
||||||
a shell variable, whose value contains the directory to
|
|
||||||
change to. */
|
|
||||||
if (lflag & LCD_DOVARS)
|
|
||||||
{
|
|
||||||
temp = get_string_value (dirname);
|
|
||||||
if (temp && change_to_directory (temp, no_symlinks, xattrflag))
|
|
||||||
{
|
|
||||||
printf ("%s\n", temp);
|
|
||||||
return (bindpwd (no_symlinks));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the user requests it, try to find a directory name similar in
|
|
||||||
spelling to the one requested, in case the user made a simple
|
|
||||||
typo. This is similar to the UNIX 8th and 9th Edition shells. */
|
|
||||||
if (lflag & LCD_DOSPELL)
|
|
||||||
{
|
|
||||||
temp = dirspell (dirname);
|
|
||||||
if (temp && change_to_directory (temp, no_symlinks, xattrflag))
|
|
||||||
{
|
|
||||||
printf ("%s\n", temp);
|
|
||||||
free (temp);
|
|
||||||
return (bindpwd (no_symlinks));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
FREE (temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
e = errno;
|
|
||||||
temp = printable_filename (dirname, 0);
|
|
||||||
builtin_error ("%s: %s", temp, strerror (e));
|
|
||||||
if (temp != dirname)
|
|
||||||
free (temp);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#line 478 "./cd.def"
|
|
||||||
|
|
||||||
/* Non-zero means that pwd always prints the physical directory, without
|
|
||||||
symbolic links. */
|
|
||||||
static int verbatim_pwd;
|
|
||||||
|
|
||||||
/* Print the name of the current working directory. */
|
|
||||||
int
|
|
||||||
pwd_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
char *directory;
|
|
||||||
int opt, pflag;
|
|
||||||
|
|
||||||
verbatim_pwd = no_symbolic_links;
|
|
||||||
pflag = 0;
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "LP")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'P':
|
|
||||||
verbatim_pwd = pflag = 1;
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
verbatim_pwd = 0;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
#define tcwd the_current_working_directory
|
|
||||||
|
|
||||||
directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
|
|
||||||
: get_working_directory ("pwd");
|
|
||||||
|
|
||||||
/* Try again using getcwd() if canonicalization fails (for instance, if
|
|
||||||
the file system has changed state underneath bash). */
|
|
||||||
if ((tcwd && directory == 0) ||
|
|
||||||
(posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
|
|
||||||
{
|
|
||||||
if (directory && directory != tcwd)
|
|
||||||
free (directory);
|
|
||||||
directory = resetpwd ("pwd");
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef tcwd
|
|
||||||
|
|
||||||
if (directory)
|
|
||||||
{
|
|
||||||
opt = EXECUTION_SUCCESS;
|
|
||||||
printf ("%s\n", directory);
|
|
||||||
/* This is dumb but posix-mandated. */
|
|
||||||
if (posixly_correct && pflag)
|
|
||||||
opt = setpwd (directory);
|
|
||||||
if (directory != the_current_working_directory)
|
|
||||||
free (directory);
|
|
||||||
return (sh_chkwrite (opt));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do the work of changing to the directory NEWDIR. Handle symbolic
|
|
||||||
link following, etc. This function *must* return with
|
|
||||||
the_current_working_directory either set to NULL (in which case
|
|
||||||
getcwd() will eventually be called), or set to a string corresponding
|
|
||||||
to the working directory. Return 1 on success, 0 on failure. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
change_to_directory (newdir, nolinks, xattr)
|
|
||||||
char *newdir;
|
|
||||||
int nolinks, xattr;
|
|
||||||
{
|
|
||||||
char *t, *tdir, *ndir;
|
|
||||||
int err, canon_failed, r, ndlen;
|
|
||||||
|
|
||||||
tdir = (char *)NULL;
|
|
||||||
|
|
||||||
if (the_current_working_directory == 0)
|
|
||||||
{
|
|
||||||
t = get_working_directory ("chdir");
|
|
||||||
FREE (t);
|
|
||||||
}
|
|
||||||
|
|
||||||
t = make_absolute (newdir, the_current_working_directory);
|
|
||||||
|
|
||||||
/* TDIR is either the canonicalized absolute pathname of NEWDIR
|
|
||||||
(nolinks == 0) or the absolute physical pathname of NEWDIR
|
|
||||||
(nolinks != 0). */
|
|
||||||
tdir = nolinks ? sh_physpath (t, 0)
|
|
||||||
: sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
|
|
||||||
|
|
||||||
ndlen = strlen (newdir);
|
|
||||||
|
|
||||||
/* Use the canonicalized version of NEWDIR, or, if canonicalization
|
|
||||||
failed, use the non-canonical form. */
|
|
||||||
canon_failed = 0;
|
|
||||||
if (tdir && *tdir)
|
|
||||||
free (t);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FREE (tdir);
|
|
||||||
tdir = t;
|
|
||||||
canon_failed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
|
|
||||||
returns NULL (because it checks the path, it will return NULL if the
|
|
||||||
resolved path doesn't exist), fail immediately. */
|
|
||||||
#if defined (ENAMETOOLONG)
|
|
||||||
if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
|
|
||||||
#else
|
|
||||||
if (posixly_correct && nolinks == 0 && canon_failed && ndlen > PATH_MAX)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#if defined ENAMETOOLONG
|
|
||||||
if (errno != ENOENT && errno != ENAMETOOLONG)
|
|
||||||
#else
|
|
||||||
if (errno != ENOENT)
|
|
||||||
#endif
|
|
||||||
errno = ENOTDIR;
|
|
||||||
free (tdir);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (O_XATTR)
|
|
||||||
if (xattrflag)
|
|
||||||
{
|
|
||||||
r = cdxattr (nolinks ? newdir : tdir, &ndir);
|
|
||||||
if (r >= 0)
|
|
||||||
{
|
|
||||||
canon_failed = 0;
|
|
||||||
free (tdir);
|
|
||||||
tdir = ndir;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
err = errno;
|
|
||||||
free (tdir);
|
|
||||||
errno = err;
|
|
||||||
return (0); /* no xattr */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
r = chdir (nolinks ? newdir : tdir);
|
|
||||||
if (r >= 0)
|
|
||||||
resetxattr ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the chdir succeeds, update the_current_working_directory. */
|
|
||||||
if (r == 0)
|
|
||||||
{
|
|
||||||
/* If canonicalization failed, but the chdir succeeded, reset the
|
|
||||||
shell's idea of the_current_working_directory. */
|
|
||||||
if (canon_failed)
|
|
||||||
{
|
|
||||||
t = resetpwd ("cd");
|
|
||||||
if (t == 0)
|
|
||||||
set_working_directory (tdir);
|
|
||||||
else
|
|
||||||
free (t);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
set_working_directory (tdir);
|
|
||||||
|
|
||||||
free (tdir);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We failed to change to the appropriate directory name. If we tried
|
|
||||||
what the user passed (nolinks != 0), punt now. */
|
|
||||||
if (nolinks)
|
|
||||||
{
|
|
||||||
free (tdir);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = errno;
|
|
||||||
|
|
||||||
/* We're not in physical mode (nolinks == 0), but we failed to change to
|
|
||||||
the canonicalized directory name (TDIR). Try what the user passed
|
|
||||||
verbatim. If we succeed, reinitialize the_current_working_directory.
|
|
||||||
POSIX requires that we just fail here, so we do in posix mode. */
|
|
||||||
if (posixly_correct == 0 && chdir (newdir) == 0)
|
|
||||||
{
|
|
||||||
t = resetpwd ("cd");
|
|
||||||
if (t == 0)
|
|
||||||
set_working_directory (tdir);
|
|
||||||
else
|
|
||||||
free (t);
|
|
||||||
|
|
||||||
r = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
errno = err;
|
|
||||||
r = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
free (tdir);
|
|
||||||
return r;
|
|
||||||
}
|
|
33
third_party/bash/builtins_colon.c
vendored
33
third_party/bash/builtins_colon.c
vendored
|
@ -1,33 +0,0 @@
|
||||||
/* colon.c, created from colon.def. */
|
|
||||||
#line 22 "./colon.def"
|
|
||||||
|
|
||||||
#line 34 "./colon.def"
|
|
||||||
|
|
||||||
#line 43 "./colon.def"
|
|
||||||
|
|
||||||
#line 52 "./colon.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "shell.h"
|
|
||||||
|
|
||||||
/* Return a successful result. */
|
|
||||||
int
|
|
||||||
colon_builtin (ignore)
|
|
||||||
WORD_LIST *ignore;
|
|
||||||
{
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return an unsuccessful result. */
|
|
||||||
int
|
|
||||||
false_builtin (ignore)
|
|
||||||
WORD_LIST *ignore;
|
|
||||||
{
|
|
||||||
return (1);
|
|
||||||
}
|
|
107
third_party/bash/builtins_command.c
vendored
107
third_party/bash/builtins_command.c
vendored
|
@ -1,107 +0,0 @@
|
||||||
/* command.c, created from command.def. */
|
|
||||||
#line 22 "./command.def"
|
|
||||||
|
|
||||||
#line 41 "./command.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "flags.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#if defined (_CS_PATH) && defined (HAVE_CONFSTR) && !HAVE_DECL_CONFSTR
|
|
||||||
extern size_t confstr PARAMS((int, char *, size_t));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Run the commands mentioned in LIST without paying attention to shell
|
|
||||||
functions. */
|
|
||||||
int
|
|
||||||
command_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int result, verbose, use_standard_path, opt;
|
|
||||||
COMMAND *command;
|
|
||||||
|
|
||||||
verbose = use_standard_path = 0;
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "pvV")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'p':
|
|
||||||
use_standard_path = CDESC_STDPATH;
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
verbose = CDESC_SHORTDESC|CDESC_ABSPATH; /* look in common.h for constants */
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
verbose = CDESC_REUSABLE; /* ditto */
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
#if defined (RESTRICTED_SHELL)
|
|
||||||
if (use_standard_path && restricted)
|
|
||||||
{
|
|
||||||
sh_restricted ("-p");
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
int found, any_found;
|
|
||||||
|
|
||||||
for (any_found = 0; list; list = list->next)
|
|
||||||
{
|
|
||||||
found = describe_command (list->word->word, verbose|use_standard_path);
|
|
||||||
|
|
||||||
if (found == 0 && verbose != CDESC_REUSABLE)
|
|
||||||
sh_notfound (list->word->word);
|
|
||||||
|
|
||||||
any_found += found;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (any_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
begin_unwind_frame ("command_builtin");
|
|
||||||
|
|
||||||
#define COMMAND_BUILTIN_FLAGS (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN | (use_standard_path ? CMD_STDPATH : 0))
|
|
||||||
|
|
||||||
INTERNAL_DEBUG (("command_builtin: running execute_command for `%s'", list->word->word));
|
|
||||||
|
|
||||||
/* We don't want this to be reparsed (consider command echo 'foo &'), so
|
|
||||||
just make a simple_command structure and call execute_command with it. */
|
|
||||||
command = make_bare_simple_command ();
|
|
||||||
command->value.Simple->words = (WORD_LIST *)copy_word_list (list);
|
|
||||||
command->value.Simple->redirects = (REDIRECT *)NULL;
|
|
||||||
command->flags |= COMMAND_BUILTIN_FLAGS;
|
|
||||||
command->value.Simple->flags |= COMMAND_BUILTIN_FLAGS;
|
|
||||||
|
|
||||||
add_unwind_protect ((char *)dispose_command, command);
|
|
||||||
result = execute_command (command);
|
|
||||||
|
|
||||||
run_unwind_frame ("command_builtin");
|
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
|
805
third_party/bash/builtins_complete.c
vendored
805
third_party/bash/builtins_complete.c
vendored
|
@ -1,805 +0,0 @@
|
||||||
/* complete.c, created from complete.def. */
|
|
||||||
#line 22 "./complete.def"
|
|
||||||
|
|
||||||
#line 51 "./complete.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "bashtypes.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "pcomplete.h"
|
|
||||||
#include "bashline.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
|
|
||||||
#include "third_party/readline/readline.h"
|
|
||||||
|
|
||||||
#define STRDUP(x) ((x) ? savestring (x) : (char *)NULL)
|
|
||||||
|
|
||||||
/* Structure containing all the non-action (binary) options; filled in by
|
|
||||||
build_actions(). */
|
|
||||||
struct _optflags {
|
|
||||||
int pflag;
|
|
||||||
int rflag;
|
|
||||||
int Dflag;
|
|
||||||
int Eflag;
|
|
||||||
int Iflag;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int find_compact PARAMS((char *));
|
|
||||||
static int find_compopt PARAMS((char *));
|
|
||||||
|
|
||||||
static int build_actions PARAMS((WORD_LIST *, struct _optflags *, unsigned long *, unsigned long *));
|
|
||||||
|
|
||||||
static int remove_cmd_completions PARAMS((WORD_LIST *));
|
|
||||||
|
|
||||||
static int print_one_completion PARAMS((char *, COMPSPEC *));
|
|
||||||
static int print_compitem PARAMS((BUCKET_CONTENTS *));
|
|
||||||
static void print_compopts PARAMS((const char *, COMPSPEC *, int));
|
|
||||||
static void print_all_completions PARAMS((void));
|
|
||||||
static int print_cmd_completions PARAMS((WORD_LIST *));
|
|
||||||
|
|
||||||
static void print_compoptions PARAMS((unsigned long, int));
|
|
||||||
static void print_compactions PARAMS((unsigned long));
|
|
||||||
static void print_arg PARAMS((const char *, const char *, int));
|
|
||||||
static void print_cmd_name PARAMS((const char *));
|
|
||||||
|
|
||||||
static char *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg;
|
|
||||||
|
|
||||||
static const struct _compacts {
|
|
||||||
const char * const actname;
|
|
||||||
unsigned long actflag;
|
|
||||||
int actopt;
|
|
||||||
} compacts[] = {
|
|
||||||
{ "alias", CA_ALIAS, 'a' },
|
|
||||||
{ "arrayvar", CA_ARRAYVAR, 0 },
|
|
||||||
{ "binding", CA_BINDING, 0 },
|
|
||||||
{ "builtin", CA_BUILTIN, 'b' },
|
|
||||||
{ "command", CA_COMMAND, 'c' },
|
|
||||||
{ "directory", CA_DIRECTORY, 'd' },
|
|
||||||
{ "disabled", CA_DISABLED, 0 },
|
|
||||||
{ "enabled", CA_ENABLED, 0 },
|
|
||||||
{ "export", CA_EXPORT, 'e' },
|
|
||||||
{ "file", CA_FILE, 'f' },
|
|
||||||
{ "function", CA_FUNCTION, 0 },
|
|
||||||
{ "helptopic", CA_HELPTOPIC, 0 },
|
|
||||||
{ "hostname", CA_HOSTNAME, 0 },
|
|
||||||
{ "group", CA_GROUP, 'g' },
|
|
||||||
{ "job", CA_JOB, 'j' },
|
|
||||||
{ "keyword", CA_KEYWORD, 'k' },
|
|
||||||
{ "running", CA_RUNNING, 0 },
|
|
||||||
{ "service", CA_SERVICE, 's' },
|
|
||||||
{ "setopt", CA_SETOPT, 0 },
|
|
||||||
{ "shopt", CA_SHOPT, 0 },
|
|
||||||
{ "signal", CA_SIGNAL, 0 },
|
|
||||||
{ "stopped", CA_STOPPED, 0 },
|
|
||||||
{ "user", CA_USER, 'u' },
|
|
||||||
{ "variable", CA_VARIABLE, 'v' },
|
|
||||||
{ (char *)NULL, 0, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* This should be a STRING_INT_ALIST */
|
|
||||||
static const struct _compopt {
|
|
||||||
const char * const optname;
|
|
||||||
unsigned long optflag;
|
|
||||||
} compopts[] = {
|
|
||||||
{ "bashdefault", COPT_BASHDEFAULT },
|
|
||||||
{ "default", COPT_DEFAULT },
|
|
||||||
{ "dirnames", COPT_DIRNAMES },
|
|
||||||
{ "filenames",COPT_FILENAMES},
|
|
||||||
{ "noquote", COPT_NOQUOTE },
|
|
||||||
{ "nosort", COPT_NOSORT },
|
|
||||||
{ "nospace", COPT_NOSPACE },
|
|
||||||
{ "plusdirs", COPT_PLUSDIRS },
|
|
||||||
{ (char *)NULL, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
find_compact (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
for (i = 0; compacts[i].actname; i++)
|
|
||||||
if (STREQ (name, compacts[i].actname))
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
find_compopt (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
for (i = 0; compopts[i].optname; i++)
|
|
||||||
if (STREQ (name, compopts[i].optname))
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build the actions and compspec options from the options specified in LIST.
|
|
||||||
ACTP is a pointer to an unsigned long in which to place the bitmap of
|
|
||||||
actions. OPTP is a pointer to an unsigned long in which to place the
|
|
||||||
bitmap of compspec options (arguments to `-o'). PP, if non-null, gets 1
|
|
||||||
if -p is supplied; RP, if non-null, gets 1 if -r is supplied.
|
|
||||||
If either is null, the corresponding option generates an error.
|
|
||||||
This also sets variables corresponding to options that take arguments as
|
|
||||||
a side effect; the caller should ensure that those variables are set to
|
|
||||||
NULL before calling build_actions. Return value:
|
|
||||||
EX_USAGE = bad option
|
|
||||||
EXECUTION_SUCCESS = some options supplied
|
|
||||||
EXECUTION_FAILURE = no options supplied
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
build_actions (list, flagp, actp, optp)
|
|
||||||
WORD_LIST *list;
|
|
||||||
struct _optflags *flagp;
|
|
||||||
unsigned long *actp, *optp;
|
|
||||||
{
|
|
||||||
int opt, ind, opt_given;
|
|
||||||
unsigned long acts, copts;
|
|
||||||
WORD_DESC w;
|
|
||||||
|
|
||||||
acts = copts = (unsigned long)0L;
|
|
||||||
opt_given = 0;
|
|
||||||
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:DEI")) != -1)
|
|
||||||
{
|
|
||||||
opt_given = 1;
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'r':
|
|
||||||
if (flagp)
|
|
||||||
{
|
|
||||||
flagp->rflag = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_invalidopt ("-r");
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
if (flagp)
|
|
||||||
{
|
|
||||||
flagp->pflag = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_invalidopt ("-p");
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'a':
|
|
||||||
acts |= CA_ALIAS;
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
acts |= CA_BUILTIN;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
acts |= CA_COMMAND;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
acts |= CA_DIRECTORY;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
acts |= CA_EXPORT;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
acts |= CA_FILE;
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
acts |= CA_GROUP;
|
|
||||||
break;
|
|
||||||
case 'j':
|
|
||||||
acts |= CA_JOB;
|
|
||||||
break;
|
|
||||||
case 'k':
|
|
||||||
acts |= CA_KEYWORD;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
acts |= CA_SERVICE;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
acts |= CA_USER;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
acts |= CA_VARIABLE;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
ind = find_compopt (list_optarg);
|
|
||||||
if (ind < 0)
|
|
||||||
{
|
|
||||||
sh_invalidoptname (list_optarg);
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
copts |= compopts[ind].optflag;
|
|
||||||
break;
|
|
||||||
case 'A':
|
|
||||||
ind = find_compact (list_optarg);
|
|
||||||
if (ind < 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: invalid action name"), list_optarg);
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
acts |= compacts[ind].actflag;
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
Carg = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
if (flagp)
|
|
||||||
{
|
|
||||||
flagp->Dflag = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_invalidopt ("-D");
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
case 'E':
|
|
||||||
if (flagp)
|
|
||||||
{
|
|
||||||
flagp->Eflag = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_invalidopt ("-E");
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
case 'I':
|
|
||||||
if (flagp)
|
|
||||||
{
|
|
||||||
flagp->Iflag = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_invalidopt ("-I");
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
case 'F':
|
|
||||||
w.word = Farg = list_optarg;
|
|
||||||
w.flags = 0;
|
|
||||||
if (check_identifier (&w, posixly_correct) == 0 || strpbrk (Farg, shell_break_chars) != 0)
|
|
||||||
{
|
|
||||||
sh_invalidid (Farg);
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'G':
|
|
||||||
Garg = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
Parg = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
Sarg = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'W':
|
|
||||||
Warg = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'X':
|
|
||||||
Xarg = list_optarg;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*actp = acts;
|
|
||||||
*optp = copts;
|
|
||||||
|
|
||||||
return (opt_given ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add, remove, and display completion specifiers. */
|
|
||||||
int
|
|
||||||
complete_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int opt_given, rval;
|
|
||||||
unsigned long acts, copts;
|
|
||||||
COMPSPEC *cs;
|
|
||||||
struct _optflags oflags;
|
|
||||||
WORD_LIST *l, *wl;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
{
|
|
||||||
print_all_completions ();
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
opt_given = oflags.pflag = oflags.rflag = 0;
|
|
||||||
oflags.Dflag = oflags.Eflag = oflags.Iflag = 0;
|
|
||||||
|
|
||||||
acts = copts = (unsigned long)0L;
|
|
||||||
Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
|
|
||||||
cs = (COMPSPEC *)NULL;
|
|
||||||
|
|
||||||
/* Build the actions from the arguments. Also sets the [A-Z]arg variables
|
|
||||||
as a side effect if they are supplied as options. */
|
|
||||||
rval = build_actions (list, &oflags, &acts, &copts);
|
|
||||||
if (rval == EX_USAGE)
|
|
||||||
return (rval);
|
|
||||||
opt_given = rval != EXECUTION_FAILURE;
|
|
||||||
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
if (oflags.Dflag)
|
|
||||||
wl = make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL);
|
|
||||||
else if (oflags.Eflag)
|
|
||||||
wl = make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST *)NULL);
|
|
||||||
else if (oflags.Iflag)
|
|
||||||
wl = make_word_list (make_bare_word (INITIALWORD), (WORD_LIST *)NULL);
|
|
||||||
else
|
|
||||||
wl = (WORD_LIST *)NULL;
|
|
||||||
|
|
||||||
/* -p overrides everything else */
|
|
||||||
if (oflags.pflag || (list == 0 && opt_given == 0))
|
|
||||||
{
|
|
||||||
if (wl)
|
|
||||||
{
|
|
||||||
rval = print_cmd_completions (wl);
|
|
||||||
dispose_words (wl);
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
else if (list == 0)
|
|
||||||
{
|
|
||||||
print_all_completions ();
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
return (print_cmd_completions (list));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* next, -r overrides everything else. */
|
|
||||||
if (oflags.rflag)
|
|
||||||
{
|
|
||||||
if (wl)
|
|
||||||
{
|
|
||||||
rval = remove_cmd_completions (wl);
|
|
||||||
dispose_words (wl);
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
else if (list == 0)
|
|
||||||
{
|
|
||||||
progcomp_flush ();
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
return (remove_cmd_completions (list));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wl == 0 && list == 0 && opt_given)
|
|
||||||
{
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we get here, we need to build a compspec and add it for each
|
|
||||||
remaining argument. */
|
|
||||||
cs = compspec_create ();
|
|
||||||
cs->actions = acts;
|
|
||||||
cs->options = copts;
|
|
||||||
|
|
||||||
cs->globpat = STRDUP (Garg);
|
|
||||||
cs->words = STRDUP (Warg);
|
|
||||||
cs->prefix = STRDUP (Parg);
|
|
||||||
cs->suffix = STRDUP (Sarg);
|
|
||||||
cs->funcname = STRDUP (Farg);
|
|
||||||
cs->command = STRDUP (Carg);
|
|
||||||
cs->filterpat = STRDUP (Xarg);
|
|
||||||
|
|
||||||
for (rval = EXECUTION_SUCCESS, l = wl ? wl : list ; l; l = l->next)
|
|
||||||
{
|
|
||||||
/* Add CS as the compspec for the specified commands. */
|
|
||||||
if (progcomp_insert (l->word->word, cs) == 0)
|
|
||||||
rval = EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispose_words (wl);
|
|
||||||
return (rval);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
remove_cmd_completions (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
WORD_LIST *l;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
|
|
||||||
{
|
|
||||||
if (progcomp_remove (l->word->word) == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: no completion specification"), l->word->word);
|
|
||||||
ret = EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_compoptions (copts, full)
|
|
||||||
unsigned long copts;
|
|
||||||
int full;
|
|
||||||
{
|
|
||||||
const struct _compopt *co;
|
|
||||||
|
|
||||||
for (co = compopts; co->optname; co++)
|
|
||||||
if (copts & co->optflag)
|
|
||||||
printf ("-o %s ", co->optname);
|
|
||||||
else if (full)
|
|
||||||
printf ("+o %s ", co->optname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_compactions (acts)
|
|
||||||
unsigned long acts;
|
|
||||||
{
|
|
||||||
const struct _compacts *ca;
|
|
||||||
|
|
||||||
/* simple flags first */
|
|
||||||
for (ca = compacts; ca->actname; ca++)
|
|
||||||
if (ca->actopt && (acts & ca->actflag))
|
|
||||||
printf ("-%c ", ca->actopt);
|
|
||||||
|
|
||||||
/* then the rest of the actions */
|
|
||||||
for (ca = compacts; ca->actname; ca++)
|
|
||||||
if (ca->actopt == 0 && (acts & ca->actflag))
|
|
||||||
printf ("-A %s ", ca->actname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_arg (arg, flag, quote)
|
|
||||||
const char *arg, *flag;
|
|
||||||
int quote;
|
|
||||||
{
|
|
||||||
char *x;
|
|
||||||
|
|
||||||
if (arg)
|
|
||||||
{
|
|
||||||
x = quote ? sh_single_quote (arg) : (char *)arg;
|
|
||||||
printf ("%s %s ", flag, x);
|
|
||||||
if (x != arg)
|
|
||||||
free (x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_cmd_name (cmd)
|
|
||||||
const char *cmd;
|
|
||||||
{
|
|
||||||
char *x;
|
|
||||||
|
|
||||||
if (STREQ (cmd, DEFAULTCMD))
|
|
||||||
printf ("-D");
|
|
||||||
else if (STREQ (cmd, EMPTYCMD))
|
|
||||||
printf ("-E");
|
|
||||||
else if (STREQ (cmd, INITIALWORD))
|
|
||||||
printf ("-I");
|
|
||||||
else if (*cmd == 0) /* XXX - can this happen? */
|
|
||||||
printf ("''");
|
|
||||||
else if (sh_contains_shell_metas (cmd))
|
|
||||||
{
|
|
||||||
x = sh_single_quote (cmd);
|
|
||||||
printf ("%s", x);
|
|
||||||
free (x);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
printf ("%s", cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
print_one_completion (cmd, cs)
|
|
||||||
char *cmd;
|
|
||||||
COMPSPEC *cs;
|
|
||||||
{
|
|
||||||
printf ("complete ");
|
|
||||||
|
|
||||||
print_compoptions (cs->options, 0);
|
|
||||||
print_compactions (cs->actions);
|
|
||||||
|
|
||||||
/* now the rest of the arguments */
|
|
||||||
|
|
||||||
/* arguments that require quoting */
|
|
||||||
print_arg (cs->globpat, "-G", 1);
|
|
||||||
print_arg (cs->words, "-W", 1);
|
|
||||||
print_arg (cs->prefix, "-P", 1);
|
|
||||||
print_arg (cs->suffix, "-S", 1);
|
|
||||||
print_arg (cs->filterpat, "-X", 1);
|
|
||||||
|
|
||||||
print_arg (cs->command, "-C", 1);
|
|
||||||
|
|
||||||
/* simple arguments that don't require quoting */
|
|
||||||
print_arg (cs->funcname, "-F", sh_contains_shell_metas (cs->funcname) != 0);
|
|
||||||
|
|
||||||
print_cmd_name (cmd);
|
|
||||||
printf ("\n");
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_compopts (cmd, cs, full)
|
|
||||||
const char *cmd;
|
|
||||||
COMPSPEC *cs;
|
|
||||||
int full;
|
|
||||||
{
|
|
||||||
printf ("compopt ");
|
|
||||||
|
|
||||||
print_compoptions (cs->options, full);
|
|
||||||
print_cmd_name (cmd);
|
|
||||||
|
|
||||||
printf ("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
print_compitem (item)
|
|
||||||
BUCKET_CONTENTS *item;
|
|
||||||
{
|
|
||||||
COMPSPEC *cs;
|
|
||||||
char *cmd;
|
|
||||||
|
|
||||||
cmd = item->key;
|
|
||||||
cs = (COMPSPEC *)item->data;
|
|
||||||
|
|
||||||
return (print_one_completion (cmd, cs));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_all_completions ()
|
|
||||||
{
|
|
||||||
progcomp_walk (print_compitem);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
print_cmd_completions (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
WORD_LIST *l;
|
|
||||||
COMPSPEC *cs;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
|
|
||||||
{
|
|
||||||
cs = progcomp_search (l->word->word);
|
|
||||||
if (cs)
|
|
||||||
print_one_completion (l->word->word, cs);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: no completion specification"), l->word->word);
|
|
||||||
ret = EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (sh_chkwrite (ret));
|
|
||||||
}
|
|
||||||
|
|
||||||
#line 663 "./complete.def"
|
|
||||||
|
|
||||||
int
|
|
||||||
compgen_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int rval;
|
|
||||||
unsigned long acts, copts;
|
|
||||||
COMPSPEC *cs;
|
|
||||||
STRINGLIST *sl;
|
|
||||||
char *word, **matches;
|
|
||||||
char *old_line;
|
|
||||||
int old_ind;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
acts = copts = (unsigned long)0L;
|
|
||||||
Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
|
|
||||||
cs = (COMPSPEC *)NULL;
|
|
||||||
|
|
||||||
/* Build the actions from the arguments. Also sets the [A-Z]arg variables
|
|
||||||
as a side effect if they are supplied as options. */
|
|
||||||
rval = build_actions (list, (struct _optflags *)NULL, &acts, &copts);
|
|
||||||
if (rval == EX_USAGE)
|
|
||||||
return (rval);
|
|
||||||
if (rval == EXECUTION_FAILURE)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
word = (list && list->word) ? list->word->word : "";
|
|
||||||
|
|
||||||
if (Farg)
|
|
||||||
builtin_error (_("warning: -F option may not work as you expect"));
|
|
||||||
if (Carg)
|
|
||||||
builtin_error (_("warning: -C option may not work as you expect"));
|
|
||||||
|
|
||||||
/* If we get here, we need to build a compspec and evaluate it. */
|
|
||||||
cs = compspec_create ();
|
|
||||||
cs->actions = acts;
|
|
||||||
cs->options = copts;
|
|
||||||
cs->refcount = 1;
|
|
||||||
|
|
||||||
cs->globpat = STRDUP (Garg);
|
|
||||||
cs->words = STRDUP (Warg);
|
|
||||||
cs->prefix = STRDUP (Parg);
|
|
||||||
cs->suffix = STRDUP (Sarg);
|
|
||||||
cs->funcname = STRDUP (Farg);
|
|
||||||
cs->command = STRDUP (Carg);
|
|
||||||
cs->filterpat = STRDUP (Xarg);
|
|
||||||
|
|
||||||
rval = EXECUTION_FAILURE;
|
|
||||||
|
|
||||||
/* probably don't have to save these, just being safe */
|
|
||||||
old_line = pcomp_line;
|
|
||||||
old_ind = pcomp_ind;
|
|
||||||
pcomp_line = (char *)NULL;
|
|
||||||
pcomp_ind = 0;
|
|
||||||
sl = gen_compspec_completions (cs, "compgen", word, 0, 0, 0);
|
|
||||||
pcomp_line = old_line;
|
|
||||||
pcomp_ind = old_ind;
|
|
||||||
|
|
||||||
/* If the compspec wants the bash default completions, temporarily
|
|
||||||
turn off programmable completion and call the bash completion code. */
|
|
||||||
if ((sl == 0 || sl->list_len == 0) && (copts & COPT_BASHDEFAULT))
|
|
||||||
{
|
|
||||||
matches = bash_default_completion (word, 0, 0, 0, 0);
|
|
||||||
sl = completions_to_stringlist (matches);
|
|
||||||
strvec_dispose (matches);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This isn't perfect, but it's the best we can do, given what readline
|
|
||||||
exports from its set of completion utility functions. */
|
|
||||||
if ((sl == 0 || sl->list_len == 0) && (copts & COPT_DEFAULT))
|
|
||||||
{
|
|
||||||
matches = rl_completion_matches (word, rl_filename_completion_function);
|
|
||||||
strlist_dispose (sl);
|
|
||||||
sl = completions_to_stringlist (matches);
|
|
||||||
strvec_dispose (matches);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sl)
|
|
||||||
{
|
|
||||||
if (sl->list && sl->list_len)
|
|
||||||
{
|
|
||||||
rval = EXECUTION_SUCCESS;
|
|
||||||
strlist_print (sl, (char *)NULL);
|
|
||||||
}
|
|
||||||
strlist_dispose (sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
compspec_dispose (cs);
|
|
||||||
return (rval);
|
|
||||||
}
|
|
||||||
|
|
||||||
#line 788 "./complete.def"
|
|
||||||
|
|
||||||
int
|
|
||||||
compopt_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int opts_on, opts_off, *opts, opt, oind, ret, Dflag, Eflag, Iflag;
|
|
||||||
WORD_LIST *l, *wl;
|
|
||||||
COMPSPEC *cs;
|
|
||||||
|
|
||||||
opts_on = opts_off = Eflag = Dflag = Iflag = 0;
|
|
||||||
ret = EXECUTION_SUCCESS;
|
|
||||||
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "+o:DEI")) != -1)
|
|
||||||
{
|
|
||||||
opts = (list_opttype == '-') ? &opts_on : &opts_off;
|
|
||||||
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'o':
|
|
||||||
oind = find_compopt (list_optarg);
|
|
||||||
if (oind < 0)
|
|
||||||
{
|
|
||||||
sh_invalidoptname (list_optarg);
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
*opts |= compopts[oind].optflag;
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
Dflag = 1;
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
Eflag = 1;
|
|
||||||
break;
|
|
||||||
case 'I':
|
|
||||||
Iflag = 1;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
if (Dflag)
|
|
||||||
wl = make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL);
|
|
||||||
else if (Eflag)
|
|
||||||
wl = make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST *)NULL);
|
|
||||||
else if (Iflag)
|
|
||||||
wl = make_word_list (make_bare_word (INITIALWORD), (WORD_LIST *)NULL);
|
|
||||||
else
|
|
||||||
wl = (WORD_LIST *)NULL;
|
|
||||||
|
|
||||||
if (list == 0 && wl == 0)
|
|
||||||
{
|
|
||||||
if (RL_ISSTATE (RL_STATE_COMPLETING) == 0 || pcomp_curcs == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("not currently executing completion function"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
cs = pcomp_curcs;
|
|
||||||
|
|
||||||
if (opts_on == 0 && opts_off == 0)
|
|
||||||
{
|
|
||||||
print_compopts (pcomp_curcmd, cs, 1);
|
|
||||||
return (sh_chkwrite (ret));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the compspec options */
|
|
||||||
pcomp_set_compspec_options (cs, opts_on, 1);
|
|
||||||
pcomp_set_compspec_options (cs, opts_off, 0);
|
|
||||||
|
|
||||||
/* And change the readline variables the options control */
|
|
||||||
pcomp_set_readline_variables (opts_on, 1);
|
|
||||||
pcomp_set_readline_variables (opts_off, 0);
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (l = wl ? wl : list; l; l = l->next)
|
|
||||||
{
|
|
||||||
cs = progcomp_search (l->word->word);
|
|
||||||
if (cs == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: no completion specification"), l->word->word);
|
|
||||||
ret = EXECUTION_FAILURE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (opts_on == 0 && opts_off == 0)
|
|
||||||
{
|
|
||||||
print_compopts (l->word->word, cs, 1);
|
|
||||||
continue; /* XXX -- fill in later */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the compspec options */
|
|
||||||
pcomp_set_compspec_options (cs, opts_on, 1);
|
|
||||||
pcomp_set_compspec_options (cs, opts_off, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wl)
|
|
||||||
dispose_words (wl);
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
|
969
third_party/bash/builtins_declare.c
vendored
969
third_party/bash/builtins_declare.c
vendored
|
@ -1,969 +0,0 @@
|
||||||
/* declare.c, created from declare.def. */
|
|
||||||
#line 22 "./declare.def"
|
|
||||||
|
|
||||||
#line 64 "./declare.def"
|
|
||||||
|
|
||||||
#line 72 "./declare.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "flags.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "builtext.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
|
|
||||||
static SHELL_VAR *declare_find_variable PARAMS((const char *, int, int));
|
|
||||||
static char *declare_build_newname PARAMS((char *, char *, int, char *, int));
|
|
||||||
static char *declare_transform_name PARAMS((char *, int, int));
|
|
||||||
|
|
||||||
static int declare_internal PARAMS((register WORD_LIST *, int));
|
|
||||||
|
|
||||||
/* Declare or change variable attributes. */
|
|
||||||
int
|
|
||||||
declare_builtin (list)
|
|
||||||
register WORD_LIST *list;
|
|
||||||
{
|
|
||||||
return (declare_internal (list, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
#line 122 "./declare.def"
|
|
||||||
int
|
|
||||||
local_builtin (list)
|
|
||||||
register WORD_LIST *list;
|
|
||||||
{
|
|
||||||
/* Catch a straight `local --help' before checking function context */
|
|
||||||
if (list && list->word && STREQ (list->word->word, "--help"))
|
|
||||||
{
|
|
||||||
builtin_help ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variable_context)
|
|
||||||
return (declare_internal (list, 1));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
builtin_error (_("can only be used in a function"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
# define DECLARE_OPTS "+acfgilnprtuxAFGI"
|
|
||||||
#else
|
|
||||||
# define DECLARE_OPTS "+cfgilnprtuxFGI"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static SHELL_VAR *
|
|
||||||
declare_find_variable (name, mkglobal, chklocal)
|
|
||||||
const char *name;
|
|
||||||
int mkglobal, chklocal;
|
|
||||||
{
|
|
||||||
SHELL_VAR *var;
|
|
||||||
|
|
||||||
if (mkglobal == 0)
|
|
||||||
return (find_variable (name));
|
|
||||||
else if (chklocal)
|
|
||||||
{
|
|
||||||
var = find_variable (name);
|
|
||||||
if (var && local_p (var) && var->context == variable_context)
|
|
||||||
return var;
|
|
||||||
return (find_global_variable (name));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return (find_global_variable (name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build a new string
|
|
||||||
NAME[SUBSCRIPT][[+]=VALUE]
|
|
||||||
from expanding a nameref into NAME */
|
|
||||||
static char *
|
|
||||||
declare_build_newname (name, subscript_start, offset, value, aflags)
|
|
||||||
char *name, *subscript_start;
|
|
||||||
int offset;
|
|
||||||
char *value;
|
|
||||||
int aflags;
|
|
||||||
{
|
|
||||||
size_t namelen, savelen;
|
|
||||||
char *ret;
|
|
||||||
|
|
||||||
savelen = namelen = strlen (name);
|
|
||||||
if (subscript_start)
|
|
||||||
{
|
|
||||||
*subscript_start = '['; /* ] */
|
|
||||||
namelen += strlen (subscript_start);
|
|
||||||
}
|
|
||||||
ret = xmalloc (namelen + 2 + strlen (value) + 1);
|
|
||||||
strcpy (ret, name);
|
|
||||||
if (subscript_start)
|
|
||||||
strcpy (ret + savelen, subscript_start);
|
|
||||||
if (offset)
|
|
||||||
{
|
|
||||||
if (aflags & ASS_APPEND)
|
|
||||||
ret[namelen++] = '+';
|
|
||||||
ret[namelen++] = '=';
|
|
||||||
if (value && *value)
|
|
||||||
strcpy (ret + namelen, value);
|
|
||||||
else
|
|
||||||
ret[namelen] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
declare_transform_name (name, flags_on, flags_off)
|
|
||||||
char *name;
|
|
||||||
int flags_on, flags_off;
|
|
||||||
{
|
|
||||||
SHELL_VAR *var, *v;
|
|
||||||
char *newname;
|
|
||||||
|
|
||||||
var = find_variable (name);
|
|
||||||
if (var == 0)
|
|
||||||
newname = nameref_transform_name (name, ASS_MKLOCAL);
|
|
||||||
else if ((flags_on & att_nameref) == 0 && (flags_off & att_nameref) == 0)
|
|
||||||
{
|
|
||||||
/* Ok, we're following namerefs here, so let's make sure that if
|
|
||||||
we followed one, it was at the same context (see below for
|
|
||||||
more details). */
|
|
||||||
v = find_variable_last_nameref (name, 1);
|
|
||||||
newname = (v && v->context != variable_context) ? name : name_cell (var);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
newname = name; /* dealing with nameref attribute */
|
|
||||||
|
|
||||||
return (newname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The workhorse function. */
|
|
||||||
static int
|
|
||||||
declare_internal (list, local_var)
|
|
||||||
register WORD_LIST *list;
|
|
||||||
int local_var;
|
|
||||||
{
|
|
||||||
int flags_on, flags_off, *flags;
|
|
||||||
int any_failed, assign_error, pflag, nodefs, opt, onref, offref;
|
|
||||||
int mkglobal, chklocal, inherit_flag;
|
|
||||||
char *t, *subscript_start;
|
|
||||||
SHELL_VAR *var, *refvar, *v;
|
|
||||||
FUNCTION_DEF *shell_fn;
|
|
||||||
|
|
||||||
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
|
|
||||||
mkglobal = chklocal = inherit_flag = 0;
|
|
||||||
refvar = (SHELL_VAR *)NULL;
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, DECLARE_OPTS)) != -1)
|
|
||||||
{
|
|
||||||
flags = list_opttype == '+' ? &flags_off : &flags_on;
|
|
||||||
|
|
||||||
/* If you add options here, see whether or not they need to be added to
|
|
||||||
the loop in subst.c:shell_expand_word_list() */
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'a':
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
*flags |= att_array;
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
#endif
|
|
||||||
case 'A':
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
*flags |= att_assoc;
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
#endif
|
|
||||||
case 'p':
|
|
||||||
pflag++;
|
|
||||||
break;
|
|
||||||
case 'F':
|
|
||||||
nodefs++;
|
|
||||||
*flags |= att_function;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
*flags |= att_function;
|
|
||||||
break;
|
|
||||||
case 'G':
|
|
||||||
if (flags == &flags_on)
|
|
||||||
chklocal = 1;
|
|
||||||
/*FALLTHROUGH*/
|
|
||||||
case 'g':
|
|
||||||
if (flags == &flags_on)
|
|
||||||
mkglobal = 1;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
*flags |= att_integer;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
*flags |= att_nameref;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
*flags |= att_readonly;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
*flags |= att_trace;
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
*flags |= att_exported;
|
|
||||||
array_needs_making = 1;
|
|
||||||
break;
|
|
||||||
#if defined (CASEMOD_ATTRS)
|
|
||||||
# if defined (CASEMOD_CAPCASE)
|
|
||||||
case 'c':
|
|
||||||
*flags |= att_capcase;
|
|
||||||
if (flags == &flags_on)
|
|
||||||
flags_off |= att_uppercase|att_lowercase;
|
|
||||||
break;
|
|
||||||
# endif
|
|
||||||
case 'l':
|
|
||||||
*flags |= att_lowercase;
|
|
||||||
if (flags == &flags_on)
|
|
||||||
flags_off |= att_capcase|att_uppercase;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
*flags |= att_uppercase;
|
|
||||||
if (flags == &flags_on)
|
|
||||||
flags_off |= att_capcase|att_lowercase;
|
|
||||||
break;
|
|
||||||
#endif /* CASEMOD_ATTRS */
|
|
||||||
case 'I':
|
|
||||||
inherit_flag = MKLOC_INHERIT;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
/* If there are no more arguments left, then we just want to show
|
|
||||||
some variables. */
|
|
||||||
if (list == 0) /* declare -[aAfFilnrtux] */
|
|
||||||
{
|
|
||||||
/* Show local variables defined at this context level if this is
|
|
||||||
the `local' builtin. */
|
|
||||||
if (local_var)
|
|
||||||
show_local_var_attributes (0, nodefs); /* XXX - fix up args later */
|
|
||||||
else if (pflag && (flags_on == 0 || flags_on == att_function))
|
|
||||||
show_all_var_attributes (flags_on == 0, nodefs);
|
|
||||||
else if (flags_on == 0)
|
|
||||||
return (set_builtin ((WORD_LIST *)NULL));
|
|
||||||
else
|
|
||||||
set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
|
|
||||||
|
|
||||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pflag) /* declare -p [-aAfFilnrtux] [name ...] */
|
|
||||||
{
|
|
||||||
for (any_failed = 0; list; list = list->next)
|
|
||||||
{
|
|
||||||
if (flags_on & att_function)
|
|
||||||
pflag = show_func_attributes (list->word->word, nodefs);
|
|
||||||
else if (local_var)
|
|
||||||
pflag = show_localname_attributes (list->word->word, nodefs);
|
|
||||||
else
|
|
||||||
pflag = show_name_attributes (list->word->word, nodefs);
|
|
||||||
if (pflag)
|
|
||||||
{
|
|
||||||
sh_notfound (list->word->word);
|
|
||||||
any_failed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some option combinations that don't make any sense */
|
|
||||||
if ((flags_on & att_function) && (flags_on & (att_array|att_assoc|att_integer|att_nameref)))
|
|
||||||
{
|
|
||||||
char *optchar;
|
|
||||||
|
|
||||||
if (flags_on & att_nameref)
|
|
||||||
optchar = "-n";
|
|
||||||
else if (flags_on & att_integer)
|
|
||||||
optchar = "-i";
|
|
||||||
else if (flags_on & att_assoc)
|
|
||||||
optchar = "-A";
|
|
||||||
else if (flags_on & att_array)
|
|
||||||
optchar = "-a";
|
|
||||||
|
|
||||||
sh_invalidopt (optchar);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NEXT_VARIABLE() free (name); list = list->next; continue
|
|
||||||
|
|
||||||
/* There are arguments left, so we are making variables. */
|
|
||||||
while (list) /* declare [-aAfFilnrtux] name[=value] [name[=value] ...] */
|
|
||||||
{
|
|
||||||
char *value, *name, *newname;
|
|
||||||
int offset, aflags, wflags, created_var;
|
|
||||||
int assoc_noexpand;
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
int making_array_special, compound_array_assign, simple_array_assign;
|
|
||||||
int var_exists, array_exists, creating_array, array_subscript_assignment;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
name = savestring (list->word->word);
|
|
||||||
wflags = list->word->flags;
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
assoc_noexpand = assoc_expand_once && (wflags & W_ASSIGNMENT);
|
|
||||||
#else
|
|
||||||
assoc_noexpand = 0;
|
|
||||||
#endif
|
|
||||||
/* XXX - we allow unbalanced brackets if assoc_noexpand is set, we count
|
|
||||||
brackets and make sure they match if assoc_noexpand is not set. So we
|
|
||||||
need to make sure we're checking assoc_noexpand and expand_once_flag
|
|
||||||
for backwards compatibility. We also use assoc_noexpand below when
|
|
||||||
we call assign_array_element, so we need to make sure they're
|
|
||||||
consistent in how they count brackets. */
|
|
||||||
offset = assignment (name, assoc_noexpand ? 2 : 0);
|
|
||||||
aflags = 0;
|
|
||||||
created_var = 0;
|
|
||||||
|
|
||||||
if (local_var && variable_context && STREQ (name, "-"))
|
|
||||||
{
|
|
||||||
var = make_local_variable ("-", 0);
|
|
||||||
FREE (value_cell (var)); /* just in case */
|
|
||||||
value = get_current_options ();
|
|
||||||
var_setvalue (var, value);
|
|
||||||
VSETATTR (var, att_invisible);
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we are declaring a function, then complain about it in some way.
|
|
||||||
We don't let people make functions by saying `typeset -f foo=bar'. */
|
|
||||||
|
|
||||||
/* Can't define functions using assignment statements */
|
|
||||||
if (offset && (flags_on & att_function)) /* declare -f [-rix] foo=bar */
|
|
||||||
{
|
|
||||||
builtin_error (_("cannot use `-f' to make functions"));
|
|
||||||
free (name);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* There should be a way, however, to let people look at a particular
|
|
||||||
function definition by saying `typeset -f foo'. This is the only
|
|
||||||
place in this builtin where we deal with functions. */
|
|
||||||
|
|
||||||
if (flags_on & att_function)
|
|
||||||
{
|
|
||||||
/* Should we restrict this when the shell is in posix mode even if
|
|
||||||
the function was created before the shell entered posix mode?
|
|
||||||
Previous versions of the shell enforced the restriction. */
|
|
||||||
if (posixly_correct && legal_identifier (name) == 0)
|
|
||||||
{
|
|
||||||
sh_invalidid (name);
|
|
||||||
assign_error++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
var = find_function (name);
|
|
||||||
|
|
||||||
if (var)
|
|
||||||
{
|
|
||||||
if (readonly_p (var) && (flags_off & att_readonly))
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: readonly function"), name);
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
/* declare -[Ff] name [name...] */
|
|
||||||
if (flags_on == att_function && flags_off == 0)
|
|
||||||
{
|
|
||||||
#if defined (DEBUGGER)
|
|
||||||
if (nodefs && debugging_mode)
|
|
||||||
{
|
|
||||||
shell_fn = find_function_def (name_cell (var));
|
|
||||||
if (shell_fn)
|
|
||||||
printf ("%s %d %s\n", name_cell (var), shell_fn->line, shell_fn->source_file);
|
|
||||||
else
|
|
||||||
printf ("%s\n", name_cell (var));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* DEBUGGER */
|
|
||||||
{
|
|
||||||
t = nodefs ? name_cell (var) : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
|
|
||||||
printf ("%s\n", t);
|
|
||||||
any_failed = sh_chkwrite (any_failed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* declare -[fF] -[rx] name [name...] */
|
|
||||||
{
|
|
||||||
VSETATTR (var, flags_on);
|
|
||||||
flags_off &= ~att_function; /* makes no sense */
|
|
||||||
VUNSETATTR (var, flags_off);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
any_failed++;
|
|
||||||
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset) /* declare [-aAfFirx] name=value */
|
|
||||||
{
|
|
||||||
name[offset] = '\0';
|
|
||||||
value = name + offset + 1;
|
|
||||||
if (name[offset - 1] == '+')
|
|
||||||
{
|
|
||||||
aflags |= ASS_APPEND;
|
|
||||||
name[offset - 1] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
value = "";
|
|
||||||
|
|
||||||
/* Do some lexical error checking on the LHS and RHS of the assignment
|
|
||||||
that is specific to nameref variables. */
|
|
||||||
if (flags_on & att_nameref)
|
|
||||||
{
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
if (valid_array_reference (name, 0))
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: reference variable cannot be an array"), name);
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
/* disallow self references at global scope, warn at function scope */
|
|
||||||
if (check_selfref (name, value, 0))
|
|
||||||
{
|
|
||||||
if (variable_context == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: nameref variable self references not allowed"), name);
|
|
||||||
assign_error++; /* XXX any_failed++ instead? */
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
builtin_warning (_("%s: circular name reference"), name);
|
|
||||||
}
|
|
||||||
if (value && *value && (aflags & ASS_APPEND) == 0 && valid_nameref_value (value, 1) == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("`%s': invalid variable name for name reference"), value);
|
|
||||||
assign_error++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
restart_new_var_name:
|
|
||||||
|
|
||||||
/* The rest of the loop body deals with declare -[aAlinrtux] name [name...]
|
|
||||||
where each NAME can be an assignment statement. */
|
|
||||||
|
|
||||||
subscript_start = (char *)NULL; /* used below */
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
/* Determine whether we are creating or assigning an array variable */
|
|
||||||
var_exists = array_exists = creating_array = 0;
|
|
||||||
compound_array_assign = simple_array_assign = 0;
|
|
||||||
array_subscript_assignment = 0;
|
|
||||||
if (t = strchr (name, '[')) /* ] */
|
|
||||||
{
|
|
||||||
/* If offset != 0 we have already validated any array reference
|
|
||||||
because assignment() calls skipsubscript() */
|
|
||||||
if (offset == 0 && valid_array_reference (name, 0) == 0)
|
|
||||||
{
|
|
||||||
sh_invalidid (name);
|
|
||||||
assign_error++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
subscript_start = t;
|
|
||||||
*t = '\0';
|
|
||||||
making_array_special = 1; /* XXX - should this check offset? */
|
|
||||||
array_subscript_assignment = offset != 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
making_array_special = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Ensure the argument is a valid, well-formed shell identifier. */
|
|
||||||
if (legal_identifier (name) == 0)
|
|
||||||
{
|
|
||||||
sh_invalidid (name);
|
|
||||||
assign_error++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If VARIABLE_CONTEXT has a non-zero value, then we are executing
|
|
||||||
inside of a function. This means we should make local variables,
|
|
||||||
not global ones. */
|
|
||||||
|
|
||||||
/* XXX - this has consequences when we're making a local copy of a
|
|
||||||
variable that was in the temporary environment. Watch out
|
|
||||||
for this. */
|
|
||||||
refvar = (SHELL_VAR *)NULL;
|
|
||||||
if (variable_context && mkglobal == 0)
|
|
||||||
{
|
|
||||||
/* We don't check newname for validity here. We should not have an
|
|
||||||
invalid name assigned as the value of a nameref, but this could
|
|
||||||
cause problems. */
|
|
||||||
newname = declare_transform_name (name, flags_on, flags_off);
|
|
||||||
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
/* Pass 1 as second argument to make_local_{assoc,array}_variable
|
|
||||||
return an existing {array,assoc} variable to be flagged as an
|
|
||||||
error below. */
|
|
||||||
if (flags_on & att_assoc)
|
|
||||||
var = make_local_assoc_variable (newname, MKLOC_ARRAYOK|inherit_flag);
|
|
||||||
else if ((flags_on & att_array) || making_array_special)
|
|
||||||
var = make_local_array_variable (newname, MKLOC_ASSOCOK|inherit_flag);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (offset == 0 && (flags_on & att_nameref))
|
|
||||||
{
|
|
||||||
/* First look for refvar at current scope */
|
|
||||||
refvar = find_variable_last_nameref (name, 1);
|
|
||||||
/* VARIABLE_CONTEXT != 0, so we are attempting to create or modify
|
|
||||||
the attributes for a local variable at the same scope. If we've
|
|
||||||
used a reference from a previous context to resolve VAR, we
|
|
||||||
want to throw REFVAR and VAR away and create a new local var. */
|
|
||||||
if (refvar && refvar->context != variable_context)
|
|
||||||
{
|
|
||||||
refvar = 0;
|
|
||||||
var = make_local_variable (name, inherit_flag);
|
|
||||||
}
|
|
||||||
else if (refvar && refvar->context == variable_context)
|
|
||||||
var = refvar;
|
|
||||||
/* Maybe we just want to create a new local variable */
|
|
||||||
else if ((var = find_variable (name)) == 0 || var->context != variable_context)
|
|
||||||
var = make_local_variable (name, inherit_flag);
|
|
||||||
/* otherwise we have a var at the right context */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* XXX - check name for validity here with valid_nameref_value? */
|
|
||||||
var = make_local_variable ((flags_on & att_nameref) ? name : newname, inherit_flag); /* sets att_invisible for new vars */
|
|
||||||
|
|
||||||
if (var == 0)
|
|
||||||
{
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
if (var && nameref_p (var) && readonly_p (var) && nameref_cell (var) && (flags_off & att_nameref))
|
|
||||||
{
|
|
||||||
sh_readonly (name);
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
var = (SHELL_VAR *)NULL;
|
|
||||||
|
|
||||||
/* VAR is non-null if we just created or fetched a local variable. */
|
|
||||||
|
|
||||||
/* Here's what ksh93 seems to do as of the 2012 version: if we are
|
|
||||||
using declare -n to modify the value of an existing nameref
|
|
||||||
variable, don't follow the nameref chain at all and just search
|
|
||||||
for a nameref at the current context. If we have a nameref,
|
|
||||||
modify its value (changing which variable it references). */
|
|
||||||
if (var == 0 && (flags_on & att_nameref))
|
|
||||||
{
|
|
||||||
/* See if we are trying to modify an existing nameref variable,
|
|
||||||
but don't follow the nameref chain. */
|
|
||||||
var = mkglobal ? find_global_variable_noref (name) : find_variable_noref (name);
|
|
||||||
if (var && nameref_p (var) == 0)
|
|
||||||
var = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* However, if we're turning off the nameref attribute on an existing
|
|
||||||
nameref variable, we first follow the nameref chain to the end,
|
|
||||||
modify the value of the variable this nameref variable references
|
|
||||||
if there is an assignment statement argument,
|
|
||||||
*CHANGING ITS VALUE AS A SIDE EFFECT*, then turn off the nameref
|
|
||||||
flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */
|
|
||||||
else if (var == 0 && (flags_off & att_nameref))
|
|
||||||
{
|
|
||||||
/* See if we are trying to modify an existing nameref variable */
|
|
||||||
refvar = mkglobal ? find_global_variable_last_nameref (name, 0) : find_variable_last_nameref (name, 0);
|
|
||||||
if (refvar && nameref_p (refvar) == 0)
|
|
||||||
refvar = 0;
|
|
||||||
/* If the nameref is readonly but doesn't have a value, ksh93
|
|
||||||
allows the nameref attribute to be removed. If it's readonly
|
|
||||||
and has a value, even if the value doesn't reference an
|
|
||||||
existing variable, we disallow the modification */
|
|
||||||
if (refvar && nameref_cell (refvar) && readonly_p (refvar))
|
|
||||||
{
|
|
||||||
sh_readonly (name);
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If all we're doing is turning off the nameref attribute, don't
|
|
||||||
bother with VAR at all, whether it exists or not. Just turn it
|
|
||||||
off and go on. */
|
|
||||||
if (refvar && flags_on == 0 && offset == 0 && flags_off == att_nameref)
|
|
||||||
{
|
|
||||||
VUNSETATTR (refvar, att_nameref);
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (refvar)
|
|
||||||
var = declare_find_variable (nameref_cell (refvar), mkglobal, 0);
|
|
||||||
}
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
/* If we have an array assignment to a nameref, remove the nameref
|
|
||||||
attribute and go on. This handles
|
|
||||||
declare -n xref[=value]; declare [-a] xref[1]=one */
|
|
||||||
else if (var == 0 && offset && array_subscript_assignment)
|
|
||||||
{
|
|
||||||
var = mkglobal ? find_global_variable_noref (name) : find_variable_noref (name);
|
|
||||||
if (var && nameref_p (var))
|
|
||||||
{
|
|
||||||
internal_warning (_("%s: removing nameref attribute"), name);
|
|
||||||
FREE (value_cell (var)); /* XXX - bash-4.3 compat */
|
|
||||||
var_setvalue (var, (char *)NULL);
|
|
||||||
VUNSETATTR (var, att_nameref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* See if we are trying to set flags or value (or create) for an
|
|
||||||
existing nameref that points to a non-existent variable: e.g.,
|
|
||||||
declare -n foo=bar
|
|
||||||
unset foo # unsets bar
|
|
||||||
declare -i foo
|
|
||||||
foo=4+4
|
|
||||||
declare -p foo
|
|
||||||
*/
|
|
||||||
if (var == 0 && (mkglobal || flags_on || flags_off || offset))
|
|
||||||
{
|
|
||||||
refvar = mkglobal ? find_global_variable_last_nameref (name, 0) : find_variable_last_nameref (name, 0);
|
|
||||||
if (refvar && nameref_p (refvar) == 0)
|
|
||||||
refvar = 0;
|
|
||||||
if (refvar)
|
|
||||||
var = declare_find_variable (nameref_cell (refvar), mkglobal, 0);
|
|
||||||
if (refvar && var == 0)
|
|
||||||
{
|
|
||||||
/* I'm not sure subscript_start is ever non-null here. In any
|
|
||||||
event, build a new name from the nameref value, including any
|
|
||||||
subscript, and add the [[+]=value] if offset != 0 */
|
|
||||||
newname = declare_build_newname (nameref_cell (refvar), subscript_start, offset, value, aflags);
|
|
||||||
free (name);
|
|
||||||
name = newname;
|
|
||||||
|
|
||||||
if (offset)
|
|
||||||
{
|
|
||||||
offset = assignment (name, 0);
|
|
||||||
/* If offset was valid previously, but substituting the
|
|
||||||
the nameref value results in an invalid assignment,
|
|
||||||
throw an invalid identifier error */
|
|
||||||
if (offset == 0)
|
|
||||||
{
|
|
||||||
sh_invalidid (name);
|
|
||||||
assign_error++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
name[(aflags & ASS_APPEND) ? offset - 1 : offset] = '\0';
|
|
||||||
value = name + offset + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK, let's turn off the nameref attribute.
|
|
||||||
Now everything else applies to VAR. */
|
|
||||||
if (flags_off & att_nameref)
|
|
||||||
VUNSETATTR (refvar, att_nameref);
|
|
||||||
|
|
||||||
goto restart_new_var_name;
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (var == 0)
|
|
||||||
var = declare_find_variable (name, mkglobal, chklocal);
|
|
||||||
|
|
||||||
/* At this point, VAR is the variable we are dealing with; REFVAR is the
|
|
||||||
nameref variable we dereferenced to get VAR, if any. */
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
var_exists = var != 0;
|
|
||||||
array_exists = var && (array_p (var) || assoc_p (var));
|
|
||||||
creating_array = flags_on & (att_array|att_assoc);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Make a new variable if we need to. */
|
|
||||||
if (var == 0)
|
|
||||||
{
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
if (flags_on & att_assoc)
|
|
||||||
var = make_new_assoc_variable (name);
|
|
||||||
else if ((flags_on & att_array) || making_array_special)
|
|
||||||
var = make_new_array_variable (name);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
var = mkglobal ? bind_global_variable (name, (char *)NULL, ASS_FORCE) : bind_variable (name, (char *)NULL, ASS_FORCE);
|
|
||||||
|
|
||||||
if (var == 0)
|
|
||||||
{
|
|
||||||
/* Has to appear in brackets */
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
if (offset == 0)
|
|
||||||
VSETATTR (var, att_invisible);
|
|
||||||
created_var = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nameref variable error checking. */
|
|
||||||
|
|
||||||
/* Can't take an existing array variable and make it a nameref */
|
|
||||||
else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: reference variable cannot be an array"), name);
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
/* Can't have an invalid identifier as nameref value */
|
|
||||||
else if (nameref_p (var) && (flags_on & att_nameref) == 0 && (flags_off & att_nameref) == 0 && offset && valid_nameref_value (value, 1) == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("`%s': invalid variable name for name reference"), value);
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
/* Can't make an existing variable a nameref if its current value is not
|
|
||||||
a valid identifier. Check of offset is to allow an assignment to a
|
|
||||||
nameref var as part of the declare word to override existing value. */
|
|
||||||
else if ((flags_on & att_nameref) && nameref_p (var) == 0 && var_isset (var) && offset == 0 && valid_nameref_value (value_cell (var), 0) == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("`%s': invalid variable name for name reference"), value_cell (var));
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
/* Can't make an existing readonly variable a nameref. */
|
|
||||||
else if ((flags_on & att_nameref) && readonly_p (var))
|
|
||||||
{
|
|
||||||
sh_readonly (name);
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Readonly variable error checking. */
|
|
||||||
|
|
||||||
/* Cannot use declare +r to turn off readonly attribute. */
|
|
||||||
if (readonly_p (var) && (flags_off & att_readonly))
|
|
||||||
{
|
|
||||||
sh_readonly (name_cell (var));
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
/* Cannot use declare to assign value to readonly or noassign variable. */
|
|
||||||
else if ((readonly_p (var) || noassign_p (var)) && offset)
|
|
||||||
{
|
|
||||||
if (readonly_p (var))
|
|
||||||
sh_readonly (name);
|
|
||||||
assign_error++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
/* Array variable error checking. */
|
|
||||||
|
|
||||||
/* Cannot use declare +a name or declare +A name to remove an array variable. */
|
|
||||||
if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: cannot destroy array variables in this way"), name);
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
else if ((flags_on & att_array) && assoc_p (var))
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: cannot convert associative to indexed array"), name);
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
else if ((flags_on & att_assoc) && array_p (var))
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: cannot convert indexed to associative array"), name);
|
|
||||||
any_failed++;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make declare A[2]=foo as similar to A[2]=foo as possible if A is
|
|
||||||
already an array or assoc variable. */
|
|
||||||
if (array_subscript_assignment && array_exists && creating_array == 0)
|
|
||||||
simple_array_assign = 1;
|
|
||||||
else if ((making_array_special || creating_array || array_exists) && offset)
|
|
||||||
{
|
|
||||||
int vlen;
|
|
||||||
vlen = STRLEN (value);
|
|
||||||
/*itrace("declare_builtin: name = %s value = %s flags = %d", name, value, wflags);*/
|
|
||||||
|
|
||||||
if (shell_compatibility_level > 43 && (wflags & W_COMPASSIGN) == 0 &&
|
|
||||||
value[0] == '(' && value[vlen-1] == ')')
|
|
||||||
{
|
|
||||||
/* I don't believe this warning is printed any more.
|
|
||||||
We use creating_array to allow things like
|
|
||||||
declare -a foo$bar='(abc)'
|
|
||||||
to work as they have in the past. */
|
|
||||||
if (array_exists == 0 && creating_array == 0)
|
|
||||||
internal_warning (_("%s: quoted compound array assignment deprecated"), list->word->word);
|
|
||||||
compound_array_assign = array_exists || creating_array;
|
|
||||||
simple_array_assign = making_array_special;
|
|
||||||
}
|
|
||||||
else if (value[0] == '(' && value[vlen-1] == ')' && (shell_compatibility_level < 44 || (wflags & W_COMPASSIGN)))
|
|
||||||
compound_array_assign = 1;
|
|
||||||
else
|
|
||||||
simple_array_assign = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* declare -A name[[n]] makes name an associative array variable. */
|
|
||||||
if (flags_on & att_assoc)
|
|
||||||
{
|
|
||||||
if (assoc_p (var) == 0)
|
|
||||||
var = convert_var_to_assoc (var);
|
|
||||||
}
|
|
||||||
/* declare -a name[[n]] or declare name[n] makes NAME an indexed
|
|
||||||
array variable. */
|
|
||||||
else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
|
|
||||||
var = convert_var_to_array (var);
|
|
||||||
#endif /* ARRAY_VARS */
|
|
||||||
|
|
||||||
/* ksh93 compat: turning on nameref attribute turns off -ilu */
|
|
||||||
if (flags_on & att_nameref)
|
|
||||||
VUNSETATTR (var, att_integer|att_uppercase|att_lowercase|att_capcase);
|
|
||||||
|
|
||||||
/* XXX - we note that we are turning on nameref attribute and defer
|
|
||||||
setting it until the assignment has been made so we don't do an
|
|
||||||
inadvertent nameref lookup. Might have to do the same thing for
|
|
||||||
flags_off&att_nameref. */
|
|
||||||
/* XXX - ksh93 makes it an error to set a readonly nameref variable
|
|
||||||
using a single typeset command. */
|
|
||||||
onref = (flags_on & att_nameref);
|
|
||||||
flags_on &= ~att_nameref;
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
/* I don't believe this condition ever tests true, but array variables
|
|
||||||
may not be namerefs */
|
|
||||||
if (array_p (var) || assoc_p (var) || compound_array_assign || simple_array_assign)
|
|
||||||
onref = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ksh93 seems to do this */
|
|
||||||
offref = (flags_off & att_nameref);
|
|
||||||
flags_off &= ~att_nameref;
|
|
||||||
|
|
||||||
VSETATTR (var, flags_on);
|
|
||||||
VUNSETATTR (var, flags_off);
|
|
||||||
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
if (offset && compound_array_assign)
|
|
||||||
assign_array_var_from_string (var, value, aflags|ASS_FORCE);
|
|
||||||
else if (simple_array_assign && subscript_start)
|
|
||||||
{
|
|
||||||
int local_aflags;
|
|
||||||
|
|
||||||
/* declare [-aA] name[N]=value */
|
|
||||||
*subscript_start = '['; /* ] */
|
|
||||||
/* XXX - problem here with appending */
|
|
||||||
local_aflags = aflags&ASS_APPEND;
|
|
||||||
local_aflags |= assoc_noexpand ? ASS_NOEXPAND : 0;
|
|
||||||
local_aflags |= ASS_ALLOWALLSUB; /* allow declare a[@]=at */
|
|
||||||
var = assign_array_element (name, value, local_aflags, (array_eltstate_t *)0); /* XXX - not aflags */
|
|
||||||
*subscript_start = '\0';
|
|
||||||
if (var == 0) /* some kind of assignment error */
|
|
||||||
{
|
|
||||||
assign_error++;
|
|
||||||
flags_on |= onref;
|
|
||||||
flags_off |= offref;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (simple_array_assign)
|
|
||||||
{
|
|
||||||
/* let bind_{array,assoc}_variable take care of this. */
|
|
||||||
if (assoc_p (var))
|
|
||||||
bind_assoc_variable (var, name, savestring ("0"), value, aflags|ASS_FORCE);
|
|
||||||
else
|
|
||||||
bind_array_variable (name, 0, value, aflags|ASS_FORCE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
/* XXX - no ASS_FORCE here */
|
|
||||||
/* bind_variable_value duplicates the essential internals of bind_variable() */
|
|
||||||
if (offset)
|
|
||||||
{
|
|
||||||
if (onref || nameref_p (var))
|
|
||||||
aflags |= ASS_NAMEREF;
|
|
||||||
v = bind_variable_value (var, value, aflags);
|
|
||||||
if (v == 0 && (onref || nameref_p (var)))
|
|
||||||
{
|
|
||||||
if (valid_nameref_value (value, 1) == 0)
|
|
||||||
sh_invalidid (value);
|
|
||||||
assign_error++;
|
|
||||||
/* XXX - unset this variable? or leave it as normal var? */
|
|
||||||
if (created_var)
|
|
||||||
delete_var (name_cell (var), mkglobal ? global_variables : shell_variables);
|
|
||||||
flags_on |= onref; /* undo change from above */
|
|
||||||
flags_off |= offref;
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we found this variable in the temporary environment, as with
|
|
||||||
`var=value declare -x var', make sure it is treated identically
|
|
||||||
to `var=value export var'. Do the same for `declare -r' and
|
|
||||||
`readonly'. Preserve the attributes, except for att_tempvar. */
|
|
||||||
/* XXX -- should this create a variable in the global scope, or
|
|
||||||
modify the local variable flags? ksh93 has it modify the
|
|
||||||
global scope.
|
|
||||||
Need to handle case like in set_var_attribute where a temporary
|
|
||||||
variable is in the same table as the function local vars. */
|
|
||||||
if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
|
|
||||||
{
|
|
||||||
SHELL_VAR *tv;
|
|
||||||
char *tvalue;
|
|
||||||
|
|
||||||
tv = find_tempenv_variable (name_cell (var));
|
|
||||||
if (tv)
|
|
||||||
{
|
|
||||||
tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
|
|
||||||
tv = bind_variable (name_cell (var), tvalue, 0);
|
|
||||||
if (tv)
|
|
||||||
{
|
|
||||||
tv->attributes |= var->attributes & ~att_tempvar;
|
|
||||||
if (tv->context > 0)
|
|
||||||
VSETATTR (tv, att_propagate);
|
|
||||||
}
|
|
||||||
free (tvalue);
|
|
||||||
}
|
|
||||||
VSETATTR (var, att_propagate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Turn on nameref attribute we deferred above. */
|
|
||||||
VSETATTR (var, onref);
|
|
||||||
flags_on |= onref;
|
|
||||||
VUNSETATTR (var, offref);
|
|
||||||
flags_off |= offref;
|
|
||||||
|
|
||||||
/* Yuck. ksh93 compatibility. XXX - need to investigate more but
|
|
||||||
definitely happens when turning off nameref attribute on nameref
|
|
||||||
(see comments above). Under no circumstances allow this to turn
|
|
||||||
off readonly attribute on readonly nameref variable. */
|
|
||||||
if (refvar)
|
|
||||||
{
|
|
||||||
if (flags_off & att_readonly)
|
|
||||||
flags_off &= ~att_readonly;
|
|
||||||
VUNSETATTR (refvar, flags_off);
|
|
||||||
}
|
|
||||||
|
|
||||||
stupidly_hack_special_variables (name);
|
|
||||||
|
|
||||||
NEXT_VARIABLE ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (assign_error ? EX_BADASSIGN
|
|
||||||
: ((any_failed == 0) ? EXECUTION_SUCCESS
|
|
||||||
: EXECUTION_FAILURE));
|
|
||||||
}
|
|
133
third_party/bash/builtins_echo.c
vendored
133
third_party/bash/builtins_echo.c
vendored
|
@ -1,133 +0,0 @@
|
||||||
/* echo.c, created from echo.def. */
|
|
||||||
#line 22 "./echo.def"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "shell.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#line 73 "./echo.def"
|
|
||||||
|
|
||||||
#line 88 "./echo.def"
|
|
||||||
|
|
||||||
#if defined (V9_ECHO)
|
|
||||||
# define VALID_ECHO_OPTIONS "neE"
|
|
||||||
#else /* !V9_ECHO */
|
|
||||||
# define VALID_ECHO_OPTIONS "n"
|
|
||||||
#endif /* !V9_ECHO */
|
|
||||||
|
|
||||||
/* System V machines already have a /bin/sh with a v9 behaviour. We
|
|
||||||
give Bash the identical behaviour for these machines so that the
|
|
||||||
existing system shells won't barf. Regrettably, the SUS v2 has
|
|
||||||
standardized the Sys V echo behavior. This variable is external
|
|
||||||
so that we can have a `shopt' variable to control it at runtime. */
|
|
||||||
#if defined (DEFAULT_ECHO_TO_XPG) || defined (STRICT_POSIX)
|
|
||||||
int xpg_echo = 1;
|
|
||||||
#else
|
|
||||||
int xpg_echo = 0;
|
|
||||||
#endif /* DEFAULT_ECHO_TO_XPG */
|
|
||||||
|
|
||||||
/* Print the words in LIST to standard output. If the first word is
|
|
||||||
`-n', then don't print a trailing newline. We also support the
|
|
||||||
echo syntax from Version 9 Unix systems. */
|
|
||||||
int
|
|
||||||
echo_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int display_return, do_v9, i, len;
|
|
||||||
char *temp, *s;
|
|
||||||
|
|
||||||
do_v9 = xpg_echo;
|
|
||||||
display_return = 1;
|
|
||||||
|
|
||||||
if (posixly_correct && xpg_echo)
|
|
||||||
goto just_echo;
|
|
||||||
|
|
||||||
for (; list && (temp = list->word->word) && *temp == '-'; list = list->next)
|
|
||||||
{
|
|
||||||
/* If it appears that we are handling options, then make sure that
|
|
||||||
all of the options specified are actually valid. Otherwise, the
|
|
||||||
string should just be echoed. */
|
|
||||||
temp++;
|
|
||||||
|
|
||||||
for (i = 0; temp[i]; i++)
|
|
||||||
{
|
|
||||||
if (strchr (VALID_ECHO_OPTIONS, temp[i]) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* echo - and echo -<nonopt> both mean to just echo the arguments. */
|
|
||||||
if (*temp == 0 || temp[i])
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* All of the options in TEMP are valid options to ECHO.
|
|
||||||
Handle them. */
|
|
||||||
while (i = *temp++)
|
|
||||||
{
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 'n':
|
|
||||||
display_return = 0;
|
|
||||||
break;
|
|
||||||
#if defined (V9_ECHO)
|
|
||||||
case 'e':
|
|
||||||
do_v9 = 1;
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
do_v9 = 0;
|
|
||||||
break;
|
|
||||||
#endif /* V9_ECHO */
|
|
||||||
default:
|
|
||||||
goto just_echo; /* XXX */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
just_echo:
|
|
||||||
|
|
||||||
clearerr (stdout); /* clear error before writing and testing success */
|
|
||||||
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
i = len = 0;
|
|
||||||
temp = do_v9 ? ansicstr (list->word->word, STRLEN (list->word->word), 1, &i, &len)
|
|
||||||
: list->word->word;
|
|
||||||
if (temp)
|
|
||||||
{
|
|
||||||
if (do_v9)
|
|
||||||
{
|
|
||||||
for (s = temp; len > 0; len--)
|
|
||||||
putchar (*s++);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
printf ("%s", temp);
|
|
||||||
#if defined (SunOS5)
|
|
||||||
fflush (stdout); /* Fix for bug in SunOS 5.5 printf(3) */
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
QUIT;
|
|
||||||
if (do_v9 && temp)
|
|
||||||
free (temp);
|
|
||||||
list = list->next;
|
|
||||||
if (i)
|
|
||||||
{
|
|
||||||
display_return = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (list)
|
|
||||||
putchar(' ');
|
|
||||||
QUIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (display_return)
|
|
||||||
putchar ('\n');
|
|
||||||
|
|
||||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
|
||||||
}
|
|
541
third_party/bash/builtins_enable.c
vendored
541
third_party/bash/builtins_enable.c
vendored
|
@ -1,541 +0,0 @@
|
||||||
/* enable.c, created from enable.def. */
|
|
||||||
#line 22 "./enable.def"
|
|
||||||
|
|
||||||
#line 50 "./enable.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "flags.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
#include "findcmd.h"
|
|
||||||
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
# include "pcomplete.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ENABLED 1
|
|
||||||
#define DISABLED 2
|
|
||||||
#define SPECIAL 4
|
|
||||||
#define SILENT 8 /* affects dyn_load_builtin behavior */
|
|
||||||
|
|
||||||
#define AFLAG 0x01
|
|
||||||
#define DFLAG 0x02
|
|
||||||
#define FFLAG 0x04
|
|
||||||
#define NFLAG 0x08
|
|
||||||
#define PFLAG 0x10
|
|
||||||
#define SFLAG 0x20
|
|
||||||
|
|
||||||
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
|
|
||||||
static int dyn_load_builtin PARAMS((WORD_LIST *, int, char *));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (HAVE_DLCLOSE)
|
|
||||||
static int dyn_unload_builtin PARAMS((char *));
|
|
||||||
static void delete_builtin PARAMS((struct builtin *));
|
|
||||||
static int local_dlclose PARAMS((void *));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define STRUCT_SUFFIX "_struct"
|
|
||||||
/* for now */
|
|
||||||
#define LOAD_SUFFIX "_builtin_load"
|
|
||||||
#define UNLOAD_SUFFIX "_builtin_unload"
|
|
||||||
|
|
||||||
static void list_some_builtins PARAMS((int));
|
|
||||||
static int enable_shell_command PARAMS((char *, int));
|
|
||||||
|
|
||||||
/* Enable/disable shell commands present in LIST. If list is not specified,
|
|
||||||
then print out a list of shell commands showing which are enabled and
|
|
||||||
which are disabled. */
|
|
||||||
int
|
|
||||||
enable_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int result, flags;
|
|
||||||
int opt, filter;
|
|
||||||
WORD_LIST *next;
|
|
||||||
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
|
|
||||||
char *filename;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
result = EXECUTION_SUCCESS;
|
|
||||||
flags = 0;
|
|
||||||
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "adnpsf:")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'a':
|
|
||||||
flags |= AFLAG;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
flags |= NFLAG;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
flags |= PFLAG;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
flags |= SFLAG;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
|
|
||||||
flags |= FFLAG;
|
|
||||||
filename = list_optarg;
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
builtin_error (_("dynamic loading not available"));
|
|
||||||
return (EX_USAGE);
|
|
||||||
#endif
|
|
||||||
#if defined (HAVE_DLCLOSE)
|
|
||||||
case 'd':
|
|
||||||
flags |= DFLAG;
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
builtin_error (_("dynamic loading not available"));
|
|
||||||
return (EX_USAGE);
|
|
||||||
#endif /* HAVE_DLCLOSE */
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
#if defined (RESTRICTED_SHELL)
|
|
||||||
/* Restricted shells cannot load new builtins. */
|
|
||||||
if (restricted && (flags & (FFLAG|DFLAG)))
|
|
||||||
{
|
|
||||||
sh_restricted ((char *)NULL);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (list == 0 || (flags & PFLAG))
|
|
||||||
{
|
|
||||||
filter = (flags & AFLAG) ? (ENABLED | DISABLED)
|
|
||||||
: (flags & NFLAG) ? DISABLED : ENABLED;
|
|
||||||
|
|
||||||
if (flags & SFLAG)
|
|
||||||
filter |= SPECIAL;
|
|
||||||
|
|
||||||
list_some_builtins (filter);
|
|
||||||
result = sh_chkwrite (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
|
|
||||||
else if (flags & FFLAG)
|
|
||||||
{
|
|
||||||
filter = (flags & NFLAG) ? DISABLED : ENABLED;
|
|
||||||
if (flags & SFLAG)
|
|
||||||
filter |= SPECIAL;
|
|
||||||
|
|
||||||
result = dyn_load_builtin (list, filter, filename);
|
|
||||||
if (result != EXECUTION_SUCCESS)
|
|
||||||
result = EXECUTION_FAILURE; /* normalize return value */
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
set_itemlist_dirty (&it_builtins);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined (HAVE_DLCLOSE)
|
|
||||||
else if (flags & DFLAG)
|
|
||||||
{
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
opt = dyn_unload_builtin (list->word->word);
|
|
||||||
if (opt == EXECUTION_FAILURE)
|
|
||||||
result = EXECUTION_FAILURE;
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
set_itemlist_dirty (&it_builtins);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
opt = enable_shell_command (list->word->word, flags & NFLAG);
|
|
||||||
next = list->next;
|
|
||||||
|
|
||||||
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
|
|
||||||
/* If we try to enable a non-existent builtin, and we have dynamic
|
|
||||||
loading, try the equivalent of `enable -f name name'. */
|
|
||||||
if (opt == EX_NOTFOUND)
|
|
||||||
{
|
|
||||||
int dflags, r;
|
|
||||||
|
|
||||||
dflags = ENABLED|SILENT|((flags & SFLAG) ? SPECIAL : 0);
|
|
||||||
|
|
||||||
list->next = 0;
|
|
||||||
r = dyn_load_builtin (list, dflags, list->word->word);
|
|
||||||
list->next = next;
|
|
||||||
if (r == EXECUTION_SUCCESS)
|
|
||||||
opt = r;
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
set_itemlist_dirty (&it_builtins);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (opt == EX_NOTFOUND)
|
|
||||||
{
|
|
||||||
sh_notbuiltin (list->word->word);
|
|
||||||
result = EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
else if (opt != EXECUTION_SUCCESS)
|
|
||||||
result = EXECUTION_FAILURE;
|
|
||||||
|
|
||||||
list = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* List some builtins.
|
|
||||||
FILTER is a mask with two slots: ENABLED and DISABLED. */
|
|
||||||
static void
|
|
||||||
list_some_builtins (filter)
|
|
||||||
int filter;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
for (i = 0; i < num_shell_builtins; i++)
|
|
||||||
{
|
|
||||||
if (shell_builtins[i].function == 0 || (shell_builtins[i].flags & BUILTIN_DELETED))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((filter & SPECIAL) &&
|
|
||||||
(shell_builtins[i].flags & SPECIAL_BUILTIN) == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((filter & ENABLED) && (shell_builtins[i].flags & BUILTIN_ENABLED))
|
|
||||||
printf ("enable %s\n", shell_builtins[i].name);
|
|
||||||
else if ((filter & DISABLED) &&
|
|
||||||
((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
|
|
||||||
printf ("enable -n %s\n", shell_builtins[i].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enable the shell command NAME. If DISABLE_P is non-zero, then
|
|
||||||
disable NAME instead. */
|
|
||||||
static int
|
|
||||||
enable_shell_command (name, disable_p)
|
|
||||||
char *name;
|
|
||||||
int disable_p;
|
|
||||||
{
|
|
||||||
struct builtin *b;
|
|
||||||
|
|
||||||
b = builtin_address_internal (name, 1);
|
|
||||||
if (b == 0)
|
|
||||||
return (EX_NOTFOUND);
|
|
||||||
|
|
||||||
if (disable_p)
|
|
||||||
b->flags &= ~BUILTIN_ENABLED;
|
|
||||||
#if defined (RESTRICTED_SHELL)
|
|
||||||
else if (restricted && ((b->flags & BUILTIN_ENABLED) == 0))
|
|
||||||
{
|
|
||||||
sh_restricted ((char *)NULL);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
b->flags |= BUILTIN_ENABLED;
|
|
||||||
|
|
||||||
#if defined (PROGRAMMABLE_COMPLETION)
|
|
||||||
set_itemlist_dirty (&it_enabled);
|
|
||||||
set_itemlist_dirty (&it_disabled);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM)
|
|
||||||
|
|
||||||
#if defined (HAVE_DLFCN_H)
|
|
||||||
# include <dlfcn.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int
|
|
||||||
dyn_load_builtin (list, flags, filename)
|
|
||||||
WORD_LIST *list;
|
|
||||||
int flags;
|
|
||||||
char *filename;
|
|
||||||
{
|
|
||||||
WORD_LIST *l;
|
|
||||||
void *handle;
|
|
||||||
|
|
||||||
int total, size, new, replaced, r;
|
|
||||||
char *struct_name, *name, *funcname;
|
|
||||||
sh_load_func_t *loadfunc;
|
|
||||||
struct builtin **new_builtins, *b, *new_shell_builtins, *old_builtin;
|
|
||||||
char *loadables_path, *load_path;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
|
|
||||||
#ifndef RTLD_LAZY
|
|
||||||
#define RTLD_LAZY 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
handle = 0;
|
|
||||||
if (absolute_program (filename) == 0)
|
|
||||||
{
|
|
||||||
loadables_path = get_string_value ("BASH_LOADABLES_PATH");
|
|
||||||
if (loadables_path)
|
|
||||||
{
|
|
||||||
load_path = find_in_path (filename, loadables_path, FS_NODIRS|FS_EXEC_PREFERRED);
|
|
||||||
if (load_path)
|
|
||||||
{
|
|
||||||
#if defined (_AIX)
|
|
||||||
handle = dlopen (load_path, RTLD_NOW|RTLD_GLOBAL);
|
|
||||||
#else
|
|
||||||
handle = dlopen (load_path, RTLD_LAZY);
|
|
||||||
#endif /* !_AIX */
|
|
||||||
free (load_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fall back to current directory for now */
|
|
||||||
if (handle == 0)
|
|
||||||
#if defined (_AIX)
|
|
||||||
handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
|
|
||||||
#else
|
|
||||||
handle = dlopen (filename, RTLD_LAZY);
|
|
||||||
#endif /* !_AIX */
|
|
||||||
|
|
||||||
if (handle == 0)
|
|
||||||
{
|
|
||||||
/* If we've been told to be quiet, don't complain about not finding the
|
|
||||||
specified shared object. */
|
|
||||||
if ((flags & SILENT) == 0)
|
|
||||||
{
|
|
||||||
name = printable_filename (filename, 0);
|
|
||||||
builtin_error (_("cannot open shared object %s: %s"), name, dlerror ());
|
|
||||||
if (name != filename)
|
|
||||||
free (name);
|
|
||||||
}
|
|
||||||
return (EX_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (new = 0, l = list; l; l = l->next, new++)
|
|
||||||
;
|
|
||||||
new_builtins = (struct builtin **)xmalloc (new * sizeof (struct builtin *));
|
|
||||||
|
|
||||||
/* For each new builtin in the shared object, find it and its describing
|
|
||||||
structure. If this is overwriting an existing builtin, do so, otherwise
|
|
||||||
save the loaded struct for creating the new list of builtins. */
|
|
||||||
for (replaced = new = 0; list; list = list->next)
|
|
||||||
{
|
|
||||||
name = list->word->word;
|
|
||||||
|
|
||||||
size = strlen (name);
|
|
||||||
struct_name = (char *)xmalloc (size + 8);
|
|
||||||
strcpy (struct_name, name);
|
|
||||||
strcpy (struct_name + size, STRUCT_SUFFIX);
|
|
||||||
|
|
||||||
old_builtin = builtin_address_internal (name, 1);
|
|
||||||
|
|
||||||
b = (struct builtin *)dlsym (handle, struct_name);
|
|
||||||
if (b == 0)
|
|
||||||
{
|
|
||||||
name = printable_filename (filename, 0);
|
|
||||||
builtin_error (_("cannot find %s in shared object %s: %s"),
|
|
||||||
struct_name, name, dlerror ());
|
|
||||||
if (name != filename)
|
|
||||||
free (name);
|
|
||||||
free (struct_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
funcname = xrealloc (struct_name, size + sizeof (LOAD_SUFFIX) + 1);
|
|
||||||
strcpy (funcname, name);
|
|
||||||
strcpy (funcname + size, LOAD_SUFFIX);
|
|
||||||
|
|
||||||
loadfunc = (sh_load_func_t *)dlsym (handle, funcname);
|
|
||||||
if (loadfunc)
|
|
||||||
{
|
|
||||||
/* Add warning if running an init function more than once */
|
|
||||||
if (old_builtin && (old_builtin->flags & STATIC_BUILTIN) == 0)
|
|
||||||
builtin_warning (_("%s: dynamic builtin already loaded"), name);
|
|
||||||
r = (*loadfunc) (name);
|
|
||||||
if (r == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("load function for %s returns failure (%d): not loaded"), name, r);
|
|
||||||
free (funcname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free (funcname);
|
|
||||||
|
|
||||||
b->flags &= ~STATIC_BUILTIN;
|
|
||||||
if (flags & SPECIAL)
|
|
||||||
b->flags |= SPECIAL_BUILTIN;
|
|
||||||
b->handle = handle;
|
|
||||||
|
|
||||||
if (old_builtin)
|
|
||||||
{
|
|
||||||
replaced++;
|
|
||||||
FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
new_builtins[new++] = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (replaced == 0 && new == 0)
|
|
||||||
{
|
|
||||||
free (new_builtins);
|
|
||||||
dlclose (handle);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new)
|
|
||||||
{
|
|
||||||
total = num_shell_builtins + new;
|
|
||||||
size = (total + 1) * sizeof (struct builtin);
|
|
||||||
|
|
||||||
new_shell_builtins = (struct builtin *)xmalloc (size);
|
|
||||||
FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
|
|
||||||
num_shell_builtins * sizeof (struct builtin));
|
|
||||||
for (replaced = 0; replaced < new; replaced++)
|
|
||||||
FASTCOPY ((char *)new_builtins[replaced],
|
|
||||||
(char *)&new_shell_builtins[num_shell_builtins + replaced],
|
|
||||||
sizeof (struct builtin));
|
|
||||||
|
|
||||||
new_shell_builtins[total].name = (char *)0;
|
|
||||||
new_shell_builtins[total].function = (sh_builtin_func_t *)0;
|
|
||||||
new_shell_builtins[total].flags = 0;
|
|
||||||
|
|
||||||
if (shell_builtins != static_shell_builtins)
|
|
||||||
free (shell_builtins);
|
|
||||||
|
|
||||||
shell_builtins = new_shell_builtins;
|
|
||||||
num_shell_builtins = total;
|
|
||||||
initialize_shell_builtins ();
|
|
||||||
}
|
|
||||||
|
|
||||||
free (new_builtins);
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (HAVE_DLCLOSE)
|
|
||||||
static void
|
|
||||||
delete_builtin (b)
|
|
||||||
struct builtin *b;
|
|
||||||
{
|
|
||||||
int ind, size;
|
|
||||||
struct builtin *new_shell_builtins;
|
|
||||||
|
|
||||||
/* XXX - funky pointer arithmetic - XXX */
|
|
||||||
#ifdef __STDC__
|
|
||||||
ind = b - shell_builtins;
|
|
||||||
#else
|
|
||||||
ind = ((int)b - (int)shell_builtins) / sizeof (struct builtin);
|
|
||||||
#endif
|
|
||||||
size = num_shell_builtins * sizeof (struct builtin);
|
|
||||||
new_shell_builtins = (struct builtin *)xmalloc (size);
|
|
||||||
|
|
||||||
/* Copy shell_builtins[0]...shell_builtins[ind - 1] to new_shell_builtins */
|
|
||||||
if (ind)
|
|
||||||
FASTCOPY ((char *)shell_builtins, (char *)new_shell_builtins,
|
|
||||||
ind * sizeof (struct builtin));
|
|
||||||
/* Copy shell_builtins[ind+1]...shell_builtins[num_shell_builtins to
|
|
||||||
new_shell_builtins, starting at ind. */
|
|
||||||
FASTCOPY ((char *)(&shell_builtins[ind+1]),
|
|
||||||
(char *)(&new_shell_builtins[ind]),
|
|
||||||
(num_shell_builtins - ind) * sizeof (struct builtin));
|
|
||||||
|
|
||||||
if (shell_builtins != static_shell_builtins)
|
|
||||||
free (shell_builtins);
|
|
||||||
|
|
||||||
/* The result is still sorted. */
|
|
||||||
num_shell_builtins--;
|
|
||||||
shell_builtins = new_shell_builtins;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tenon's MachTen has a dlclose that doesn't return a value, so we
|
|
||||||
finesse it with a local wrapper. */
|
|
||||||
static int
|
|
||||||
local_dlclose (handle)
|
|
||||||
void *handle;
|
|
||||||
{
|
|
||||||
#if !defined (__MACHTEN__)
|
|
||||||
return (dlclose (handle));
|
|
||||||
#else /* __MACHTEN__ */
|
|
||||||
dlclose (handle);
|
|
||||||
return ((dlerror () != NULL) ? -1 : 0);
|
|
||||||
#endif /* __MACHTEN__ */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
dyn_unload_builtin (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
struct builtin *b;
|
|
||||||
void *handle;
|
|
||||||
char *funcname;
|
|
||||||
sh_unload_func_t *unloadfunc;
|
|
||||||
int ref, i, size;
|
|
||||||
|
|
||||||
b = builtin_address_internal (name, 1);
|
|
||||||
if (b == 0)
|
|
||||||
{
|
|
||||||
sh_notbuiltin (name);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
if (b->flags & STATIC_BUILTIN)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: not dynamically loaded"), name);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
handle = (void *)b->handle;
|
|
||||||
for (ref = i = 0; i < num_shell_builtins; i++)
|
|
||||||
{
|
|
||||||
if (shell_builtins[i].handle == b->handle)
|
|
||||||
ref++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call any unload function */
|
|
||||||
size = strlen (name);
|
|
||||||
funcname = xmalloc (size + sizeof (UNLOAD_SUFFIX) + 1);
|
|
||||||
strcpy (funcname, name);
|
|
||||||
strcpy (funcname + size, UNLOAD_SUFFIX);
|
|
||||||
|
|
||||||
unloadfunc = (sh_unload_func_t *)dlsym (handle, funcname);
|
|
||||||
if (unloadfunc)
|
|
||||||
(*unloadfunc) (name); /* void function */
|
|
||||||
free (funcname);
|
|
||||||
|
|
||||||
/* Don't remove the shared object unless the reference count of builtins
|
|
||||||
using it drops to zero. */
|
|
||||||
if (ref == 1 && local_dlclose (handle) != 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: cannot delete: %s"), name, dlerror ());
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now remove this entry from the builtin table and reinitialize. */
|
|
||||||
delete_builtin (b);
|
|
||||||
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
#endif
|
|
28
third_party/bash/builtins_eval.c
vendored
28
third_party/bash/builtins_eval.c
vendored
|
@ -1,28 +0,0 @@
|
||||||
/* eval.c, created from eval.def. */
|
|
||||||
#line 22 "./eval.def"
|
|
||||||
|
|
||||||
#line 34 "./eval.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/* Parse the string that these words make, and execute the command found. */
|
|
||||||
int
|
|
||||||
eval_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
if (no_options (list))
|
|
||||||
return (EX_USAGE);
|
|
||||||
list = loptend; /* skip over possible `--' */
|
|
||||||
|
|
||||||
return (list ? evalstring (string_list (list), "eval", SEVAL_NOHIST) : EXECUTION_SUCCESS);
|
|
||||||
}
|
|
238
third_party/bash/builtins_exec.c
vendored
238
third_party/bash/builtins_exec.c
vendored
|
@ -1,238 +0,0 @@
|
||||||
/* exec.c, created from exec.def. */
|
|
||||||
#line 22 "./exec.def"
|
|
||||||
|
|
||||||
#line 43 "./exec.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "bashtypes.h"
|
|
||||||
#include "posixstat.h"
|
|
||||||
#include <signal.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "findcmd.h"
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
# include "jobs.h"
|
|
||||||
#endif
|
|
||||||
#include "flags.h"
|
|
||||||
#include "trap.h"
|
|
||||||
#if defined (HISTORY)
|
|
||||||
# include "bashhist.h"
|
|
||||||
#endif
|
|
||||||
#include "common.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
#include "input.h"
|
|
||||||
|
|
||||||
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
|
|
||||||
#if !defined (errno)
|
|
||||||
extern int errno;
|
|
||||||
#endif /* !errno */
|
|
||||||
|
|
||||||
extern REDIRECT *redirection_undo_list;
|
|
||||||
extern char *exec_argv0;
|
|
||||||
|
|
||||||
int no_exit_on_failed_exec;
|
|
||||||
|
|
||||||
/* If the user wants this to look like a login shell, then
|
|
||||||
prepend a `-' onto NAME and return the new name. */
|
|
||||||
static char *
|
|
||||||
mkdashname (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
char *ret;
|
|
||||||
|
|
||||||
ret = (char *)xmalloc (2 + strlen (name));
|
|
||||||
ret[0] = '-';
|
|
||||||
strcpy (ret + 1, name);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
exec_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int exit_value = EXECUTION_FAILURE;
|
|
||||||
int cleanenv, login, opt, orig_job_control;
|
|
||||||
char *argv0, *command, **args, **env, *newname, *com2;
|
|
||||||
|
|
||||||
cleanenv = login = orig_job_control = 0;
|
|
||||||
exec_argv0 = argv0 = (char *)NULL;
|
|
||||||
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "cla:")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'c':
|
|
||||||
cleanenv = 1;
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
login = 1;
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
argv0 = list_optarg;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
/* First, let the redirections remain. */
|
|
||||||
dispose_redirects (redirection_undo_list);
|
|
||||||
redirection_undo_list = (REDIRECT *)NULL;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
|
|
||||||
#if defined (RESTRICTED_SHELL)
|
|
||||||
if (restricted)
|
|
||||||
{
|
|
||||||
sh_restricted ((char *)NULL);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
#endif /* RESTRICTED_SHELL */
|
|
||||||
|
|
||||||
args = strvec_from_word_list (list, 1, 0, (int *)NULL);
|
|
||||||
env = (char **)0;
|
|
||||||
|
|
||||||
/* A command with a slash anywhere in its name is not looked up in $PATH. */
|
|
||||||
command = absolute_program (args[0]) ? args[0] : search_for_command (args[0], 1);
|
|
||||||
|
|
||||||
if (command == 0)
|
|
||||||
{
|
|
||||||
if (file_isdir (args[0]))
|
|
||||||
{
|
|
||||||
#if defined (EISDIR)
|
|
||||||
builtin_error (_("%s: cannot execute: %s"), args[0], strerror (EISDIR));
|
|
||||||
#else
|
|
||||||
builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno));
|
|
||||||
#endif
|
|
||||||
exit_value = EX_NOEXEC;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_notfound (args[0]);
|
|
||||||
exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
|
|
||||||
}
|
|
||||||
goto failed_exec;
|
|
||||||
}
|
|
||||||
|
|
||||||
com2 = full_pathname (command);
|
|
||||||
if (com2)
|
|
||||||
{
|
|
||||||
if (command != args[0])
|
|
||||||
free (command);
|
|
||||||
command = com2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argv0)
|
|
||||||
{
|
|
||||||
free (args[0]);
|
|
||||||
args[0] = login ? mkdashname (argv0) : savestring (argv0);
|
|
||||||
exec_argv0 = savestring (args[0]);
|
|
||||||
}
|
|
||||||
else if (login)
|
|
||||||
{
|
|
||||||
newname = mkdashname (args[0]);
|
|
||||||
free (args[0]);
|
|
||||||
args[0] = newname;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decrement SHLVL by 1 so a new shell started here has the same value,
|
|
||||||
preserving the appearance. After we do that, we need to change the
|
|
||||||
exported environment to include the new value. If we've already forked
|
|
||||||
and are in a subshell, we don't want to decrement the shell level,
|
|
||||||
since we are `increasing' the level */
|
|
||||||
|
|
||||||
if (cleanenv == 0 && (subshell_environment & SUBSHELL_PAREN) == 0)
|
|
||||||
adjust_shell_level (-1);
|
|
||||||
|
|
||||||
if (cleanenv)
|
|
||||||
{
|
|
||||||
env = strvec_create (1);
|
|
||||||
env[0] = (char *)0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
maybe_make_export_env ();
|
|
||||||
env = export_env;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (HISTORY)
|
|
||||||
if (interactive_shell && subshell_environment == 0)
|
|
||||||
maybe_save_shell_history ();
|
|
||||||
#endif /* HISTORY */
|
|
||||||
|
|
||||||
reset_signal_handlers (); /* leave trap strings in place */
|
|
||||||
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
orig_job_control = job_control; /* XXX - was also interactive_shell */
|
|
||||||
if (subshell_environment == 0)
|
|
||||||
end_job_control ();
|
|
||||||
if (interactive || job_control)
|
|
||||||
default_tty_job_signals (); /* undo initialize_job_signals */
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
|
|
||||||
#if defined (BUFFERED_INPUT)
|
|
||||||
if (default_buffered_input >= 0)
|
|
||||||
sync_buffered_stream (default_buffered_input);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
exit_value = shell_execve (command, args, env);
|
|
||||||
|
|
||||||
/* We have to set this to NULL because shell_execve has called realloc()
|
|
||||||
to stuff more items at the front of the array, which may have caused
|
|
||||||
the memory to be freed by realloc(). We don't want to free it twice. */
|
|
||||||
args = (char **)NULL;
|
|
||||||
if (cleanenv == 0)
|
|
||||||
adjust_shell_level (1);
|
|
||||||
|
|
||||||
if (exit_value == EX_NOTFOUND) /* no duplicate error message */
|
|
||||||
goto failed_exec;
|
|
||||||
else if (executable_file (command) == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
|
|
||||||
exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
file_error (command);
|
|
||||||
|
|
||||||
failed_exec:
|
|
||||||
FREE (command);
|
|
||||||
|
|
||||||
if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
|
|
||||||
exit_shell (last_command_exit_value = exit_value);
|
|
||||||
|
|
||||||
if (args)
|
|
||||||
strvec_dispose (args);
|
|
||||||
|
|
||||||
if (env && env != export_env)
|
|
||||||
strvec_dispose (env);
|
|
||||||
|
|
||||||
/* If we're not exiting after the exec fails, we restore the shell signal
|
|
||||||
handlers and then modify the signal dispositions based on the trap strings
|
|
||||||
before the failed exec. */
|
|
||||||
initialize_signals (1);
|
|
||||||
restore_traps ();
|
|
||||||
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
if (orig_job_control)
|
|
||||||
restart_job_control ();
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
|
|
||||||
return (exit_value);
|
|
||||||
}
|
|
136
third_party/bash/builtins_exit.c
vendored
136
third_party/bash/builtins_exit.c
vendored
|
@ -1,136 +0,0 @@
|
||||||
/* exit.c, created from exit.def. */
|
|
||||||
#line 22 "./exit.def"
|
|
||||||
|
|
||||||
#line 31 "./exit.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "bashtypes.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "jobs.h"
|
|
||||||
#include "trap.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "builtext.h" /* for jobs_builtin */
|
|
||||||
|
|
||||||
extern int check_jobs_at_exit;
|
|
||||||
|
|
||||||
static int exit_or_logout PARAMS((WORD_LIST *));
|
|
||||||
static int sourced_logout;
|
|
||||||
|
|
||||||
int
|
|
||||||
exit_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
if (interactive)
|
|
||||||
{
|
|
||||||
fprintf (stderr, login_shell ? _("logout\n") : "exit\n");
|
|
||||||
fflush (stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (exit_or_logout (list));
|
|
||||||
}
|
|
||||||
|
|
||||||
#line 79 "./exit.def"
|
|
||||||
|
|
||||||
/* How to logout. */
|
|
||||||
int
|
|
||||||
logout_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
if (login_shell == 0 /* && interactive */)
|
|
||||||
{
|
|
||||||
builtin_error (_("not login shell: use `exit'"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return (exit_or_logout (list));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
exit_or_logout (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int exit_value;
|
|
||||||
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
int exit_immediate_okay, stopmsg;
|
|
||||||
|
|
||||||
exit_immediate_okay = (interactive == 0 ||
|
|
||||||
last_shell_builtin == exit_builtin ||
|
|
||||||
last_shell_builtin == logout_builtin ||
|
|
||||||
last_shell_builtin == jobs_builtin);
|
|
||||||
|
|
||||||
/* Check for stopped jobs if the user wants to. */
|
|
||||||
if (exit_immediate_okay == 0)
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
for (i = stopmsg = 0; i < js.j_jobslots; i++)
|
|
||||||
if (jobs[i] && STOPPED (i))
|
|
||||||
stopmsg = JSTOPPED;
|
|
||||||
else if (check_jobs_at_exit && stopmsg == 0 && jobs[i] && RUNNING (i))
|
|
||||||
stopmsg = JRUNNING;
|
|
||||||
|
|
||||||
if (stopmsg == JSTOPPED)
|
|
||||||
fprintf (stderr, _("There are stopped jobs.\n"));
|
|
||||||
else if (stopmsg == JRUNNING)
|
|
||||||
fprintf (stderr, _("There are running jobs.\n"));
|
|
||||||
|
|
||||||
if (stopmsg && check_jobs_at_exit)
|
|
||||||
list_all_jobs (JLIST_STANDARD);
|
|
||||||
|
|
||||||
if (stopmsg)
|
|
||||||
{
|
|
||||||
/* This is NOT superfluous because EOF can get here without
|
|
||||||
going through the command parser. Set both last and this
|
|
||||||
so that either `exit', `logout', or ^D will work to exit
|
|
||||||
immediately if nothing intervenes. */
|
|
||||||
this_shell_builtin = last_shell_builtin = exit_builtin;
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
|
|
||||||
/* Get return value if present. This means that you can type
|
|
||||||
`logout 5' to a shell, and it returns 5. */
|
|
||||||
|
|
||||||
/* If we're running the exit trap (running_trap == 1, since running_trap
|
|
||||||
gets set to SIG+1), and we don't have a argument given to `exit'
|
|
||||||
(list == 0), use the exit status we saved before running the trap
|
|
||||||
commands (trap_saved_exit_value). */
|
|
||||||
exit_value = (running_trap == 1 && list == 0) ? trap_saved_exit_value : get_exitstat (list);
|
|
||||||
|
|
||||||
bash_logout ();
|
|
||||||
|
|
||||||
last_command_exit_value = exit_value;
|
|
||||||
|
|
||||||
/* Exit the program. */
|
|
||||||
jump_to_top_level (EXITBLTIN);
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
bash_logout ()
|
|
||||||
{
|
|
||||||
/* Run our `~/.bash_logout' file if it exists, and this is a login shell. */
|
|
||||||
if (login_shell && sourced_logout++ == 0 && subshell_environment == 0)
|
|
||||||
{
|
|
||||||
maybe_execute_file ("~/.bash_logout", 1);
|
|
||||||
#ifdef SYS_BASH_LOGOUT
|
|
||||||
maybe_execute_file (SYS_BASH_LOGOUT, 1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
739
third_party/bash/builtins_fc.c
vendored
739
third_party/bash/builtins_fc.c
vendored
|
@ -1,739 +0,0 @@
|
||||||
/* fc.c, created from fc.def. */
|
|
||||||
#line 22 "./fc.def"
|
|
||||||
|
|
||||||
#line 51 "./fc.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HISTORY)
|
|
||||||
#if defined (HAVE_SYS_PARAM_H)
|
|
||||||
# include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
#include "bashtypes.h"
|
|
||||||
#include "posixstat.h"
|
|
||||||
#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
|
|
||||||
# include <sys/file.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "chartypes.h"
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "flags.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include "bashhist.h"
|
|
||||||
#include "maxpath.h"
|
|
||||||
#include "third_party/readline/history.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#if !defined (errno)
|
|
||||||
extern int errno;
|
|
||||||
#endif /* !errno */
|
|
||||||
|
|
||||||
#define HIST_INVALID INT_MIN
|
|
||||||
#define HIST_ERANGE INT_MIN+1
|
|
||||||
#define HIST_NOTFOUND INT_MIN+2
|
|
||||||
|
|
||||||
/* Values for the flags argument to fc_gethnum */
|
|
||||||
#define HN_LISTING 0x01
|
|
||||||
#define HN_FIRST 0x02
|
|
||||||
|
|
||||||
extern int unlink PARAMS((const char *));
|
|
||||||
|
|
||||||
extern FILE *sh_mktmpfp PARAMS((char *, int, char **));
|
|
||||||
|
|
||||||
extern int suppress_debug_trap_verbose;
|
|
||||||
|
|
||||||
/* **************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* The K*rn shell style fc command (Fix Command) */
|
|
||||||
/* */
|
|
||||||
/* **************************************************************** */
|
|
||||||
|
|
||||||
/* fc builtin command (fix command) for Bash for those who
|
|
||||||
like K*rn-style history better than csh-style.
|
|
||||||
|
|
||||||
fc [-e ename] [-nlr] [first] [last]
|
|
||||||
|
|
||||||
FIRST and LAST can be numbers specifying the range, or FIRST can be
|
|
||||||
a string, which means the most recent command beginning with that
|
|
||||||
string.
|
|
||||||
|
|
||||||
-e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
|
|
||||||
then the editor which corresponds to the current readline editing
|
|
||||||
mode, then vi.
|
|
||||||
|
|
||||||
-l means list lines instead of editing.
|
|
||||||
-n means no line numbers listed.
|
|
||||||
-r means reverse the order of the lines (making it newest listed first).
|
|
||||||
|
|
||||||
fc -e - [pat=rep ...] [command]
|
|
||||||
fc -s [pat=rep ...] [command]
|
|
||||||
|
|
||||||
Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Data structure describing a list of global replacements to perform. */
|
|
||||||
typedef struct repl {
|
|
||||||
struct repl *next;
|
|
||||||
char *pat;
|
|
||||||
char *rep;
|
|
||||||
} REPL;
|
|
||||||
|
|
||||||
/* Accessors for HIST_ENTRY lists that are called HLIST. */
|
|
||||||
#define histline(i) (hlist[(i)]->line)
|
|
||||||
#define histdata(i) (hlist[(i)]->data)
|
|
||||||
|
|
||||||
#define FREE_RLIST() \
|
|
||||||
do { \
|
|
||||||
for (rl = rlist; rl; ) { \
|
|
||||||
REPL *r; \
|
|
||||||
r = rl->next; \
|
|
||||||
if (rl->pat) \
|
|
||||||
free (rl->pat); \
|
|
||||||
if (rl->rep) \
|
|
||||||
free (rl->rep); \
|
|
||||||
free (rl); \
|
|
||||||
rl = r; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
static char *fc_dosubs PARAMS((char *, REPL *));
|
|
||||||
static char *fc_gethist PARAMS((char *, HIST_ENTRY **, int));
|
|
||||||
static int fc_gethnum PARAMS((char *, HIST_ENTRY **, int));
|
|
||||||
static int fc_number PARAMS((WORD_LIST *));
|
|
||||||
static void fc_replhist PARAMS((char *));
|
|
||||||
#ifdef INCLUDE_UNUSED
|
|
||||||
static char *fc_readline PARAMS((FILE *));
|
|
||||||
static void fc_addhist PARAMS((char *));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_verbose_flag ()
|
|
||||||
{
|
|
||||||
echo_input_at_read = verbose_flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* String to execute on a file that we want to edit. */
|
|
||||||
#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
|
|
||||||
#if defined (STRICT_POSIX)
|
|
||||||
# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-ed}"
|
|
||||||
#else
|
|
||||||
# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
|
||||||
fc_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
register char *sep;
|
|
||||||
int numbering, reverse, listing, execute;
|
|
||||||
int histbeg, histend, last_hist, retval, opt, rh, real_last;
|
|
||||||
FILE *stream;
|
|
||||||
REPL *rlist, *rl;
|
|
||||||
char *ename, *command, *newcom, *fcedit;
|
|
||||||
HIST_ENTRY **hlist;
|
|
||||||
char *fn;
|
|
||||||
|
|
||||||
numbering = 1;
|
|
||||||
reverse = listing = execute = 0;
|
|
||||||
ename = (char *)NULL;
|
|
||||||
|
|
||||||
/* Parse out the options and set which of the two forms we're in. */
|
|
||||||
reset_internal_getopt ();
|
|
||||||
lcurrent = list; /* XXX */
|
|
||||||
while (fc_number (loptend = lcurrent) == 0 &&
|
|
||||||
(opt = internal_getopt (list, ":e:lnrs")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'n':
|
|
||||||
numbering = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'l':
|
|
||||||
listing = HN_LISTING; /* for fc_gethnum */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
reverse = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
execute = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'e':
|
|
||||||
ename = list_optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
if (ename && (*ename == '-') && (ename[1] == '\0'))
|
|
||||||
execute = 1;
|
|
||||||
|
|
||||||
/* The "execute" form of the command (re-run, with possible string
|
|
||||||
substitutions). */
|
|
||||||
if (execute)
|
|
||||||
{
|
|
||||||
rlist = (REPL *)NULL;
|
|
||||||
while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
|
|
||||||
{
|
|
||||||
*sep++ = '\0';
|
|
||||||
rl = (REPL *)xmalloc (sizeof (REPL));
|
|
||||||
rl->next = (REPL *)NULL;
|
|
||||||
rl->pat = savestring (list->word->word);
|
|
||||||
rl->rep = savestring (sep);
|
|
||||||
|
|
||||||
if (rlist == NULL)
|
|
||||||
rlist = rl;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rl->next = rlist;
|
|
||||||
rlist = rl;
|
|
||||||
}
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have a list of substitutions to do, then reverse it
|
|
||||||
to get the replacements in the proper order. */
|
|
||||||
|
|
||||||
rlist = REVERSE_LIST (rlist, REPL *);
|
|
||||||
|
|
||||||
hlist = history_list ();
|
|
||||||
|
|
||||||
/* If we still have something in list, it is a command spec.
|
|
||||||
Otherwise, we use the most recent command in time. */
|
|
||||||
command = fc_gethist (list ? list->word->word : (char *)NULL, hlist, 0);
|
|
||||||
|
|
||||||
if (command == NULL)
|
|
||||||
{
|
|
||||||
builtin_error (_("no command found"));
|
|
||||||
if (rlist)
|
|
||||||
FREE_RLIST ();
|
|
||||||
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rlist)
|
|
||||||
{
|
|
||||||
newcom = fc_dosubs (command, rlist);
|
|
||||||
free (command);
|
|
||||||
FREE_RLIST ();
|
|
||||||
command = newcom;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf (stderr, "%s\n", command);
|
|
||||||
fc_replhist (command); /* replace `fc -s' with command */
|
|
||||||
/* Posix says that the re-executed commands should be entered into the
|
|
||||||
history. */
|
|
||||||
return (parse_and_execute (command, "fc", SEVAL_NOHIST));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is the second form of the command (the list-or-edit-and-rerun
|
|
||||||
form). */
|
|
||||||
hlist = history_list ();
|
|
||||||
if (hlist == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
for (i = 0; hlist[i]; i++);
|
|
||||||
|
|
||||||
/* With the Bash implementation of history, the current command line
|
|
||||||
("fc blah..." and so on) is already part of the history list by
|
|
||||||
the time we get to this point. This just skips over that command
|
|
||||||
and makes the last command that this deals with be the last command
|
|
||||||
the user entered before the fc. We need to check whether the
|
|
||||||
line was actually added (HISTIGNORE may have caused it to not be),
|
|
||||||
so we check hist_last_line_added. */
|
|
||||||
|
|
||||||
/* Even though command substitution through parse_and_execute turns off
|
|
||||||
remember_on_history, command substitution in a shell when set -o history
|
|
||||||
has been enabled (interactive or not) should use it in the last_hist
|
|
||||||
calculation as if it were on. */
|
|
||||||
rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
|
|
||||||
last_hist = i - rh - hist_last_line_added;
|
|
||||||
|
|
||||||
/* Make sure that real_last is calculated the same way here and in
|
|
||||||
fc_gethnum. The return value from fc_gethnum is treated specially if
|
|
||||||
it is == real_last and we are listing commands. */
|
|
||||||
real_last = i;
|
|
||||||
/* back up from the end to the last non-null history entry */
|
|
||||||
while (hlist[real_last] == 0 && real_last > 0)
|
|
||||||
real_last--;
|
|
||||||
|
|
||||||
/* XXX */
|
|
||||||
if (i == last_hist && hlist[last_hist] == 0)
|
|
||||||
while (last_hist >= 0 && hlist[last_hist] == 0)
|
|
||||||
last_hist--;
|
|
||||||
if (last_hist < 0)
|
|
||||||
last_hist = 0; /* per POSIX */
|
|
||||||
|
|
||||||
if (list)
|
|
||||||
{
|
|
||||||
histbeg = fc_gethnum (list->word->word, hlist, listing|HN_FIRST);
|
|
||||||
list = list->next;
|
|
||||||
|
|
||||||
if (list)
|
|
||||||
histend = fc_gethnum (list->word->word, hlist, listing);
|
|
||||||
else if (histbeg == real_last)
|
|
||||||
histend = listing ? real_last : histbeg;
|
|
||||||
else
|
|
||||||
histend = listing ? last_hist : histbeg;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The default for listing is the last 16 history items. */
|
|
||||||
if (listing)
|
|
||||||
{
|
|
||||||
histend = last_hist;
|
|
||||||
histbeg = histend - 16 + 1; /* +1 because loop below uses >= */
|
|
||||||
if (histbeg < 0)
|
|
||||||
histbeg = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* For editing, it is the last history command. */
|
|
||||||
histbeg = histend = last_hist;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (histbeg == HIST_INVALID || histend == HIST_INVALID)
|
|
||||||
{
|
|
||||||
sh_erange ((char *)NULL, _("history specification"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else if (histbeg == HIST_ERANGE || histend == HIST_ERANGE)
|
|
||||||
{
|
|
||||||
sh_erange ((char *)NULL, _("history specification"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else if (histbeg == HIST_NOTFOUND || histend == HIST_NOTFOUND)
|
|
||||||
{
|
|
||||||
builtin_error (_("no command found"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't throw an error for line specifications out of range, per POSIX */
|
|
||||||
if (histbeg < 0)
|
|
||||||
histbeg = 0;
|
|
||||||
if (histend < 0)
|
|
||||||
histend = 0;
|
|
||||||
|
|
||||||
/* "When not listing, the fc command that caused the editing shall not be
|
|
||||||
entered into the history list." */
|
|
||||||
if (listing == 0 && hist_last_line_added)
|
|
||||||
{
|
|
||||||
bash_delete_last_history ();
|
|
||||||
/* If we're editing a single command -- the last command in the
|
|
||||||
history -- and we just removed the dummy command added by
|
|
||||||
edit_and_execute_command (), we need to check whether or not we
|
|
||||||
just removed the last command in the history and need to back
|
|
||||||
the pointer up. remember_on_history is off because we're running
|
|
||||||
in parse_and_execute(). */
|
|
||||||
if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0)
|
|
||||||
last_hist = histbeg = --histend;
|
|
||||||
|
|
||||||
if (hlist[last_hist] == 0)
|
|
||||||
last_hist--;
|
|
||||||
if (histend >= last_hist)
|
|
||||||
histend = last_hist;
|
|
||||||
else if (histbeg >= last_hist)
|
|
||||||
histbeg = last_hist;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (histbeg == HIST_INVALID || histend == HIST_INVALID)
|
|
||||||
{
|
|
||||||
sh_erange ((char *)NULL, _("history specification"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else if (histbeg == HIST_ERANGE || histend == HIST_ERANGE)
|
|
||||||
{
|
|
||||||
sh_erange ((char *)NULL, _("history specification"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else if (histbeg == HIST_NOTFOUND || histend == HIST_NOTFOUND)
|
|
||||||
{
|
|
||||||
builtin_error (_("no command found"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't throw an error for line specifications out of range, per POSIX */
|
|
||||||
if (histbeg < 0)
|
|
||||||
histbeg = 0;
|
|
||||||
if (histend < 0)
|
|
||||||
histend = 0;
|
|
||||||
|
|
||||||
if (histend < histbeg)
|
|
||||||
{
|
|
||||||
i = histend;
|
|
||||||
histend = histbeg;
|
|
||||||
histbeg = i;
|
|
||||||
|
|
||||||
reverse = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listing)
|
|
||||||
stream = stdout;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numbering = 0;
|
|
||||||
stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn);
|
|
||||||
if (stream == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno));
|
|
||||||
FREE (fn);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
|
|
||||||
{
|
|
||||||
QUIT;
|
|
||||||
if (hlist[i] == 0)
|
|
||||||
continue;
|
|
||||||
if (numbering)
|
|
||||||
fprintf (stream, "%d", i + history_base);
|
|
||||||
if (listing)
|
|
||||||
{
|
|
||||||
if (posixly_correct)
|
|
||||||
fputs ("\t", stream);
|
|
||||||
else
|
|
||||||
fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
|
|
||||||
}
|
|
||||||
if (histline (i))
|
|
||||||
fprintf (stream, "%s\n", histline (i));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listing)
|
|
||||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
|
||||||
|
|
||||||
fflush (stream);
|
|
||||||
if (ferror (stream))
|
|
||||||
{
|
|
||||||
sh_wrerror ();
|
|
||||||
fclose (stream);
|
|
||||||
FREE (fn);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
fclose (stream);
|
|
||||||
|
|
||||||
/* Now edit the file of commands. */
|
|
||||||
if (ename)
|
|
||||||
{
|
|
||||||
command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
|
|
||||||
sprintf (command, "%s %s", ename, fn);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND;
|
|
||||||
command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn));
|
|
||||||
sprintf (command, "%s %s", fcedit, fn);
|
|
||||||
}
|
|
||||||
retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
|
|
||||||
if (retval != EXECUTION_SUCCESS)
|
|
||||||
{
|
|
||||||
unlink (fn);
|
|
||||||
free (fn);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (READLINE)
|
|
||||||
/* If we're executing as part of a dispatched readline command like
|
|
||||||
{emacs,vi}_edit_and_execute_command, the readline state will indicate it.
|
|
||||||
We could remove the partial command from the history, but ksh93 doesn't
|
|
||||||
so we stay compatible. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Make sure parse_and_execute doesn't turn this off, even though a
|
|
||||||
call to parse_and_execute farther up the function call stack (e.g.,
|
|
||||||
if this is called by vi_edit_and_execute_command) may have already
|
|
||||||
called bash_history_disable. */
|
|
||||||
remember_on_history = 1;
|
|
||||||
|
|
||||||
/* Turn on the `v' flag while fc_execute_file runs so the commands
|
|
||||||
will be echoed as they are read by the parser. */
|
|
||||||
begin_unwind_frame ("fc builtin");
|
|
||||||
add_unwind_protect (xfree, fn);
|
|
||||||
add_unwind_protect (unlink, fn);
|
|
||||||
add_unwind_protect (set_verbose_flag, (char *)NULL);
|
|
||||||
unwind_protect_int (suppress_debug_trap_verbose);
|
|
||||||
echo_input_at_read = 1;
|
|
||||||
suppress_debug_trap_verbose = 1;
|
|
||||||
|
|
||||||
retval = fc_execute_file (fn);
|
|
||||||
run_unwind_frame ("fc builtin");
|
|
||||||
|
|
||||||
return (retval);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return 1 if LIST->word->word is a legal number for fc's use. */
|
|
||||||
static int
|
|
||||||
fc_number (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
return 0;
|
|
||||||
s = list->word->word;
|
|
||||||
if (*s == '-')
|
|
||||||
s++;
|
|
||||||
return (legal_number (s, (intmax_t *)NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return an absolute index into HLIST which corresponds to COMMAND. If
|
|
||||||
COMMAND is a number, then it was specified in relative terms. If it
|
|
||||||
is a string, then it is the start of a command line present in HLIST.
|
|
||||||
MODE includes HN_LISTING if we are listing commands, and does not if we
|
|
||||||
are executing them. If MODE includes HN_FIRST we are looking for the
|
|
||||||
first history number specification. */
|
|
||||||
static int
|
|
||||||
fc_gethnum (command, hlist, mode)
|
|
||||||
char *command;
|
|
||||||
HIST_ENTRY **hlist;
|
|
||||||
int mode;
|
|
||||||
{
|
|
||||||
int sign, n, clen, rh;
|
|
||||||
register int i, j, last_hist, real_last, listing;
|
|
||||||
register char *s;
|
|
||||||
|
|
||||||
listing = mode & HN_LISTING;
|
|
||||||
sign = 1;
|
|
||||||
/* Count history elements. */
|
|
||||||
for (i = 0; hlist[i]; i++);
|
|
||||||
|
|
||||||
/* With the Bash implementation of history, the current command line
|
|
||||||
("fc blah..." and so on) is already part of the history list by
|
|
||||||
the time we get to this point. This just skips over that command
|
|
||||||
and makes the last command that this deals with be the last command
|
|
||||||
the user entered before the fc. We need to check whether the
|
|
||||||
line was actually added (HISTIGNORE may have caused it to not be),
|
|
||||||
so we check hist_last_line_added. This needs to agree with the
|
|
||||||
calculation of last_hist in fc_builtin above. */
|
|
||||||
/* Even though command substitution through parse_and_execute turns off
|
|
||||||
remember_on_history, command substitution in a shell when set -o history
|
|
||||||
has been enabled (interactive or not) should use it in the last_hist
|
|
||||||
calculation as if it were on. */
|
|
||||||
rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
|
|
||||||
last_hist = i - rh - hist_last_line_added;
|
|
||||||
|
|
||||||
if (i == last_hist && hlist[last_hist] == 0)
|
|
||||||
while (last_hist >= 0 && hlist[last_hist] == 0)
|
|
||||||
last_hist--;
|
|
||||||
if (last_hist < 0)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
real_last = i;
|
|
||||||
i = last_hist;
|
|
||||||
|
|
||||||
/* No specification defaults to most recent command. */
|
|
||||||
if (command == NULL)
|
|
||||||
return (i);
|
|
||||||
|
|
||||||
/* back up from the end to the last non-null history entry */
|
|
||||||
while (hlist[real_last] == 0 && real_last > 0)
|
|
||||||
real_last--;
|
|
||||||
|
|
||||||
/* Otherwise, there is a specification. It can be a number relative to
|
|
||||||
the current position, or an absolute history number. */
|
|
||||||
s = command;
|
|
||||||
|
|
||||||
/* Handle possible leading minus sign. */
|
|
||||||
if (s && (*s == '-'))
|
|
||||||
{
|
|
||||||
sign = -1;
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s && DIGIT(*s))
|
|
||||||
{
|
|
||||||
n = atoi (s);
|
|
||||||
n *= sign;
|
|
||||||
|
|
||||||
/* We want to return something that is an offset to HISTORY_BASE. */
|
|
||||||
|
|
||||||
/* If the value is negative or zero, then it is an offset from
|
|
||||||
the current history item. */
|
|
||||||
/* We don't use HN_FIRST here, so we don't return different values
|
|
||||||
depending on whether we're looking for the first or last in a
|
|
||||||
pair of range arguments, but nobody else does, either. */
|
|
||||||
if (n < 0)
|
|
||||||
{
|
|
||||||
n += i + 1;
|
|
||||||
return (n < 0 ? 0 : n);
|
|
||||||
}
|
|
||||||
else if (n == 0)
|
|
||||||
return ((sign == -1) ? (listing ? real_last : HIST_INVALID) : i);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If we're out of range (greater than I (last history entry) or
|
|
||||||
less than HISTORY_BASE, we want to return different values
|
|
||||||
based on whether or not we are looking for the first or last
|
|
||||||
value in a desired range of history entries. */
|
|
||||||
n -= history_base;
|
|
||||||
if (n < 0)
|
|
||||||
return (mode & HN_FIRST ? 0 : i);
|
|
||||||
else if (n >= i)
|
|
||||||
return (mode & HN_FIRST ? 0 : i);
|
|
||||||
else
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clen = strlen (command);
|
|
||||||
for (j = i; j >= 0; j--)
|
|
||||||
{
|
|
||||||
if (STREQN (command, histline (j), clen))
|
|
||||||
return (j);
|
|
||||||
}
|
|
||||||
return (HIST_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Locate the most recent history line which begins with
|
|
||||||
COMMAND in HLIST, and return a malloc()'ed copy of it.
|
|
||||||
MODE is 1 if we are listing commands, 0 if we are executing them. */
|
|
||||||
static char *
|
|
||||||
fc_gethist (command, hlist, mode)
|
|
||||||
char *command;
|
|
||||||
HIST_ENTRY **hlist;
|
|
||||||
int mode;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (hlist == 0)
|
|
||||||
return ((char *)NULL);
|
|
||||||
|
|
||||||
i = fc_gethnum (command, hlist, mode);
|
|
||||||
|
|
||||||
if (i >= 0)
|
|
||||||
return (savestring (histline (i)));
|
|
||||||
else
|
|
||||||
return ((char *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef INCLUDE_UNUSED
|
|
||||||
/* Read the edited history lines from STREAM and return them
|
|
||||||
one at a time. This can read unlimited length lines. The
|
|
||||||
caller should free the storage. */
|
|
||||||
static char *
|
|
||||||
fc_readline (stream)
|
|
||||||
FILE *stream;
|
|
||||||
{
|
|
||||||
register int c;
|
|
||||||
int line_len = 0, lindex = 0;
|
|
||||||
char *line = (char *)NULL;
|
|
||||||
|
|
||||||
while ((c = getc (stream)) != EOF)
|
|
||||||
{
|
|
||||||
if ((lindex + 2) >= line_len)
|
|
||||||
line = (char *)xrealloc (line, (line_len += 128));
|
|
||||||
|
|
||||||
if (c == '\n')
|
|
||||||
{
|
|
||||||
line[lindex++] = '\n';
|
|
||||||
line[lindex++] = '\0';
|
|
||||||
return (line);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
line[lindex++] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lindex)
|
|
||||||
{
|
|
||||||
if (line)
|
|
||||||
free (line);
|
|
||||||
|
|
||||||
return ((char *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lindex + 2 >= line_len)
|
|
||||||
line = (char *)xrealloc (line, lindex + 3);
|
|
||||||
|
|
||||||
line[lindex++] = '\n'; /* Finish with newline if none in file */
|
|
||||||
line[lindex++] = '\0';
|
|
||||||
return (line);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Perform the SUBS on COMMAND.
|
|
||||||
SUBS is a list of substitutions, and COMMAND is a simple string.
|
|
||||||
Return a pointer to a malloc'ed string which contains the substituted
|
|
||||||
command. */
|
|
||||||
static char *
|
|
||||||
fc_dosubs (command, subs)
|
|
||||||
char *command;
|
|
||||||
REPL *subs;
|
|
||||||
{
|
|
||||||
register char *new, *t;
|
|
||||||
register REPL *r;
|
|
||||||
|
|
||||||
for (new = savestring (command), r = subs; r; r = r->next)
|
|
||||||
{
|
|
||||||
t = strsub (new, r->pat, r->rep, 1);
|
|
||||||
free (new);
|
|
||||||
new = t;
|
|
||||||
}
|
|
||||||
return (new);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use `command' to replace the last entry in the history list, which,
|
|
||||||
by this time, is `fc blah...'. The intent is that the new command
|
|
||||||
become the history entry, and that `fc' should never appear in the
|
|
||||||
history list. This way you can do `r' to your heart's content. */
|
|
||||||
static void
|
|
||||||
fc_replhist (command)
|
|
||||||
char *command;
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (command == 0 || *command == '\0')
|
|
||||||
return;
|
|
||||||
|
|
||||||
n = strlen (command);
|
|
||||||
if (command[n - 1] == '\n')
|
|
||||||
command[n - 1] = '\0';
|
|
||||||
|
|
||||||
if (command && *command)
|
|
||||||
{
|
|
||||||
bash_delete_last_history ();
|
|
||||||
maybe_add_history (command); /* Obeys HISTCONTROL setting. */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef INCLUDE_UNUSED
|
|
||||||
/* Add LINE to the history, after removing a single trailing newline. */
|
|
||||||
static void
|
|
||||||
fc_addhist (line)
|
|
||||||
char *line;
|
|
||||||
{
|
|
||||||
register int n;
|
|
||||||
|
|
||||||
if (line == 0 || *line == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
n = strlen (line);
|
|
||||||
|
|
||||||
if (line[n - 1] == '\n')
|
|
||||||
line[n - 1] = '\0';
|
|
||||||
|
|
||||||
if (line && *line)
|
|
||||||
maybe_add_history (line); /* Obeys HISTCONTROL setting. */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* HISTORY */
|
|
146
third_party/bash/builtins_fg_bg.c
vendored
146
third_party/bash/builtins_fg_bg.c
vendored
|
@ -1,146 +0,0 @@
|
||||||
/* fg_bg.c, created from fg_bg.def. */
|
|
||||||
#line 22 "./fg_bg.def"
|
|
||||||
|
|
||||||
#line 36 "./fg_bg.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "bashtypes.h"
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "jobs.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
static int fg_bg PARAMS((WORD_LIST *, int));
|
|
||||||
|
|
||||||
/* How to bring a job into the foreground. */
|
|
||||||
int
|
|
||||||
fg_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int fg_bit;
|
|
||||||
register WORD_LIST *t;
|
|
||||||
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
if (job_control == 0)
|
|
||||||
{
|
|
||||||
sh_nojobs ((char *)NULL);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (no_options (list))
|
|
||||||
return (EX_USAGE);
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
/* If the last arg on the line is '&', then start this job in the
|
|
||||||
background. Else, fg the job. */
|
|
||||||
for (t = list; t && t->next; t = t->next)
|
|
||||||
;
|
|
||||||
fg_bit = (t && t->word->word[0] == '&' && t->word->word[1] == '\0') == 0;
|
|
||||||
|
|
||||||
return (fg_bg (list, fg_bit));
|
|
||||||
}
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
|
|
||||||
#line 100 "./fg_bg.def"
|
|
||||||
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
/* How to put a job into the background. */
|
|
||||||
int
|
|
||||||
bg_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
if (job_control == 0)
|
|
||||||
{
|
|
||||||
sh_nojobs ((char *)NULL);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (no_options (list))
|
|
||||||
return (EX_USAGE);
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
/* This relies on the fact that fg_bg() takes a WORD_LIST *, but only acts
|
|
||||||
on the first member (if any) of that list. */
|
|
||||||
r = EXECUTION_SUCCESS;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (fg_bg (list, 0) == EXECUTION_FAILURE)
|
|
||||||
r = EXECUTION_FAILURE;
|
|
||||||
if (list)
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
while (list);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* How to put a job into the foreground/background. */
|
|
||||||
static int
|
|
||||||
fg_bg (list, foreground)
|
|
||||||
WORD_LIST *list;
|
|
||||||
int foreground;
|
|
||||||
{
|
|
||||||
sigset_t set, oset;
|
|
||||||
int job, status, old_async_pid;
|
|
||||||
JOB *j;
|
|
||||||
|
|
||||||
BLOCK_CHILD (set, oset);
|
|
||||||
job = get_job_spec (list);
|
|
||||||
|
|
||||||
if (INVALID_JOB (job))
|
|
||||||
{
|
|
||||||
if (job != DUP_JOB)
|
|
||||||
sh_badjob (list ? list->word->word : _("current"));
|
|
||||||
|
|
||||||
goto failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
j = get_job_by_jid (job);
|
|
||||||
/* Or if j->pgrp == shell_pgrp. */
|
|
||||||
if (IS_JOBCONTROL (job) == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("job %d started without job control"), job + 1);
|
|
||||||
goto failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foreground == 0)
|
|
||||||
{
|
|
||||||
old_async_pid = last_asynchronous_pid;
|
|
||||||
last_asynchronous_pid = j->pgrp; /* As per Posix.2 5.4.2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
status = start_job (job, foreground);
|
|
||||||
|
|
||||||
if (status >= 0)
|
|
||||||
{
|
|
||||||
/* win: */
|
|
||||||
UNBLOCK_CHILD (oset);
|
|
||||||
return (foreground ? status : EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (foreground == 0)
|
|
||||||
last_asynchronous_pid = old_async_pid;
|
|
||||||
|
|
||||||
failure:
|
|
||||||
UNBLOCK_CHILD (oset);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* JOB_CONTROL */
|
|
284
third_party/bash/builtins_getopts.c
vendored
284
third_party/bash/builtins_getopts.c
vendored
|
@ -1,284 +0,0 @@
|
||||||
/* getopts.c, created from getopts.def. */
|
|
||||||
#line 22 "./getopts.def"
|
|
||||||
|
|
||||||
#line 64 "./getopts.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
#include "getopt.h"
|
|
||||||
|
|
||||||
#define G_EOF -1
|
|
||||||
#define G_INVALID_OPT -2
|
|
||||||
#define G_ARG_MISSING -3
|
|
||||||
|
|
||||||
static int getopts_unbind_variable PARAMS((char *));
|
|
||||||
static int getopts_bind_variable PARAMS((char *, char *));
|
|
||||||
static int dogetopts PARAMS((int, char **));
|
|
||||||
|
|
||||||
/* getopts_reset is magic code for when OPTIND is reset. N is the
|
|
||||||
value that has just been assigned to OPTIND. */
|
|
||||||
void
|
|
||||||
getopts_reset (newind)
|
|
||||||
int newind;
|
|
||||||
{
|
|
||||||
sh_optind = newind;
|
|
||||||
sh_badopt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
getopts_unbind_variable (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
return (unbind_variable (name));
|
|
||||||
#else
|
|
||||||
return (unbind_variable_noref (name));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
getopts_bind_variable (name, value)
|
|
||||||
char *name, *value;
|
|
||||||
{
|
|
||||||
SHELL_VAR *v;
|
|
||||||
|
|
||||||
if (legal_identifier (name))
|
|
||||||
{
|
|
||||||
v = bind_variable (name, value, 0);
|
|
||||||
if (v && (readonly_p (v) || noassign_p (v)))
|
|
||||||
return (EX_MISCERROR);
|
|
||||||
return (v ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_invalidid (name);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Error handling is now performed as specified by Posix.2, draft 11
|
|
||||||
(identical to that of ksh-88). The special handling is enabled if
|
|
||||||
the first character of the option string is a colon; this handling
|
|
||||||
disables diagnostic messages concerning missing option arguments
|
|
||||||
and invalid option characters. The handling is as follows.
|
|
||||||
|
|
||||||
INVALID OPTIONS:
|
|
||||||
name -> "?"
|
|
||||||
if (special_error) then
|
|
||||||
OPTARG = option character found
|
|
||||||
no error output
|
|
||||||
else
|
|
||||||
OPTARG unset
|
|
||||||
diagnostic message
|
|
||||||
fi
|
|
||||||
|
|
||||||
MISSING OPTION ARGUMENT;
|
|
||||||
if (special_error) then
|
|
||||||
name -> ":"
|
|
||||||
OPTARG = option character found
|
|
||||||
else
|
|
||||||
name -> "?"
|
|
||||||
OPTARG unset
|
|
||||||
diagnostic message
|
|
||||||
fi
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
dogetopts (argc, argv)
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
{
|
|
||||||
int ret, special_error, old_opterr, i, n;
|
|
||||||
char strval[2], numval[16];
|
|
||||||
char *optstr; /* list of options */
|
|
||||||
char *name; /* variable to get flag val */
|
|
||||||
char *t;
|
|
||||||
|
|
||||||
if (argc < 3)
|
|
||||||
{
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* argv[0] is "getopts". */
|
|
||||||
|
|
||||||
optstr = argv[1];
|
|
||||||
name = argv[2];
|
|
||||||
argc -= 2;
|
|
||||||
argv += 2;
|
|
||||||
|
|
||||||
special_error = optstr[0] == ':';
|
|
||||||
|
|
||||||
if (special_error)
|
|
||||||
{
|
|
||||||
old_opterr = sh_opterr;
|
|
||||||
optstr++;
|
|
||||||
sh_opterr = 0; /* suppress diagnostic messages */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc > 1)
|
|
||||||
{
|
|
||||||
sh_getopt_restore_state (argv);
|
|
||||||
t = argv[0];
|
|
||||||
argv[0] = dollar_vars[0];
|
|
||||||
ret = sh_getopt (argc, argv, optstr);
|
|
||||||
argv[0] = t;
|
|
||||||
}
|
|
||||||
else if (rest_of_args == (WORD_LIST *)NULL)
|
|
||||||
{
|
|
||||||
for (i = 0; i < 10 && dollar_vars[i]; i++)
|
|
||||||
;
|
|
||||||
|
|
||||||
sh_getopt_restore_state (dollar_vars);
|
|
||||||
ret = sh_getopt (i, dollar_vars, optstr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
register WORD_LIST *words;
|
|
||||||
char **v;
|
|
||||||
|
|
||||||
i = number_of_args () + 1; /* +1 for $0 */
|
|
||||||
v = strvec_create (i + 1);
|
|
||||||
for (i = 0; i < 10 && dollar_vars[i]; i++)
|
|
||||||
v[i] = dollar_vars[i];
|
|
||||||
for (words = rest_of_args; words; words = words->next, i++)
|
|
||||||
v[i] = words->word->word;
|
|
||||||
v[i] = (char *)NULL;
|
|
||||||
sh_getopt_restore_state (v);
|
|
||||||
ret = sh_getopt (i, v, optstr);
|
|
||||||
free (v);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (special_error)
|
|
||||||
sh_opterr = old_opterr;
|
|
||||||
|
|
||||||
/* Set the OPTIND variable in any case, to handle "--" skipping. It's
|
|
||||||
highly unlikely that 14 digits will be too few. */
|
|
||||||
if (sh_optind < 10)
|
|
||||||
{
|
|
||||||
numval[14] = sh_optind + '0';
|
|
||||||
numval[15] = '\0';
|
|
||||||
i = 14;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numval[i = 15] = '\0';
|
|
||||||
n = sh_optind;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
numval[--i] = (n % 10) + '0';
|
|
||||||
}
|
|
||||||
while (n /= 10);
|
|
||||||
}
|
|
||||||
bind_variable ("OPTIND", numval + i, 0);
|
|
||||||
|
|
||||||
/* If an error occurred, decide which one it is and set the return
|
|
||||||
code appropriately. In all cases, the option character in error
|
|
||||||
is in OPTOPT. If an invalid option was encountered, OPTARG is
|
|
||||||
NULL. If a required option argument was missing, OPTARG points
|
|
||||||
to a NULL string (that is, sh_optarg[0] == 0). */
|
|
||||||
if (ret == '?')
|
|
||||||
{
|
|
||||||
if (sh_optarg == NULL)
|
|
||||||
ret = G_INVALID_OPT;
|
|
||||||
else if (sh_optarg[0] == '\0')
|
|
||||||
ret = G_ARG_MISSING;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == G_EOF)
|
|
||||||
{
|
|
||||||
getopts_unbind_variable ("OPTARG");
|
|
||||||
getopts_bind_variable (name, "?");
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == G_INVALID_OPT)
|
|
||||||
{
|
|
||||||
/* Invalid option encountered. */
|
|
||||||
ret = getopts_bind_variable (name, "?");
|
|
||||||
|
|
||||||
if (special_error)
|
|
||||||
{
|
|
||||||
strval[0] = (char)sh_optopt;
|
|
||||||
strval[1] = '\0';
|
|
||||||
bind_variable ("OPTARG", strval, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
getopts_unbind_variable ("OPTARG");
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == G_ARG_MISSING)
|
|
||||||
{
|
|
||||||
/* Required argument missing. */
|
|
||||||
if (special_error)
|
|
||||||
{
|
|
||||||
ret = getopts_bind_variable (name, ":");
|
|
||||||
|
|
||||||
strval[0] = (char)sh_optopt;
|
|
||||||
strval[1] = '\0';
|
|
||||||
bind_variable ("OPTARG", strval, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = getopts_bind_variable (name, "?");
|
|
||||||
getopts_unbind_variable ("OPTARG");
|
|
||||||
}
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind_variable ("OPTARG", sh_optarg, 0);
|
|
||||||
|
|
||||||
strval[0] = (char) ret;
|
|
||||||
strval[1] = '\0';
|
|
||||||
return (getopts_bind_variable (name, strval));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The getopts builtin. Build an argv, and call dogetopts with it. */
|
|
||||||
int
|
|
||||||
getopts_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
char **av;
|
|
||||||
int ac, ret;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
{
|
|
||||||
builtin_usage ();
|
|
||||||
return EX_USAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_internal_getopt ();
|
|
||||||
if ((ret = internal_getopt (list, "")) != -1)
|
|
||||||
{
|
|
||||||
if (ret == GETOPT_HELP)
|
|
||||||
builtin_help ();
|
|
||||||
else
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
av = make_builtin_argv (list, &ac);
|
|
||||||
ret = dogetopts (ac, av);
|
|
||||||
free ((char *)av);
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
|
264
third_party/bash/builtins_hash.c
vendored
264
third_party/bash/builtins_hash.c
vendored
|
@ -1,264 +0,0 @@
|
||||||
/* hash.c, created from hash.def. */
|
|
||||||
#line 22 "./hash.def"
|
|
||||||
|
|
||||||
#line 46 "./hash.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "bashtypes.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "flags.h"
|
|
||||||
#include "findcmd.h"
|
|
||||||
#include "hashcmd.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
|
|
||||||
extern int dot_found_in_search;
|
|
||||||
|
|
||||||
static int add_hashed_command PARAMS((char *, int));
|
|
||||||
static int print_hash_info PARAMS((BUCKET_CONTENTS *));
|
|
||||||
static int print_portable_hash_info PARAMS((BUCKET_CONTENTS *));
|
|
||||||
static int print_hashed_commands PARAMS((int));
|
|
||||||
static int list_hashed_filename_targets PARAMS((WORD_LIST *, int));
|
|
||||||
|
|
||||||
/* Print statistics on the current state of hashed commands. If LIST is
|
|
||||||
not empty, then rehash (or hash in the first place) the specified
|
|
||||||
commands. */
|
|
||||||
int
|
|
||||||
hash_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int expunge_hash_table, list_targets, list_portably, delete, opt;
|
|
||||||
char *w, *pathname;
|
|
||||||
|
|
||||||
if (hashing_enabled == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("hashing disabled"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
expunge_hash_table = list_targets = list_portably = delete = 0;
|
|
||||||
pathname = (char *)NULL;
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "dlp:rt")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'd':
|
|
||||||
delete = 1;
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
list_portably = 1;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
pathname = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
expunge_hash_table = 1;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
list_targets = 1;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
/* hash -t requires at least one argument. */
|
|
||||||
if (list == 0 && (delete || list_targets))
|
|
||||||
{
|
|
||||||
sh_needarg (delete ? "-d" : "-t");
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We want hash -r to be silent, but hash -- to print hashing info, so
|
|
||||||
we test expunge_hash_table. */
|
|
||||||
if (list == 0 && expunge_hash_table == 0)
|
|
||||||
{
|
|
||||||
opt = print_hashed_commands (list_portably);
|
|
||||||
if (opt == 0 && posixly_correct == 0 &&
|
|
||||||
(list_portably == 0 || shell_compatibility_level <= 50))
|
|
||||||
printf (_("%s: hash table empty\n"), this_command_name);
|
|
||||||
|
|
||||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expunge_hash_table)
|
|
||||||
phash_flush ();
|
|
||||||
|
|
||||||
/* If someone runs `hash -r -t xyz' he will be disappointed. */
|
|
||||||
if (list_targets)
|
|
||||||
return (list_hashed_filename_targets (list, list_portably));
|
|
||||||
|
|
||||||
#if defined (RESTRICTED_SHELL)
|
|
||||||
if (restricted && pathname)
|
|
||||||
{
|
|
||||||
if (strchr (pathname, '/'))
|
|
||||||
{
|
|
||||||
sh_restricted (pathname);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
/* If we are changing the hash table in a restricted shell, make sure the
|
|
||||||
target pathname can be found using a $PATH search. */
|
|
||||||
w = find_user_command (pathname);
|
|
||||||
if (w == 0 || *w == 0 || executable_file (w) == 0)
|
|
||||||
{
|
|
||||||
sh_notfound (pathname);
|
|
||||||
free (w);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
free (w);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (opt = EXECUTION_SUCCESS; list; list = list->next)
|
|
||||||
{
|
|
||||||
/* Add, remove or rehash the specified commands. */
|
|
||||||
w = list->word->word;
|
|
||||||
if (absolute_program (w))
|
|
||||||
continue;
|
|
||||||
else if (pathname)
|
|
||||||
{
|
|
||||||
if (file_isdir (pathname))
|
|
||||||
{
|
|
||||||
#ifdef EISDIR
|
|
||||||
builtin_error ("%s: %s", pathname, strerror (EISDIR));
|
|
||||||
#else
|
|
||||||
builtin_error (_("%s: is a directory"), pathname);
|
|
||||||
#endif
|
|
||||||
opt = EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
phash_insert (w, pathname, 0, 0);
|
|
||||||
}
|
|
||||||
else if (delete)
|
|
||||||
{
|
|
||||||
if (phash_remove (w))
|
|
||||||
{
|
|
||||||
sh_notfound (w);
|
|
||||||
opt = EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (add_hashed_command (w, 0))
|
|
||||||
opt = EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
fflush (stdout);
|
|
||||||
return (opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
add_hashed_command (w, quiet)
|
|
||||||
char *w;
|
|
||||||
int quiet;
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
char *full_path;
|
|
||||||
|
|
||||||
rv = 0;
|
|
||||||
if (find_function (w) == 0 && find_shell_builtin (w) == 0)
|
|
||||||
{
|
|
||||||
phash_remove (w);
|
|
||||||
full_path = find_user_command (w);
|
|
||||||
if (full_path && executable_file (full_path))
|
|
||||||
phash_insert (w, full_path, dot_found_in_search, 0);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (quiet == 0)
|
|
||||||
sh_notfound (w);
|
|
||||||
rv++;
|
|
||||||
}
|
|
||||||
FREE (full_path);
|
|
||||||
}
|
|
||||||
return (rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print information about current hashed info. */
|
|
||||||
static int
|
|
||||||
print_hash_info (item)
|
|
||||||
BUCKET_CONTENTS *item;
|
|
||||||
{
|
|
||||||
printf ("%4d\t%s\n", item->times_found, pathdata(item)->path);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
print_portable_hash_info (item)
|
|
||||||
BUCKET_CONTENTS *item;
|
|
||||||
{
|
|
||||||
char *fp, *fn;
|
|
||||||
|
|
||||||
fp = printable_filename (pathdata(item)->path, 1);
|
|
||||||
fn = printable_filename (item->key, 1);
|
|
||||||
printf ("builtin hash -p %s %s\n", fp, fn);
|
|
||||||
if (fp != pathdata(item)->path)
|
|
||||||
free (fp);
|
|
||||||
if (fn != item->key)
|
|
||||||
free (fn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
print_hashed_commands (fmt)
|
|
||||||
int fmt;
|
|
||||||
{
|
|
||||||
if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (fmt == 0)
|
|
||||||
printf (_("hits\tcommand\n"));
|
|
||||||
hash_walk (hashed_filenames, fmt ? print_portable_hash_info : print_hash_info);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
list_hashed_filename_targets (list, fmt)
|
|
||||||
WORD_LIST *list;
|
|
||||||
int fmt;
|
|
||||||
{
|
|
||||||
int all_found, multiple;
|
|
||||||
char *target;
|
|
||||||
WORD_LIST *l;
|
|
||||||
|
|
||||||
all_found = 1;
|
|
||||||
multiple = list->next != 0;
|
|
||||||
|
|
||||||
for (l = list; l; l = l->next)
|
|
||||||
{
|
|
||||||
target = phash_search (l->word->word);
|
|
||||||
if (target == 0)
|
|
||||||
{
|
|
||||||
all_found = 0;
|
|
||||||
sh_notfound (l->word->word);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (fmt)
|
|
||||||
printf ("builtin hash -p %s %s\n", target, l->word->word);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (multiple)
|
|
||||||
printf ("%s\t", l->word->word);
|
|
||||||
printf ("%s\n", target);
|
|
||||||
}
|
|
||||||
free (target);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
|
||||||
}
|
|
512
third_party/bash/builtins_help.c
vendored
512
third_party/bash/builtins_help.c
vendored
|
@ -1,512 +0,0 @@
|
||||||
/* help.c, created from help.def. */
|
|
||||||
#line 22 "./help.def"
|
|
||||||
|
|
||||||
#line 45 "./help.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HELP_BUILTIN)
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "filecntl.h"
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "pathexp.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
|
|
||||||
#include "strmatch.h"
|
|
||||||
#include "glob.h"
|
|
||||||
|
|
||||||
#ifndef errno
|
|
||||||
extern int errno;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern const char * const bash_copyright;
|
|
||||||
extern const char * const bash_license;
|
|
||||||
|
|
||||||
static void show_builtin_command_help PARAMS((void));
|
|
||||||
static int open_helpfile PARAMS((char *));
|
|
||||||
static void show_desc PARAMS((char *, int));
|
|
||||||
static void show_manpage PARAMS((char *, int));
|
|
||||||
static void show_longdoc PARAMS((int));
|
|
||||||
|
|
||||||
/* Print out a list of the known functions in the shell, and what they do.
|
|
||||||
If LIST is supplied, print out the list which matches for each pattern
|
|
||||||
specified. */
|
|
||||||
int
|
|
||||||
help_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
char *pattern, *name;
|
|
||||||
int plen, match_found, sflag, dflag, mflag, m, pass, this_found;
|
|
||||||
|
|
||||||
dflag = sflag = mflag = 0;
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((i = internal_getopt (list, "dms")) != -1)
|
|
||||||
{
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 'd':
|
|
||||||
dflag = 1;
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
mflag = 1;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
sflag = 1;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
{
|
|
||||||
show_shell_version (0);
|
|
||||||
show_builtin_command_help ();
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We should consider making `help bash' do something. */
|
|
||||||
|
|
||||||
if (glob_pattern_p (list->word->word) == 1)
|
|
||||||
{
|
|
||||||
printf ("%s", ngettext ("Shell commands matching keyword `", "Shell commands matching keywords `", (list->next ? 2 : 1)));
|
|
||||||
print_word_list (list, ", ");
|
|
||||||
printf ("%s", _("'\n\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (match_found = 0, pattern = ""; list; list = list->next)
|
|
||||||
{
|
|
||||||
pattern = list->word->word;
|
|
||||||
plen = strlen (pattern);
|
|
||||||
|
|
||||||
for (pass = 1, this_found = 0; pass < 3; pass++)
|
|
||||||
{
|
|
||||||
for (i = 0; name = shell_builtins[i].name; i++)
|
|
||||||
{
|
|
||||||
QUIT;
|
|
||||||
|
|
||||||
/* First pass: look for exact string or pattern matches.
|
|
||||||
Second pass: look for prefix matches like bash-4.2 */
|
|
||||||
if (pass == 1)
|
|
||||||
m = (strcmp (pattern, name) == 0) ||
|
|
||||||
(strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH);
|
|
||||||
else
|
|
||||||
m = strncmp (pattern, name, plen) == 0;
|
|
||||||
|
|
||||||
if (m)
|
|
||||||
{
|
|
||||||
this_found = 1;
|
|
||||||
match_found++;
|
|
||||||
if (dflag)
|
|
||||||
{
|
|
||||||
show_desc (name, i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (mflag)
|
|
||||||
{
|
|
||||||
show_manpage (name, i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf ("%s: %s\n", name, _(shell_builtins[i].short_doc));
|
|
||||||
|
|
||||||
if (sflag == 0)
|
|
||||||
show_longdoc (i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pass == 1 && this_found == 1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match_found == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("no help topics match `%s'. Try `help help' or `man -k %s' or `info %s'."), pattern, pattern, pattern);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
builtin_help ()
|
|
||||||
{
|
|
||||||
int ind;
|
|
||||||
ptrdiff_t d;
|
|
||||||
|
|
||||||
current_builtin = builtin_address_internal (this_command_name, 0);
|
|
||||||
if (current_builtin == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
d = current_builtin - shell_builtins;
|
|
||||||
|
|
||||||
#if defined (__STDC__)
|
|
||||||
ind = (int)d;
|
|
||||||
#else
|
|
||||||
ind = (int)d / sizeof (struct builtin);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
printf ("%s: %s\n", this_command_name, _(shell_builtins[ind].short_doc));
|
|
||||||
show_longdoc (ind);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
open_helpfile (name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = open (name, O_RDONLY);
|
|
||||||
if (fd == -1)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: cannot open: %s"), name, strerror (errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* By convention, enforced by mkbuiltins.c, if separate help files are being
|
|
||||||
used, the long_doc array contains one string -- the full pathname of the
|
|
||||||
help file for this builtin. */
|
|
||||||
static void
|
|
||||||
show_longdoc (i)
|
|
||||||
int i;
|
|
||||||
{
|
|
||||||
register int j;
|
|
||||||
char * const *doc;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
doc = shell_builtins[i].long_doc;
|
|
||||||
|
|
||||||
if (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL)
|
|
||||||
{
|
|
||||||
fd = open_helpfile (doc[0]);
|
|
||||||
if (fd < 0)
|
|
||||||
return;
|
|
||||||
zcatfd (fd, 1, doc[0]);
|
|
||||||
close (fd);
|
|
||||||
}
|
|
||||||
else if (doc)
|
|
||||||
for (j = 0; doc[j]; j++)
|
|
||||||
printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
show_desc (name, i)
|
|
||||||
char *name;
|
|
||||||
int i;
|
|
||||||
{
|
|
||||||
register int j, r;
|
|
||||||
char **doc, *line;
|
|
||||||
int fd, usefile;
|
|
||||||
|
|
||||||
doc = (char **)shell_builtins[i].long_doc;
|
|
||||||
|
|
||||||
usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL);
|
|
||||||
if (usefile)
|
|
||||||
{
|
|
||||||
fd = open_helpfile (doc[0]);
|
|
||||||
if (fd < 0)
|
|
||||||
return;
|
|
||||||
r = zmapfd (fd, &line, doc[0]);
|
|
||||||
close (fd);
|
|
||||||
/* XXX - handle errors if zmapfd returns < 0 */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
line = doc ? doc[0] : (char *)NULL;
|
|
||||||
|
|
||||||
printf ("%s - ", name);
|
|
||||||
for (j = 0; line && line[j]; j++)
|
|
||||||
{
|
|
||||||
putchar (line[j]);
|
|
||||||
if (line[j] == '\n')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fflush (stdout);
|
|
||||||
|
|
||||||
if (usefile)
|
|
||||||
free (line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print builtin help in pseudo-manpage format. */
|
|
||||||
static void
|
|
||||||
show_manpage (name, i)
|
|
||||||
char *name;
|
|
||||||
int i;
|
|
||||||
{
|
|
||||||
register int j;
|
|
||||||
char **doc, *line;
|
|
||||||
int fd, usefile;
|
|
||||||
|
|
||||||
doc = (char **)shell_builtins[i].long_doc;
|
|
||||||
|
|
||||||
usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL);
|
|
||||||
if (usefile)
|
|
||||||
{
|
|
||||||
fd = open_helpfile (doc[0]);
|
|
||||||
if (fd < 0)
|
|
||||||
return;
|
|
||||||
zmapfd (fd, &line, doc[0]);
|
|
||||||
close (fd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
line = doc ? _(doc[0]) : (char *)NULL;
|
|
||||||
|
|
||||||
/* NAME */
|
|
||||||
printf ("NAME\n");
|
|
||||||
printf ("%*s%s - ", BASE_INDENT, " ", name);
|
|
||||||
for (j = 0; line && line[j]; j++)
|
|
||||||
{
|
|
||||||
putchar (line[j]);
|
|
||||||
if (line[j] == '\n')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf ("\n");
|
|
||||||
|
|
||||||
/* SYNOPSIS */
|
|
||||||
printf ("SYNOPSIS\n");
|
|
||||||
printf ("%*s%s\n\n", BASE_INDENT, " ", _(shell_builtins[i].short_doc));
|
|
||||||
|
|
||||||
/* DESCRIPTION */
|
|
||||||
printf ("DESCRIPTION\n");
|
|
||||||
if (usefile == 0)
|
|
||||||
{
|
|
||||||
for (j = 0; doc[j]; j++)
|
|
||||||
printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (j = 0; line && line[j]; j++)
|
|
||||||
{
|
|
||||||
putchar (line[j]);
|
|
||||||
if (line[j] == '\n')
|
|
||||||
printf ("%*s", BASE_INDENT, " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
putchar ('\n');
|
|
||||||
|
|
||||||
/* SEE ALSO */
|
|
||||||
printf ("SEE ALSO\n");
|
|
||||||
printf ("%*sbash(1)\n\n", BASE_INDENT, " ");
|
|
||||||
|
|
||||||
/* IMPLEMENTATION */
|
|
||||||
printf ("IMPLEMENTATION\n");
|
|
||||||
printf ("%*s", BASE_INDENT, " ");
|
|
||||||
show_shell_version (0);
|
|
||||||
printf ("%*s", BASE_INDENT, " ");
|
|
||||||
printf ("%s\n", _(bash_copyright));
|
|
||||||
printf ("%*s", BASE_INDENT, " ");
|
|
||||||
printf ("%s\n", _(bash_license));
|
|
||||||
|
|
||||||
fflush (stdout);
|
|
||||||
if (usefile)
|
|
||||||
free (line);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dispcolumn (i, buf, bufsize, width, height)
|
|
||||||
int i;
|
|
||||||
char *buf;
|
|
||||||
size_t bufsize;
|
|
||||||
int width, height;
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
int dispcols;
|
|
||||||
char *helpdoc;
|
|
||||||
|
|
||||||
/* first column */
|
|
||||||
helpdoc = _(shell_builtins[i].short_doc);
|
|
||||||
|
|
||||||
buf[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
|
|
||||||
strncpy (buf + 1, helpdoc, width - 2);
|
|
||||||
buf[width - 2] = '>'; /* indicate truncation */
|
|
||||||
buf[width - 1] = '\0';
|
|
||||||
printf ("%s", buf);
|
|
||||||
if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
|
|
||||||
{
|
|
||||||
printf ("\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispcols = strlen (buf);
|
|
||||||
/* two spaces */
|
|
||||||
for (j = dispcols; j < width; j++)
|
|
||||||
putc (' ', stdout);
|
|
||||||
|
|
||||||
/* second column */
|
|
||||||
helpdoc = _(shell_builtins[i+height].short_doc);
|
|
||||||
|
|
||||||
buf[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*';
|
|
||||||
strncpy (buf + 1, helpdoc, width - 3);
|
|
||||||
buf[width - 3] = '>'; /* indicate truncation */
|
|
||||||
buf[width - 2] = '\0';
|
|
||||||
|
|
||||||
printf ("%s\n", buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (HANDLE_MULTIBYTE)
|
|
||||||
static void
|
|
||||||
wdispcolumn (i, buf, bufsize, width, height)
|
|
||||||
int i;
|
|
||||||
char *buf;
|
|
||||||
size_t bufsize;
|
|
||||||
int width, height;
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
int dispcols, dispchars;
|
|
||||||
char *helpdoc;
|
|
||||||
wchar_t *wcstr;
|
|
||||||
size_t slen, n;
|
|
||||||
|
|
||||||
/* first column */
|
|
||||||
helpdoc = _(shell_builtins[i].short_doc);
|
|
||||||
|
|
||||||
wcstr = 0;
|
|
||||||
slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
|
|
||||||
if (slen == -1)
|
|
||||||
{
|
|
||||||
dispcolumn (i, buf, bufsize, width, height);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No bigger than the passed max width */
|
|
||||||
if (slen >= width)
|
|
||||||
slen = width - 2;
|
|
||||||
wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (width + 2));
|
|
||||||
n = mbstowcs (wcstr+1, helpdoc, slen + 1);
|
|
||||||
wcstr[n+1] = L'\0';
|
|
||||||
|
|
||||||
/* Turn tabs and newlines into spaces for column display, since wcwidth
|
|
||||||
returns -1 for them */
|
|
||||||
for (j = 1; j < n; j++)
|
|
||||||
if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
|
|
||||||
wcstr[j] = L' ';
|
|
||||||
|
|
||||||
/* dispchars == number of characters that will be displayed */
|
|
||||||
dispchars = wcsnwidth (wcstr+1, slen, width - 2);
|
|
||||||
/* dispcols == number of columns required to display DISPCHARS */
|
|
||||||
dispcols = wcswidth (wcstr+1, dispchars) + 1; /* +1 for ' ' or '*' */
|
|
||||||
|
|
||||||
wcstr[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? L' ' : L'*';
|
|
||||||
|
|
||||||
if (dispcols >= width-2)
|
|
||||||
{
|
|
||||||
wcstr[dispchars] = L'>'; /* indicate truncation */
|
|
||||||
wcstr[dispchars+1] = L'\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
printf ("%ls", wcstr);
|
|
||||||
if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
|
|
||||||
{
|
|
||||||
printf ("\n");
|
|
||||||
free (wcstr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at least one space */
|
|
||||||
for (j = dispcols; j < width; j++)
|
|
||||||
putc (' ', stdout);
|
|
||||||
|
|
||||||
/* second column */
|
|
||||||
helpdoc = _(shell_builtins[i+height].short_doc);
|
|
||||||
slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
|
|
||||||
if (slen == -1)
|
|
||||||
{
|
|
||||||
/* for now */
|
|
||||||
printf ("%c%s\n", (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*', helpdoc);
|
|
||||||
free (wcstr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reuse wcstr since it is already width wide chars long */
|
|
||||||
if (slen >= width)
|
|
||||||
slen = width - 2;
|
|
||||||
n = mbstowcs (wcstr+1, helpdoc, slen + 1);
|
|
||||||
wcstr[n+1] = L'\0'; /* make sure null-terminated */
|
|
||||||
|
|
||||||
/* Turn tabs and newlines into spaces for column display */
|
|
||||||
for (j = 1; j < n; j++)
|
|
||||||
if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
|
|
||||||
wcstr[j] = L' ';
|
|
||||||
|
|
||||||
/* dispchars == number of characters that will be displayed */
|
|
||||||
dispchars = wcsnwidth (wcstr+1, slen, width - 2);
|
|
||||||
dispcols = wcswidth (wcstr+1, dispchars) + 1; /* +1 for ' ' or '*' */
|
|
||||||
|
|
||||||
wcstr[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? L' ' : L'*';
|
|
||||||
|
|
||||||
/* The dispchars-1 is there for terminals that behave strangely when you
|
|
||||||
have \n in the nth column for terminal width n; this is what bash-4.3
|
|
||||||
did. */
|
|
||||||
if (dispcols >= width - 2)
|
|
||||||
{
|
|
||||||
wcstr[dispchars-1] = L'>'; /* indicate truncation */
|
|
||||||
wcstr[dispchars] = L'\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
printf ("%ls\n", wcstr);
|
|
||||||
|
|
||||||
free (wcstr);
|
|
||||||
}
|
|
||||||
#endif /* HANDLE_MULTIBYTE */
|
|
||||||
|
|
||||||
static void
|
|
||||||
show_builtin_command_help ()
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
int height, width;
|
|
||||||
char *t, blurb[128];
|
|
||||||
|
|
||||||
printf (
|
|
||||||
_("These shell commands are defined internally. Type `help' to see this list.\n\
|
|
||||||
Type `help name' to find out more about the function `name'.\n\
|
|
||||||
Use `info bash' to find out more about the shell in general.\n\
|
|
||||||
Use `man -k' or `info' to find out more about commands not in this list.\n\
|
|
||||||
\n\
|
|
||||||
A star (*) next to a name means that the command is disabled.\n\
|
|
||||||
\n"));
|
|
||||||
|
|
||||||
width = default_columns ();
|
|
||||||
|
|
||||||
width /= 2;
|
|
||||||
if (width > sizeof (blurb))
|
|
||||||
width = sizeof (blurb);
|
|
||||||
if (width <= 3)
|
|
||||||
width = 40;
|
|
||||||
height = (num_shell_builtins + 1) / 2; /* number of rows */
|
|
||||||
|
|
||||||
for (i = 0; i < height; i++)
|
|
||||||
{
|
|
||||||
QUIT;
|
|
||||||
|
|
||||||
#if defined (HANDLE_MULTIBYTE)
|
|
||||||
if (MB_CUR_MAX > 1)
|
|
||||||
wdispcolumn (i, blurb, sizeof (blurb), width, height);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
dispcolumn (i, blurb, sizeof (blurb), width, height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* HELP_BUILTIN */
|
|
411
third_party/bash/builtins_history.c
vendored
411
third_party/bash/builtins_history.c
vendored
|
@ -1,411 +0,0 @@
|
||||||
/* history.c, created from history.def. */
|
|
||||||
#line 22 "./history.def"
|
|
||||||
|
|
||||||
#line 58 "./history.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HISTORY)
|
|
||||||
#include "bashtypes.h"
|
|
||||||
#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
|
|
||||||
# include <sys/file.h>
|
|
||||||
#endif
|
|
||||||
#include "posixstat.h"
|
|
||||||
#include "filecntl.h"
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "flags.h"
|
|
||||||
#include "parser.h"
|
|
||||||
#include "bashhist.h"
|
|
||||||
#include "third_party/readline/history.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#if !defined (errno)
|
|
||||||
extern int errno;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static char *histtime PARAMS((HIST_ENTRY *, const char *));
|
|
||||||
static int display_history PARAMS((WORD_LIST *));
|
|
||||||
static void push_history PARAMS((WORD_LIST *));
|
|
||||||
static int expand_and_print_history PARAMS((WORD_LIST *));
|
|
||||||
|
|
||||||
#define AFLAG 0x01
|
|
||||||
#define RFLAG 0x02
|
|
||||||
#define WFLAG 0x04
|
|
||||||
#define NFLAG 0x08
|
|
||||||
#define SFLAG 0x10
|
|
||||||
#define PFLAG 0x20
|
|
||||||
#define CFLAG 0x40
|
|
||||||
#define DFLAG 0x80
|
|
||||||
|
|
||||||
#ifndef TIMELEN_MAX
|
|
||||||
# define TIMELEN_MAX 128
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
|
||||||
history_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int flags, opt, result, old_history_lines, obase, ind;
|
|
||||||
char *filename, *delete_arg, *range;
|
|
||||||
intmax_t delete_offset;
|
|
||||||
|
|
||||||
flags = 0;
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "acd:npsrw")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'a':
|
|
||||||
flags |= AFLAG;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
flags |= CFLAG;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
flags |= NFLAG;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
flags |= RFLAG;
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
flags |= WFLAG;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
flags |= SFLAG;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
flags |= DFLAG;
|
|
||||||
delete_arg = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
#if defined (BANG_HISTORY)
|
|
||||||
flags |= PFLAG;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
opt = flags & (AFLAG|RFLAG|WFLAG|NFLAG);
|
|
||||||
if (opt && opt != AFLAG && opt != RFLAG && opt != WFLAG && opt != NFLAG)
|
|
||||||
{
|
|
||||||
builtin_error (_("cannot use more than one of -anrw"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clear the history, but allow other arguments to add to it again. */
|
|
||||||
if (flags & CFLAG)
|
|
||||||
{
|
|
||||||
bash_clear_history ();
|
|
||||||
if (list == 0)
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & SFLAG)
|
|
||||||
{
|
|
||||||
if (list)
|
|
||||||
push_history (list);
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
#if defined (BANG_HISTORY)
|
|
||||||
else if (flags & PFLAG)
|
|
||||||
{
|
|
||||||
if (list)
|
|
||||||
return (expand_and_print_history (list));
|
|
||||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if ((flags & DFLAG) && (range = strchr ((delete_arg[0] == '-') ? delete_arg + 1 : delete_arg, '-')))
|
|
||||||
{
|
|
||||||
intmax_t delete_start, delete_end;
|
|
||||||
*range++ = '\0';
|
|
||||||
if (legal_number (delete_arg, &delete_start) == 0 || legal_number (range, &delete_end) == 0)
|
|
||||||
{
|
|
||||||
range[-1] = '-';
|
|
||||||
sh_erange (delete_arg, _("history position"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
if (delete_arg[0] == '-' && delete_start < 0)
|
|
||||||
/* the_history[history_length] == 0x0, so this is correct */
|
|
||||||
delete_start += history_length;
|
|
||||||
/* numbers as displayed by display_history are offset by history_base */
|
|
||||||
else if (delete_start > 0)
|
|
||||||
delete_start -= history_base;
|
|
||||||
|
|
||||||
if (delete_start < 0 || delete_start >= history_length)
|
|
||||||
{
|
|
||||||
sh_erange (delete_arg, _("history position"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (range[0] == '-' && delete_end < 0)
|
|
||||||
delete_end += history_length;
|
|
||||||
else if (delete_end > 0)
|
|
||||||
delete_end -= history_base;
|
|
||||||
|
|
||||||
if (delete_end < 0 || delete_end >= history_length)
|
|
||||||
{
|
|
||||||
sh_erange (range, _("history position"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
/* XXX - print error if end < start? */
|
|
||||||
result = bash_delete_history_range (delete_start, delete_end);
|
|
||||||
if (where_history () > history_length)
|
|
||||||
history_set_pos (history_length);
|
|
||||||
return (result ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else if (flags & DFLAG)
|
|
||||||
{
|
|
||||||
if (legal_number (delete_arg, &delete_offset) == 0)
|
|
||||||
{
|
|
||||||
sh_erange (delete_arg, _("history position"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
/* check for negative offsets, count back from end of list */
|
|
||||||
if (delete_arg[0] == '-' && delete_offset < 0)
|
|
||||||
{
|
|
||||||
/* since the_history[history_length] == 0x0, this calculation means
|
|
||||||
that history -d -1 will delete the last history entry, which at
|
|
||||||
this point is the history -d -1 we just added. */
|
|
||||||
ind = history_length + delete_offset;
|
|
||||||
if (ind < 0) /* offset by history_base below */
|
|
||||||
{
|
|
||||||
sh_erange (delete_arg, _("history position"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
opt = ind + history_base; /* compensate for opt - history_base below */
|
|
||||||
}
|
|
||||||
else if ((delete_offset < history_base) || (delete_offset >= (history_base + history_length)))
|
|
||||||
{
|
|
||||||
sh_erange (delete_arg, _("history position"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
opt = delete_offset;
|
|
||||||
|
|
||||||
/* Positive arguments from numbers as displayed by display_history need
|
|
||||||
to be offset by history_base */
|
|
||||||
result = bash_delete_histent (opt - history_base);
|
|
||||||
/* Since remove_history changes history_length, this can happen if
|
|
||||||
we delete the last history entry. */
|
|
||||||
if (where_history () > history_length)
|
|
||||||
history_set_pos (history_length);
|
|
||||||
return (result ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else if ((flags & (AFLAG|RFLAG|NFLAG|WFLAG|CFLAG)) == 0)
|
|
||||||
{
|
|
||||||
result = display_history (list);
|
|
||||||
return (sh_chkwrite (result));
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = list ? list->word->word : get_string_value ("HISTFILE");
|
|
||||||
result = EXECUTION_SUCCESS;
|
|
||||||
|
|
||||||
#if defined (RESTRICTED_SHELL)
|
|
||||||
if (restricted && strchr (filename, '/'))
|
|
||||||
{
|
|
||||||
sh_restricted (filename);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (flags & AFLAG) /* Append session's history to file. */
|
|
||||||
result = maybe_append_history (filename);
|
|
||||||
else if (flags & WFLAG) /* Write entire history. */
|
|
||||||
result = write_history (filename);
|
|
||||||
else if (flags & RFLAG) /* Read entire file. */
|
|
||||||
{
|
|
||||||
result = read_history (filename);
|
|
||||||
history_lines_in_file = history_lines_read_from_file;
|
|
||||||
/* history_lines_in_file = where_history () + history_base - 1; */
|
|
||||||
}
|
|
||||||
else if (flags & NFLAG) /* Read `new' history from file. */
|
|
||||||
{
|
|
||||||
/* Read all of the lines in the file that we haven't already read. */
|
|
||||||
old_history_lines = history_lines_in_file;
|
|
||||||
obase = history_base;
|
|
||||||
|
|
||||||
using_history ();
|
|
||||||
result = read_history_range (filename, history_lines_in_file, -1);
|
|
||||||
using_history ();
|
|
||||||
|
|
||||||
history_lines_in_file = history_lines_read_from_file;
|
|
||||||
/* history_lines_in_file = where_history () + history_base - 1; */
|
|
||||||
|
|
||||||
/* If we're rewriting the history file at shell exit rather than just
|
|
||||||
appending the lines from this session to it, the question is whether
|
|
||||||
we reset history_lines_this_session to 0, losing any history entries
|
|
||||||
we had before we read the new entries from the history file, or
|
|
||||||
whether we count the new entries we just read from the file as
|
|
||||||
history lines added during this session.
|
|
||||||
Right now, we do the latter. This will cause these history entries
|
|
||||||
to be written to the history file along with any intermediate entries
|
|
||||||
we add when we do a `history -a', but the alternative is losing
|
|
||||||
them altogether. */
|
|
||||||
if (force_append_history == 0)
|
|
||||||
history_lines_this_session += history_lines_in_file - old_history_lines +
|
|
||||||
history_base - obase;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (result ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Accessors for HIST_ENTRY lists that are called HLIST. */
|
|
||||||
#define histline(i) (hlist[(i)]->line)
|
|
||||||
#define histdata(i) (hlist[(i)]->data)
|
|
||||||
|
|
||||||
static char *
|
|
||||||
histtime (hlist, histtimefmt)
|
|
||||||
HIST_ENTRY *hlist;
|
|
||||||
const char *histtimefmt;
|
|
||||||
{
|
|
||||||
static char timestr[TIMELEN_MAX];
|
|
||||||
time_t t;
|
|
||||||
struct tm *tm;
|
|
||||||
|
|
||||||
t = history_get_time (hlist);
|
|
||||||
tm = t ? localtime (&t) : 0;
|
|
||||||
if (t && tm)
|
|
||||||
strftime (timestr, sizeof (timestr), histtimefmt, tm);
|
|
||||||
else if (hlist->timestamp && hlist->timestamp[0])
|
|
||||||
snprintf (timestr, sizeof (timestr), _("%s: invalid timestamp"),
|
|
||||||
(hlist->timestamp[0] == '#') ? hlist->timestamp + 1: hlist->timestamp);
|
|
||||||
else
|
|
||||||
strcpy (timestr, "??");
|
|
||||||
return timestr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
display_history (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
intmax_t limit;
|
|
||||||
HIST_ENTRY **hlist;
|
|
||||||
char *histtimefmt, *timestr;
|
|
||||||
|
|
||||||
if (list)
|
|
||||||
{
|
|
||||||
if (get_numeric_arg (list, 0, &limit) == 0)
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
|
|
||||||
if (limit < 0)
|
|
||||||
limit = -limit;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
limit = -1;
|
|
||||||
|
|
||||||
hlist = history_list ();
|
|
||||||
|
|
||||||
if (hlist)
|
|
||||||
{
|
|
||||||
for (i = 0; hlist[i]; i++)
|
|
||||||
;
|
|
||||||
|
|
||||||
if (0 <= limit && limit < i)
|
|
||||||
i -= limit;
|
|
||||||
else
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
histtimefmt = get_string_value ("HISTTIMEFORMAT");
|
|
||||||
|
|
||||||
while (hlist[i])
|
|
||||||
{
|
|
||||||
QUIT;
|
|
||||||
|
|
||||||
timestr = (histtimefmt && *histtimefmt) ? histtime (hlist[i], histtimefmt) : (char *)NULL;
|
|
||||||
printf ("%5d%c %s%s\n", i + history_base,
|
|
||||||
histdata(i) ? '*' : ' ',
|
|
||||||
((timestr && *timestr) ? timestr : ""),
|
|
||||||
histline(i));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the last entry in the history list and add each argument in
|
|
||||||
LIST to the history. */
|
|
||||||
static void
|
|
||||||
push_history (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
/* Delete the last history entry if it was a single entry added to the
|
|
||||||
history list (generally the `history -s' itself), or if `history -s'
|
|
||||||
is being used in a compound command and the compound command was
|
|
||||||
added to the history as a single element (command-oriented history).
|
|
||||||
If you don't want history -s to remove the compound command from the
|
|
||||||
history, change #if 0 to #if 1 below. */
|
|
||||||
#if 0
|
|
||||||
if (remember_on_history && hist_last_line_pushed == 0 &&
|
|
||||||
hist_last_line_added && bash_delete_last_history () == 0)
|
|
||||||
#else
|
|
||||||
if (remember_on_history && hist_last_line_pushed == 0 &&
|
|
||||||
(hist_last_line_added ||
|
|
||||||
(current_command_line_count > 0 && current_command_first_line_saved && command_oriented_history))
|
|
||||||
&& bash_delete_last_history () == 0)
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
|
|
||||||
s = string_list (list);
|
|
||||||
/* Call check_add_history with FORCE set to 1 to skip the check against
|
|
||||||
current_command_line_count. If history -s is used in a compound
|
|
||||||
command, the above code will delete the compound command's history
|
|
||||||
entry and this call will add the line to the history as a separate
|
|
||||||
entry. Without FORCE=1, if current_command_line_count were > 1, the
|
|
||||||
line would be appended to the entry before the just-deleted entry. */
|
|
||||||
check_add_history (s, 1); /* obeys HISTCONTROL, HISTIGNORE */
|
|
||||||
|
|
||||||
hist_last_line_pushed = 1; /* XXX */
|
|
||||||
free (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (BANG_HISTORY)
|
|
||||||
static int
|
|
||||||
expand_and_print_history (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
char *s;
|
|
||||||
int r, result;
|
|
||||||
|
|
||||||
if (hist_last_line_pushed == 0 && hist_last_line_added && bash_delete_last_history () == 0)
|
|
||||||
return EXECUTION_FAILURE;
|
|
||||||
result = EXECUTION_SUCCESS;
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
r = history_expand (list->word->word, &s);
|
|
||||||
if (r < 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: history expansion failed"), list->word->word);
|
|
||||||
result = EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fputs (s, stdout);
|
|
||||||
putchar ('\n');
|
|
||||||
}
|
|
||||||
FREE (s);
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
fflush (stdout);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif /* BANG_HISTORY */
|
|
||||||
#endif /* HISTORY */
|
|
240
third_party/bash/builtins_jobs.c
vendored
240
third_party/bash/builtins_jobs.c
vendored
|
@ -1,240 +0,0 @@
|
||||||
/* jobs.c, created from jobs.def. */
|
|
||||||
#line 22 "./jobs.def"
|
|
||||||
|
|
||||||
#line 48 "./jobs.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
#include "bashtypes.h"
|
|
||||||
#include <signal.h>
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "jobs.h"
|
|
||||||
#include "execute_cmd.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#define JSTATE_ANY 0x0
|
|
||||||
#define JSTATE_RUNNING 0x1
|
|
||||||
#define JSTATE_STOPPED 0x2
|
|
||||||
|
|
||||||
static int execute_list_with_replacements PARAMS((WORD_LIST *));
|
|
||||||
|
|
||||||
/* The `jobs' command. Prints outs a list of active jobs. If the
|
|
||||||
argument `-l' is given, then the process id's are printed also.
|
|
||||||
If the argument `-p' is given, print the process group leader's
|
|
||||||
pid only. If `-n' is given, only processes that have changed
|
|
||||||
status since the last notification are printed. If -x is given,
|
|
||||||
replace all job specs with the pid of the appropriate process
|
|
||||||
group leader and execute the command. The -r and -s options mean
|
|
||||||
to print info about running and stopped jobs only, respectively. */
|
|
||||||
int
|
|
||||||
jobs_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int form, execute, state, opt, any_failed, job;
|
|
||||||
sigset_t set, oset;
|
|
||||||
|
|
||||||
execute = any_failed = 0;
|
|
||||||
form = JLIST_STANDARD;
|
|
||||||
state = JSTATE_ANY;
|
|
||||||
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "lpnxrs")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'l':
|
|
||||||
form = JLIST_LONG;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
form = JLIST_PID_ONLY;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
form = JLIST_CHANGED_ONLY;
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
if (form != JLIST_STANDARD)
|
|
||||||
{
|
|
||||||
builtin_error (_("no other options allowed with `-x'"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
execute++;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
state = JSTATE_RUNNING;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
state = JSTATE_STOPPED;
|
|
||||||
break;
|
|
||||||
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
if (execute)
|
|
||||||
return (execute_list_with_replacements (list));
|
|
||||||
|
|
||||||
if (!list)
|
|
||||||
{
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case JSTATE_ANY:
|
|
||||||
list_all_jobs (form);
|
|
||||||
break;
|
|
||||||
case JSTATE_RUNNING:
|
|
||||||
list_running_jobs (form);
|
|
||||||
break;
|
|
||||||
case JSTATE_STOPPED:
|
|
||||||
list_stopped_jobs (form);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
BLOCK_CHILD (set, oset);
|
|
||||||
job = get_job_spec (list);
|
|
||||||
|
|
||||||
if ((job == NO_JOB) || jobs == 0 || get_job_by_jid (job) == 0)
|
|
||||||
{
|
|
||||||
sh_badjob (list->word->word);
|
|
||||||
any_failed++;
|
|
||||||
}
|
|
||||||
else if (job != DUP_JOB)
|
|
||||||
list_one_job ((JOB *)NULL, form, 0, job);
|
|
||||||
|
|
||||||
UNBLOCK_CHILD (oset);
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
execute_list_with_replacements (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
register WORD_LIST *l;
|
|
||||||
int job, result;
|
|
||||||
COMMAND *command;
|
|
||||||
JOB *j;
|
|
||||||
|
|
||||||
/* First do the replacement of job specifications with pids. */
|
|
||||||
for (l = list; l; l = l->next)
|
|
||||||
{
|
|
||||||
if (l->word->word[0] == '%') /* we have a winner */
|
|
||||||
{
|
|
||||||
job = get_job_spec (l);
|
|
||||||
|
|
||||||
/* A bad job spec is not really a job spec! Pass it through. */
|
|
||||||
if (INVALID_JOB (job))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
j = get_job_by_jid (job);
|
|
||||||
free (l->word->word);
|
|
||||||
l->word->word = itos (j->pgrp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next make a new simple command and execute it. */
|
|
||||||
begin_unwind_frame ("jobs_builtin");
|
|
||||||
|
|
||||||
command = make_bare_simple_command ();
|
|
||||||
command->value.Simple->words = copy_word_list (list);
|
|
||||||
command->value.Simple->redirects = (REDIRECT *)NULL;
|
|
||||||
command->flags |= CMD_INHIBIT_EXPANSION;
|
|
||||||
command->value.Simple->flags |= CMD_INHIBIT_EXPANSION;
|
|
||||||
|
|
||||||
add_unwind_protect (dispose_command, command);
|
|
||||||
result = execute_command (command);
|
|
||||||
dispose_command (command);
|
|
||||||
|
|
||||||
discard_unwind_frame ("jobs_builtin");
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
#endif /* JOB_CONTROL */
|
|
||||||
|
|
||||||
#line 231 "./jobs.def"
|
|
||||||
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
int
|
|
||||||
disown_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int opt, job, retval, nohup_only, running_jobs, all_jobs;
|
|
||||||
sigset_t set, oset;
|
|
||||||
intmax_t pid_value;
|
|
||||||
|
|
||||||
nohup_only = running_jobs = all_jobs = 0;
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "ahr")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'a':
|
|
||||||
all_jobs = 1;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
nohup_only = 1;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
running_jobs = 1;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
retval = EXECUTION_SUCCESS;
|
|
||||||
|
|
||||||
/* `disown -a' or `disown -r' */
|
|
||||||
if (list == 0 && (all_jobs || running_jobs))
|
|
||||||
{
|
|
||||||
if (nohup_only)
|
|
||||||
nohup_all_jobs (running_jobs);
|
|
||||||
else
|
|
||||||
delete_all_jobs (running_jobs);
|
|
||||||
return (EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
BLOCK_CHILD (set, oset);
|
|
||||||
job = (list && legal_number (list->word->word, &pid_value) && pid_value == (pid_t) pid_value)
|
|
||||||
? get_job_by_pid ((pid_t) pid_value, 0, 0)
|
|
||||||
: get_job_spec (list);
|
|
||||||
|
|
||||||
if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
|
|
||||||
{
|
|
||||||
sh_badjob (list ? list->word->word : _("current"));
|
|
||||||
retval = EXECUTION_FAILURE;
|
|
||||||
}
|
|
||||||
else if (nohup_only)
|
|
||||||
nohup_job (job);
|
|
||||||
else
|
|
||||||
delete_job (job, 1);
|
|
||||||
UNBLOCK_CHILD (oset);
|
|
||||||
|
|
||||||
if (list)
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
while (list);
|
|
||||||
|
|
||||||
return (retval);
|
|
||||||
}
|
|
||||||
#endif /* JOB_CONTROL */
|
|
235
third_party/bash/builtins_kill.c
vendored
235
third_party/bash/builtins_kill.c
vendored
|
@ -1,235 +0,0 @@
|
||||||
/* kill.c, created from kill.def. */
|
|
||||||
#line 22 "./kill.def"
|
|
||||||
|
|
||||||
#line 46 "./kill.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "trap.h"
|
|
||||||
#include "jobs.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
|
|
||||||
#if !defined (errno)
|
|
||||||
extern int errno;
|
|
||||||
#endif /* !errno */
|
|
||||||
|
|
||||||
static void kill_error PARAMS((pid_t, int));
|
|
||||||
|
|
||||||
#if !defined (CONTINUE_AFTER_KILL_ERROR)
|
|
||||||
# define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
|
|
||||||
#else
|
|
||||||
# define CONTINUE_OR_FAIL goto continue_killing
|
|
||||||
#endif /* CONTINUE_AFTER_KILL_ERROR */
|
|
||||||
|
|
||||||
/* Here is the kill builtin. We only have it so that people can type
|
|
||||||
kill -KILL %1? No, if you fill up the process table this way you
|
|
||||||
can still kill some. */
|
|
||||||
int
|
|
||||||
kill_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int sig, any_succeeded, listing, saw_signal, dflags;
|
|
||||||
char *sigspec, *word;
|
|
||||||
pid_t pid;
|
|
||||||
intmax_t pid_value;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
{
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
any_succeeded = listing = saw_signal = 0;
|
|
||||||
sig = SIGTERM;
|
|
||||||
sigspec = "TERM";
|
|
||||||
|
|
||||||
dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0);
|
|
||||||
/* Process options. */
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
word = list->word->word;
|
|
||||||
|
|
||||||
if (ISOPTION (word, 'l') || ISOPTION (word, 'L'))
|
|
||||||
{
|
|
||||||
listing++;
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
else if (ISOPTION (word, 's') || ISOPTION (word, 'n'))
|
|
||||||
{
|
|
||||||
list = list->next;
|
|
||||||
if (list)
|
|
||||||
{
|
|
||||||
sigspec = list->word->word;
|
|
||||||
use_sigspec:
|
|
||||||
if (sigspec[0] == '0' && sigspec[1] == '\0')
|
|
||||||
sig = 0;
|
|
||||||
else
|
|
||||||
sig = decode_signal (sigspec, dflags);
|
|
||||||
list = list->next;
|
|
||||||
saw_signal++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_needarg (word);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (word[0] == '-' && word[1] == 's' && ISALPHA (word[2]))
|
|
||||||
{
|
|
||||||
sigspec = word + 2;
|
|
||||||
goto use_sigspec;
|
|
||||||
}
|
|
||||||
else if (word[0] == '-' && word[1] == 'n' && ISDIGIT (word[2]))
|
|
||||||
{
|
|
||||||
sigspec = word + 2;
|
|
||||||
goto use_sigspec;
|
|
||||||
}
|
|
||||||
else if (ISOPTION (word, '-'))
|
|
||||||
{
|
|
||||||
list = list->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (ISOPTION (word, '?'))
|
|
||||||
{
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
/* If this is a signal specification then process it. We only process
|
|
||||||
the first one seen; other arguments may signify process groups (e.g,
|
|
||||||
-num == process group num). */
|
|
||||||
else if (*word == '-' && saw_signal == 0)
|
|
||||||
{
|
|
||||||
sigspec = word + 1;
|
|
||||||
sig = decode_signal (sigspec, dflags);
|
|
||||||
saw_signal++;
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listing)
|
|
||||||
return (display_signal_list (list, 0));
|
|
||||||
|
|
||||||
/* OK, we are killing processes. */
|
|
||||||
if (sig == NO_SIG)
|
|
||||||
{
|
|
||||||
sh_invalidsig (sigspec);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
{
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
word = list->word->word;
|
|
||||||
|
|
||||||
if (*word == '-')
|
|
||||||
word++;
|
|
||||||
|
|
||||||
/* Use the entire argument in case of minus sign presence. */
|
|
||||||
if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
|
|
||||||
{
|
|
||||||
pid = (pid_t) pid_value;
|
|
||||||
|
|
||||||
if (kill_pid (pid, sig, pid < -1) < 0)
|
|
||||||
{
|
|
||||||
if (errno == EINVAL)
|
|
||||||
sh_invalidsig (sigspec);
|
|
||||||
else
|
|
||||||
kill_error (pid, errno);
|
|
||||||
CONTINUE_OR_FAIL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
any_succeeded++;
|
|
||||||
}
|
|
||||||
#if defined (JOB_CONTROL)
|
|
||||||
else if (*list->word->word && *list->word->word != '%')
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: arguments must be process or job IDs"), list->word->word);
|
|
||||||
CONTINUE_OR_FAIL;
|
|
||||||
}
|
|
||||||
else if (*word)
|
|
||||||
/* Posix.2 says you can kill without job control active (4.32.4) */
|
|
||||||
{ /* Must be a job spec. Check it out. */
|
|
||||||
int job;
|
|
||||||
sigset_t set, oset;
|
|
||||||
JOB *j;
|
|
||||||
|
|
||||||
BLOCK_CHILD (set, oset);
|
|
||||||
job = get_job_spec (list);
|
|
||||||
|
|
||||||
if (INVALID_JOB (job))
|
|
||||||
{
|
|
||||||
if (job != DUP_JOB)
|
|
||||||
sh_badjob (list->word->word);
|
|
||||||
UNBLOCK_CHILD (oset);
|
|
||||||
CONTINUE_OR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
j = get_job_by_jid (job);
|
|
||||||
/* Job spec used. Kill the process group. If the job was started
|
|
||||||
without job control, then its pgrp == shell_pgrp, so we have
|
|
||||||
to be careful. We take the pid of the first job in the pipeline
|
|
||||||
in that case. */
|
|
||||||
pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid;
|
|
||||||
|
|
||||||
UNBLOCK_CHILD (oset);
|
|
||||||
|
|
||||||
if (kill_pid (pid, sig, 1) < 0)
|
|
||||||
{
|
|
||||||
if (errno == EINVAL)
|
|
||||||
sh_invalidsig (sigspec);
|
|
||||||
else
|
|
||||||
kill_error (pid, errno);
|
|
||||||
CONTINUE_OR_FAIL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
any_succeeded++;
|
|
||||||
}
|
|
||||||
#endif /* !JOB_CONTROL */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sh_badpid (list->word->word);
|
|
||||||
CONTINUE_OR_FAIL;
|
|
||||||
}
|
|
||||||
continue_killing:
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
kill_error (pid, e)
|
|
||||||
pid_t pid;
|
|
||||||
int e;
|
|
||||||
{
|
|
||||||
char *x;
|
|
||||||
|
|
||||||
x = strerror (e);
|
|
||||||
if (x == 0)
|
|
||||||
x = _("Unknown error");
|
|
||||||
builtin_error ("(%ld) - %s", (long)pid, x);
|
|
||||||
}
|
|
68
third_party/bash/builtins_let.c
vendored
68
third_party/bash/builtins_let.c
vendored
|
@ -1,68 +0,0 @@
|
||||||
/* let.c, created from let.def. */
|
|
||||||
#line 66 "./let.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# ifdef _MINIX
|
|
||||||
# include <sys/types.h>
|
|
||||||
# endif
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
/* Arithmetic LET function. */
|
|
||||||
int
|
|
||||||
let_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
intmax_t ret;
|
|
||||||
int expok;
|
|
||||||
|
|
||||||
CHECK_HELPOPT (list);
|
|
||||||
|
|
||||||
/* Skip over leading `--' argument. */
|
|
||||||
if (list && list->word && ISOPTION (list->word->word, '-'))
|
|
||||||
list = list->next;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("expression expected"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; list; list = list->next)
|
|
||||||
{
|
|
||||||
ret = evalexp (list->word->word, EXP_EXPANDED, &expok);
|
|
||||||
if (expok == 0)
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((ret == 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef INCLUDE_UNUSED
|
|
||||||
int
|
|
||||||
exp_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
char *exp;
|
|
||||||
intmax_t ret;
|
|
||||||
int expok;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("expression expected"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
exp = string_list (list);
|
|
||||||
ret = evalexp (exp, EXP_EXPANDED, &expok);
|
|
||||||
(void)free (exp);
|
|
||||||
return (((ret == 0) || (expok == 0)) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
|
||||||
}
|
|
||||||
#endif
|
|
304
third_party/bash/builtins_mapfile.c
vendored
304
third_party/bash/builtins_mapfile.c
vendored
|
@ -1,304 +0,0 @@
|
||||||
/* mapfile.c, created from mapfile.def. */
|
|
||||||
#line 23 "./mapfile.def"
|
|
||||||
|
|
||||||
#line 59 "./mapfile.def"
|
|
||||||
|
|
||||||
#line 67 "./mapfile.def"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "builtins.h"
|
|
||||||
#include "bashtypes.h"
|
|
||||||
#include "posixstat.h"
|
|
||||||
|
|
||||||
#if defined (HAVE_UNISTD_H)
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "bashansi.h"
|
|
||||||
#include "bashintl.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "bashintl.h"
|
|
||||||
#include "shell.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "bashgetopt.h"
|
|
||||||
|
|
||||||
#if !defined (errno)
|
|
||||||
extern int errno;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (ARRAY_VARS)
|
|
||||||
|
|
||||||
static int run_callback PARAMS((const char *, unsigned int, const char *));
|
|
||||||
|
|
||||||
#define DEFAULT_ARRAY_NAME "MAPFILE"
|
|
||||||
#define DEFAULT_VARIABLE_NAME "MAPLINE" /* not used right now */
|
|
||||||
|
|
||||||
/* The value specifying how frequently `mapfile' calls the callback. */
|
|
||||||
#define DEFAULT_QUANTUM 5000
|
|
||||||
|
|
||||||
/* Values for FLAGS */
|
|
||||||
#define MAPF_CLEARARRAY 0x01
|
|
||||||
#define MAPF_CHOP 0x02
|
|
||||||
|
|
||||||
static int delim;
|
|
||||||
|
|
||||||
static int
|
|
||||||
run_callback (callback, curindex, curline)
|
|
||||||
const char *callback;
|
|
||||||
unsigned int curindex;
|
|
||||||
const char *curline;
|
|
||||||
{
|
|
||||||
unsigned int execlen;
|
|
||||||
char *execstr, *qline;
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
qline = sh_single_quote (curline);
|
|
||||||
execlen = strlen (callback) + strlen (qline) + 10;
|
|
||||||
/* 1 for each space between %s and %d,
|
|
||||||
another 1 for the last nul char for C string. */
|
|
||||||
execlen += 3;
|
|
||||||
execstr = xmalloc (execlen);
|
|
||||||
|
|
||||||
flags = SEVAL_NOHIST;
|
|
||||||
#if 0
|
|
||||||
if (interactive)
|
|
||||||
flags |= SEVAL_INTERACT;
|
|
||||||
#endif
|
|
||||||
snprintf (execstr, execlen, "%s %d %s", callback, curindex, qline);
|
|
||||||
free (qline);
|
|
||||||
return evalstring (execstr, NULL, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
do_chop(line, delim)
|
|
||||||
char *line;
|
|
||||||
unsigned char delim;
|
|
||||||
{
|
|
||||||
int length;
|
|
||||||
|
|
||||||
length = strlen (line);
|
|
||||||
if (length && (unsigned char)line[length-1] == delim)
|
|
||||||
line[length-1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_name, delim, flags)
|
|
||||||
int fd;
|
|
||||||
long line_count_goal, origin, nskip, callback_quantum;
|
|
||||||
char *callback, *array_name;
|
|
||||||
int delim;
|
|
||||||
int flags;
|
|
||||||
{
|
|
||||||
char *line;
|
|
||||||
size_t line_length;
|
|
||||||
unsigned int array_index, line_count;
|
|
||||||
SHELL_VAR *entry;
|
|
||||||
struct stat sb;
|
|
||||||
int unbuffered_read;
|
|
||||||
|
|
||||||
line = NULL;
|
|
||||||
line_length = 0;
|
|
||||||
unbuffered_read = 0;
|
|
||||||
|
|
||||||
/* The following check should be done before reading any lines. Doing it
|
|
||||||
here allows us to call bind_array_element instead of bind_array_variable
|
|
||||||
and skip the variable lookup on every call. */
|
|
||||||
entry = builtin_find_indexed_array (array_name, flags & MAPF_CLEARARRAY);
|
|
||||||
if (entry == 0)
|
|
||||||
return EXECUTION_FAILURE;
|
|
||||||
|
|
||||||
#ifndef __CYGWIN__
|
|
||||||
/* If the delimiter is a newline, turn on unbuffered reads for pipes
|
|
||||||
(terminals are ok). If the delimiter is not a newline, unbuffered reads
|
|
||||||
for every file descriptor that's not a regular file. */
|
|
||||||
if (delim == '\n')
|
|
||||||
unbuffered_read = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
|
|
||||||
else
|
|
||||||
unbuffered_read = (fstat (fd, &sb) != 0) || (S_ISREG (sb.st_mode) == 0);
|
|
||||||
#else
|
|
||||||
unbuffered_read = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
zreset ();
|
|
||||||
|
|
||||||
/* Skip any lines at beginning of file? */
|
|
||||||
for (line_count = 0; line_count < nskip; line_count++)
|
|
||||||
if (zgetline (fd, &line, &line_length, delim, unbuffered_read) < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
line = 0;
|
|
||||||
line_length = 0;
|
|
||||||
|
|
||||||
/* Reset the buffer for bash own stream */
|
|
||||||
for (array_index = origin, line_count = 1;
|
|
||||||
zgetline (fd, &line, &line_length, delim, unbuffered_read) != -1;
|
|
||||||
array_index++)
|
|
||||||
{
|
|
||||||
/* Remove trailing newlines? */
|
|
||||||
if (flags & MAPF_CHOP)
|
|
||||||
do_chop (line, delim);
|
|
||||||
|
|
||||||
/* Has a callback been registered and if so is it time to call it? */
|
|
||||||
if (callback && line_count && (line_count % callback_quantum) == 0)
|
|
||||||
{
|
|
||||||
/* Reset the buffer for bash own stream. */
|
|
||||||
if (unbuffered_read == 0)
|
|
||||||
zsyncfd (fd);
|
|
||||||
|
|
||||||
run_callback (callback, array_index, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX - bad things can happen if the callback modifies ENTRY, e.g.,
|
|
||||||
unsetting it or changing it to a non-indexed-array type. */
|
|
||||||
bind_array_element (entry, array_index, line, 0);
|
|
||||||
|
|
||||||
/* Have we exceeded # of lines to store? */
|
|
||||||
line_count++;
|
|
||||||
if (line_count_goal != 0 && line_count > line_count_goal)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
free (line);
|
|
||||||
|
|
||||||
if (unbuffered_read == 0)
|
|
||||||
zsyncfd (fd);
|
|
||||||
|
|
||||||
return EXECUTION_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
mapfile_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
int opt, code, fd, flags;
|
|
||||||
intmax_t intval;
|
|
||||||
long lines, origin, nskip, callback_quantum;
|
|
||||||
char *array_name, *callback;
|
|
||||||
|
|
||||||
fd = 0;
|
|
||||||
lines = origin = nskip = 0;
|
|
||||||
flags = MAPF_CLEARARRAY;
|
|
||||||
callback_quantum = DEFAULT_QUANTUM;
|
|
||||||
callback = 0;
|
|
||||||
delim = '\n';
|
|
||||||
|
|
||||||
reset_internal_getopt ();
|
|
||||||
while ((opt = internal_getopt (list, "d:u:n:O:tC:c:s:")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'd':
|
|
||||||
delim = *list_optarg;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
code = legal_number (list_optarg, &intval);
|
|
||||||
if (code == 0 || intval < 0 || intval != (int)intval)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fd = intval;
|
|
||||||
|
|
||||||
if (sh_validfd (fd) == 0)
|
|
||||||
{
|
|
||||||
builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
code = legal_number (list_optarg, &intval);
|
|
||||||
if (code == 0 || intval < 0 || intval != (unsigned)intval)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: invalid line count"), list_optarg);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lines = intval;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'O':
|
|
||||||
code = legal_number (list_optarg, &intval);
|
|
||||||
if (code == 0 || intval < 0 || intval != (unsigned)intval)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: invalid array origin"), list_optarg);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
origin = intval;
|
|
||||||
flags &= ~MAPF_CLEARARRAY;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
flags |= MAPF_CHOP;
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
callback = list_optarg;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
code = legal_number (list_optarg, &intval);
|
|
||||||
if (code == 0 || intval <= 0 || intval != (unsigned)intval)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: invalid callback quantum"), list_optarg);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
callback_quantum = intval;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
code = legal_number (list_optarg, &intval);
|
|
||||||
if (code == 0 || intval < 0 || intval != (unsigned)intval)
|
|
||||||
{
|
|
||||||
builtin_error (_("%s: invalid line count"), list_optarg);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
nskip = intval;
|
|
||||||
break;
|
|
||||||
CASE_HELPOPT;
|
|
||||||
default:
|
|
||||||
builtin_usage ();
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = loptend;
|
|
||||||
|
|
||||||
if (list == 0)
|
|
||||||
array_name = DEFAULT_ARRAY_NAME;
|
|
||||||
else if (list->word == 0 || list->word->word == 0)
|
|
||||||
{
|
|
||||||
builtin_error ("internal error: getting variable name");
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
else if (list->word->word[0] == '\0')
|
|
||||||
{
|
|
||||||
builtin_error (_("empty array variable name"));
|
|
||||||
return (EX_USAGE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
array_name = list->word->word;
|
|
||||||
|
|
||||||
if (legal_identifier (array_name) == 0)
|
|
||||||
{
|
|
||||||
sh_invalidid (array_name);
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapfile (fd, lines, origin, nskip, callback_quantum, callback, array_name, delim, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
int
|
|
||||||
mapfile_builtin (list)
|
|
||||||
WORD_LIST *list;
|
|
||||||
{
|
|
||||||
builtin_error (_("array variable support required"));
|
|
||||||
return (EXECUTION_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ARRAY_VARS */
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue