libdash 0.3__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- libdash-0.4.0/PKG-INFO +145 -0
- {libdash-0.3 → libdash-0.4.0}/README.md +12 -0
- {libdash-0.3 → libdash-0.4.0}/configure.ac +50 -7
- {libdash-0.3 → libdash-0.4.0}/libdash/parser.py +5 -4
- {libdash-0.3 → libdash-0.4.0}/libdash/printer.py +27 -20
- libdash-0.4.0/libdash.egg-info/PKG-INFO +145 -0
- {libdash-0.3 → libdash-0.4.0}/libdash.egg-info/SOURCES.txt +1 -0
- {libdash-0.3 → libdash-0.4.0}/pyproject.toml +6 -5
- {libdash-0.3 → libdash-0.4.0}/setup.py +26 -5
- {libdash-0.3 → libdash-0.4.0}/src/alias.c +22 -27
- {libdash-0.3 → libdash-0.4.0}/src/arith_yacc.c +2 -2
- {libdash-0.3 → libdash-0.4.0}/src/bltin/echo.1 +4 -2
- {libdash-0.3 → libdash-0.4.0}/src/bltin/printf.1 +7 -6
- {libdash-0.3 → libdash-0.4.0}/src/bltin/printf.c +141 -38
- {libdash-0.3 → libdash-0.4.0}/src/bltin/test.1 +1 -1
- {libdash-0.3 → libdash-0.4.0}/src/bltin/test.c +38 -36
- {libdash-0.3 → libdash-0.4.0}/src/bltin/times.c +1 -1
- {libdash-0.3 → libdash-0.4.0}/src/cd.c +1 -1
- {libdash-0.3 → libdash-0.4.0}/src/dash.1 +166 -73
- {libdash-0.3 → libdash-0.4.0}/src/error.h +0 -4
- {libdash-0.3 → libdash-0.4.0}/src/eval.c +52 -22
- {libdash-0.3 → libdash-0.4.0}/src/exec.c +34 -31
- {libdash-0.3 → libdash-0.4.0}/src/exec.h +5 -0
- {libdash-0.3 → libdash-0.4.0}/src/expand.c +927 -457
- {libdash-0.3 → libdash-0.4.0}/src/expand.h +5 -0
- {libdash-0.3 → libdash-0.4.0}/src/histedit.c +17 -15
- {libdash-0.3 → libdash-0.4.0}/src/init.h +4 -1
- {libdash-0.3 → libdash-0.4.0}/src/input.c +341 -151
- {libdash-0.3 → libdash-0.4.0}/src/input.h +44 -7
- {libdash-0.3 → libdash-0.4.0}/src/jobs.c +100 -49
- {libdash-0.3 → libdash-0.4.0}/src/jobs.h +2 -1
- {libdash-0.3 → libdash-0.4.0}/src/mail.c +1 -1
- {libdash-0.3 → libdash-0.4.0}/src/main.c +11 -5
- {libdash-0.3 → libdash-0.4.0}/src/main.h +2 -0
- {libdash-0.3 → libdash-0.4.0}/src/memalloc.c +37 -34
- {libdash-0.3 → libdash-0.4.0}/src/memalloc.h +10 -10
- {libdash-0.3 → libdash-0.4.0}/src/miscbltin.c +41 -28
- {libdash-0.3 → libdash-0.4.0}/src/mkinit.c +9 -2
- {libdash-0.3 → libdash-0.4.0}/src/mksignames.c +1 -3
- {libdash-0.3 → libdash-0.4.0}/src/mksyntax.c +8 -12
- {libdash-0.3 → libdash-0.4.0}/src/mktokens +1 -1
- {libdash-0.3 → libdash-0.4.0}/src/myhistedit.h +18 -0
- {libdash-0.3 → libdash-0.4.0}/src/mystring.c +6 -5
- {libdash-0.3 → libdash-0.4.0}/src/mystring.h +15 -1
- {libdash-0.3 → libdash-0.4.0}/src/nodes.c.pat +5 -15
- {libdash-0.3 → libdash-0.4.0}/src/options.c +18 -16
- {libdash-0.3 → libdash-0.4.0}/src/options.h +4 -3
- {libdash-0.3 → libdash-0.4.0}/src/parser.c +312 -141
- {libdash-0.3 → libdash-0.4.0}/src/parser.h +6 -0
- {libdash-0.3 → libdash-0.4.0}/src/redir.c +229 -180
- {libdash-0.3 → libdash-0.4.0}/src/redir.h +2 -1
- {libdash-0.3 → libdash-0.4.0}/src/system.h +75 -0
- {libdash-0.3 → libdash-0.4.0}/src/trap.c +50 -19
- libdash-0.4.0/src/type_description.ml +184 -0
- {libdash-0.3 → libdash-0.4.0}/src/var.c +40 -42
- {libdash-0.3 → libdash-0.4.0}/src/var.h +16 -1
- libdash-0.3/PKG-INFO +0 -70
- libdash-0.3/libdash.egg-info/PKG-INFO +0 -70
- {libdash-0.3 → libdash-0.4.0}/COPYING +0 -0
- {libdash-0.3 → libdash-0.4.0}/MANIFEST.in +0 -0
- {libdash-0.3 → libdash-0.4.0}/Makefile.am +0 -0
- {libdash-0.3 → libdash-0.4.0}/autogen.sh +0 -0
- {libdash-0.3 → libdash-0.4.0}/libdash/__init__.py +0 -0
- {libdash-0.3 → libdash-0.4.0}/libdash/_dash.py +0 -0
- {libdash-0.3 → libdash-0.4.0}/libdash/ast.py +0 -0
- {libdash-0.3 → libdash-0.4.0}/libdash.egg-info/dependency_links.txt +0 -0
- {libdash-0.3 → libdash-0.4.0}/libdash.egg-info/top_level.txt +0 -0
- {libdash-0.3 → libdash-0.4.0}/setup.cfg +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/Makefile.am +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/TOUR +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/alias.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/arith_yacc.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/arith_yylex.c +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/bltin/bltin.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/builtins.def.in +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/cd.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/error.c +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/eval.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/funcs/cmv +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/funcs/dirs +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/funcs/kill +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/funcs/login +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/funcs/newgrp +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/funcs/popd +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/funcs/pushd +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/funcs/suspend +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/machdep.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/mail.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/miscbltin.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/mkbuiltins +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/mknodes.c +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/nodetypes +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/output.c +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/output.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/shell.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/show.c +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/show.h +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/system.c +0 -0
- {libdash-0.3 → libdash-0.4.0}/src/trap.h +0 -0
libdash-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: libdash
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Bindings for the dash shell as a library
|
|
5
|
+
Author: PaSh contributors
|
|
6
|
+
Author-email: Michael Greenberg <michael@greenberg.science>
|
|
7
|
+
License: Copyright (c) 1989-1994
|
|
8
|
+
The Regents of the University of California. All rights reserved.
|
|
9
|
+
Copyright (c) 1997 Christos Zoulas. All rights reserved.
|
|
10
|
+
Copyright (c) 1997-2005
|
|
11
|
+
Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
|
|
12
|
+
|
|
13
|
+
This code is derived from software contributed to Berkeley by Kenneth Almquist.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Redistribution and use in source and binary forms, with or without
|
|
17
|
+
modification, are permitted provided that the following conditions
|
|
18
|
+
are met:
|
|
19
|
+
1. Redistributions of source code must retain the above copyright
|
|
20
|
+
notice, this list of conditions and the following disclaimer.
|
|
21
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
22
|
+
notice, this list of conditions and the following disclaimer in the
|
|
23
|
+
documentation and/or other materials provided with the distribution.
|
|
24
|
+
3. Neither the name of the University nor the names of its contributors
|
|
25
|
+
may be used to endorse or promote products derived from this software
|
|
26
|
+
without specific prior written permission.
|
|
27
|
+
|
|
28
|
+
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
29
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
30
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
31
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
32
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
33
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
34
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
35
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
36
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
37
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
38
|
+
SUCH DAMAGE.
|
|
39
|
+
|
|
40
|
+
mksignames.c:
|
|
41
|
+
|
|
42
|
+
This file is not directly linked with dash. However, its output is.
|
|
43
|
+
|
|
44
|
+
Copyright (C) 1992 Free Software Foundation, Inc.
|
|
45
|
+
|
|
46
|
+
This file is part of GNU Bash, the Bourne Again SHell.
|
|
47
|
+
|
|
48
|
+
Bash is free software; you can redistribute it and/or modify it under
|
|
49
|
+
the terms of the GNU General Public License as published by the Free
|
|
50
|
+
Software Foundation; either version 2, or (at your option) any later
|
|
51
|
+
version.
|
|
52
|
+
|
|
53
|
+
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
54
|
+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
55
|
+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
56
|
+
for more details.
|
|
57
|
+
|
|
58
|
+
You should have received a copy of the GNU General Public License with
|
|
59
|
+
your Debian GNU/Linux system, in /usr/share/common-licenses/GPL, or with the
|
|
60
|
+
Debian GNU/Linux hello source package as the file COPYING. If not,
|
|
61
|
+
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
62
|
+
Boston, MA 02111 USA.
|
|
63
|
+
|
|
64
|
+
Project-URL: Homepage, https://github.com/binpash/libdash
|
|
65
|
+
Project-URL: Bug Tracker, https://github.com/binpash/libdash/issues
|
|
66
|
+
Classifier: Programming Language :: Python :: 3
|
|
67
|
+
Classifier: Topic :: System :: System Shells
|
|
68
|
+
Classifier: Operating System :: POSIX
|
|
69
|
+
Requires-Python: >=3.7
|
|
70
|
+
Description-Content-Type: text/markdown
|
|
71
|
+
License-File: COPYING
|
|
72
|
+
|
|
73
|
+
[](https://github.com/mgree/libdash/actions/workflows/build.yml)
|
|
74
|
+
|
|
75
|
+
*libdash* is a fork of the Linux Kernel's `dash` shell that builds a linkable library with extra exposed interfaces. The primary use of libdash is to parse shell scripts, but it could be used for more.
|
|
76
|
+
|
|
77
|
+
The Python bindings are packaged as the [`libdash` PyPi package](https://pypi.org/project/libdash/).
|
|
78
|
+
|
|
79
|
+
The OCaml bindings---packaged as the [`libdash` OPAM package](https://opam.ocaml.org/packages/libdash/)---include two executables, `shell_to_json` and `json_to_shell`, which let you conveniently parse POSIX shell scripts into a JSON AST.
|
|
80
|
+
|
|
81
|
+
# What are the dependencies?
|
|
82
|
+
|
|
83
|
+
The C code for dash should build on a wide variety of systems; it requires `libtool` and `autotools` (`aclocal`, `autoheader`, `automake`, `autoconf`). The library may not build on platforms with esoteric linkers; it's been tested on macOS and Linux.
|
|
84
|
+
|
|
85
|
+
The Python and OCaml bindings depend on being able to build the C code. See `libdash.opam` for details on the OCaml code's dependencies, which includes the build-time external dependencies. Python wheels have no need for these build-time dependencies, but building from a Python source distribution will only succeed when `libtool` and `autotools` are present.
|
|
86
|
+
|
|
87
|
+
The CI scripts (in `.github/workflows/build.yml`) give build details.
|
|
88
|
+
|
|
89
|
+
## How to build `libdash` from source
|
|
90
|
+
|
|
91
|
+
### Python
|
|
92
|
+
|
|
93
|
+
Run `python3 setup.py install`. On macOS, you must first install the build dependencies via `brew install libtool autoconf automake`.
|
|
94
|
+
|
|
95
|
+
You can test the Python bindings by running:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
cd python; make test
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### OCaml
|
|
102
|
+
|
|
103
|
+
Install the OPAM file: `opam pin add .` or `opam install .`. This will build the OCaml library and install it in your OPAM repository. There are tests in another directory; they will only build when libdash is actually installed.
|
|
104
|
+
|
|
105
|
+
You can test the OCaml bindings by running:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
cd ocaml; make test
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Testing
|
|
112
|
+
|
|
113
|
+
The tests use `test/round_trip.sh` to ensure that every tester file in `test/tests` round-trips correctly through parsing and pretty printing.
|
|
114
|
+
|
|
115
|
+
Additionally, you can run tests that compare the OCaml and Python implementations (after you've installed them both):
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
cd test; make
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
# How to use the parser
|
|
122
|
+
|
|
123
|
+
For Python, see [`python/rt.py`](https://github.com/mgree/libdash/blob/master/python/rt.py), an example tool that does a round-trip: shell syntax to AST back to shell syntax.
|
|
124
|
+
|
|
125
|
+
For OCaml, see [`ocaml/shell_to_json.ml`](https://github.com/mgree/libdash/blob/master/ocaml/shell_to_json.ml), a tool that parses shell syntax and produces JSON (using the [atdgen](https://opam.ocaml.org/packages/atdgen/) bindings).
|
|
126
|
+
|
|
127
|
+
The ideal low-level interface to use is `parsecmd_safe` in `parser.c`; you'll need to ensure that dash's initialization routines have been called and that the stack marks are managed correctly. Parsing the POSIX shell is a complicated affair: beyond the usual locale issues, aliases affect the lexer, so one must use `setalias` and `unalias` to manage any aliases that ought to exist.
|
|
128
|
+
|
|
129
|
+
# How work with the parsed nodes
|
|
130
|
+
|
|
131
|
+
The general AST is described in `nodes.h`. There are some tricky invariants around the precise formatting of control codes; the OCaml code shows some examples of working with the `args` fields in `ocaml/ast.ml`, which converts the C AST to an OCaml AST.
|
|
132
|
+
|
|
133
|
+
The OCaml tools `shell_to_json` and `json_to_shell` will produce JSON ASTs, allowing you to work with these ASTs in any language.
|
|
134
|
+
|
|
135
|
+
# Pretty printing
|
|
136
|
+
|
|
137
|
+
The pretty printer does its best to produce valid shell scripts, but it's possible to manually construct AST nodes that don't directly correspond to valid scripts.
|
|
138
|
+
|
|
139
|
+
For example, the Python AST `[[['Q', [['C', 34]]]]]` represents a quoted field containing a double quote character. Translated literally, this would yield the string `"""`, which is not a valid shell script. The pretty printer will instead automatically escape the inner quote, rendering `"\""`.
|
|
140
|
+
|
|
141
|
+
While the printer tries to get things right either way, you should use escapes to signal to the printer when to escape: you should use the Python AST `[[['Q', [['E', 34]]]]]` to mark the inner double quote as escaped.
|
|
142
|
+
|
|
143
|
+
# Known issues
|
|
144
|
+
|
|
145
|
+
We currently do not escape the character `!` (exclamation point). In an interactive shell, `!` is likely treated as a history substitution (and so should be escaped), but in a non-interactive shell, `!` is treated normally. We currently cater to non-interactive shells; eventually this behavior will be controllable.
|
|
@@ -59,3 +59,15 @@ The ideal low-level interface to use is `parsecmd_safe` in `parser.c`; you'll ne
|
|
|
59
59
|
The general AST is described in `nodes.h`. There are some tricky invariants around the precise formatting of control codes; the OCaml code shows some examples of working with the `args` fields in `ocaml/ast.ml`, which converts the C AST to an OCaml AST.
|
|
60
60
|
|
|
61
61
|
The OCaml tools `shell_to_json` and `json_to_shell` will produce JSON ASTs, allowing you to work with these ASTs in any language.
|
|
62
|
+
|
|
63
|
+
# Pretty printing
|
|
64
|
+
|
|
65
|
+
The pretty printer does its best to produce valid shell scripts, but it's possible to manually construct AST nodes that don't directly correspond to valid scripts.
|
|
66
|
+
|
|
67
|
+
For example, the Python AST `[[['Q', [['C', 34]]]]]` represents a quoted field containing a double quote character. Translated literally, this would yield the string `"""`, which is not a valid shell script. The pretty printer will instead automatically escape the inner quote, rendering `"\""`.
|
|
68
|
+
|
|
69
|
+
While the printer tries to get things right either way, you should use escapes to signal to the printer when to escape: you should use the Python AST `[[['Q', [['E', 34]]]]]` to mark the inner double quote as escaped.
|
|
70
|
+
|
|
71
|
+
# Known issues
|
|
72
|
+
|
|
73
|
+
We currently do not escape the character `!` (exclamation point). In an interactive shell, `!` is likely treated as a history substitution (and so should be escaped), but in a non-interactive shell, `!` is treated normally. We currently cater to non-interactive shells; eventually this behavior will be controllable.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
AC_INIT([dash],[0.5.
|
|
1
|
+
AC_INIT([dash],[0.5.13.3])
|
|
2
2
|
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
|
3
3
|
AC_CONFIG_SRCDIR([src/main.c])
|
|
4
4
|
AC_CONFIG_HEADERS(config.h)
|
|
@@ -10,10 +10,12 @@ dnl Checks for programs.
|
|
|
10
10
|
AC_PROG_CC
|
|
11
11
|
AC_USE_SYSTEM_EXTENSIONS
|
|
12
12
|
|
|
13
|
+
dnl AC_GNU_SOURCE
|
|
13
14
|
AC_PROG_YACC
|
|
14
15
|
dnl MMG 2018-09-26 support building the library
|
|
15
16
|
AM_PROG_AR
|
|
16
17
|
|
|
18
|
+
|
|
17
19
|
AC_MSG_CHECKING([for build system compiler])
|
|
18
20
|
if test "$cross_compiling" = yes; then
|
|
19
21
|
CC_FOR_BUILD=${CC_FOR_BUILD-cc}
|
|
@@ -38,17 +40,20 @@ fi
|
|
|
38
40
|
AC_ARG_ENABLE(static, AS_HELP_STRING(--enable-static, \
|
|
39
41
|
[Build statical linked program]))
|
|
40
42
|
if test "$enable_static" = "yes"; then
|
|
41
|
-
export LDFLAGS="-static
|
|
43
|
+
export LDFLAGS="-static"
|
|
42
44
|
fi
|
|
43
45
|
|
|
44
46
|
AC_ARG_ENABLE(fnmatch, AS_HELP_STRING(--enable-fnmatch, \
|
|
45
47
|
[Use fnmatch(3) from libc]))
|
|
46
48
|
AC_ARG_ENABLE(glob, AS_HELP_STRING(--enable-glob, [Use glob(3) from libc]))
|
|
49
|
+
AC_ARG_ENABLE(tee, AS_HELP_STRING(--disable-tee, [Do not use tee(2)]))
|
|
50
|
+
AC_ARG_ENABLE(memfd_create, AS_HELP_STRING(--disable-memfd-create,
|
|
51
|
+
[Do not use memfd_create(3)]))
|
|
47
52
|
|
|
48
53
|
dnl Checks for libraries.
|
|
49
54
|
|
|
50
55
|
dnl Checks for header files.
|
|
51
|
-
AC_CHECK_HEADERS(alloca.h paths.h)
|
|
56
|
+
AC_CHECK_HEADERS(alloca.h paths.h sys/wait.h)
|
|
52
57
|
|
|
53
58
|
dnl Check for declarations
|
|
54
59
|
AC_CHECK_DECL([_PATH_BSHELL],,AC_DEFINE_UNQUOTED([_PATH_BSHELL], "/bin/sh", [Define to system shell path]),[
|
|
@@ -91,9 +96,9 @@ AC_CHECK_DECL([PRIdMAX],,
|
|
|
91
96
|
|
|
92
97
|
dnl Checks for library functions.
|
|
93
98
|
AC_CHECK_FUNCS(bsearch faccessat getpwnam getrlimit isalpha killpg \
|
|
94
|
-
mempcpy \
|
|
99
|
+
memfd_create memrchr mempcpy \
|
|
95
100
|
sigsetmask stpcpy strchrnul strsignal strtod strtoimax \
|
|
96
|
-
strtoumax sysconf)
|
|
101
|
+
strtoumax sysconf tee wait3)
|
|
97
102
|
|
|
98
103
|
dnl Check whether it's worth working around FreeBSD PR kern/125009.
|
|
99
104
|
dnl The traditional behavior of access/faccessat is crazy, but
|
|
@@ -135,6 +140,24 @@ if test "$use_fnmatch" = yes && test "$enable_glob" = yes; then
|
|
|
135
140
|
AC_CHECK_FUNCS(glob)
|
|
136
141
|
fi
|
|
137
142
|
|
|
143
|
+
if test "$enable_tee" != no; then
|
|
144
|
+
AC_CHECK_FUNCS(tee, use_tee=yes)
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
if test "$use_tee" = yes; then
|
|
148
|
+
AC_DEFINE([USE_TEE], [1], [Non-zero if tee(2) should be used])
|
|
149
|
+
else
|
|
150
|
+
AC_DEFINE([USE_TEE], [0], [Non-zero if tee(2) should be used])
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
if test "$enable_memfd_create" != no; then
|
|
154
|
+
AC_DEFINE([USE_MEMFD_CREATE], [1],
|
|
155
|
+
[Non-zero if memfd_create(3) should be used])
|
|
156
|
+
else
|
|
157
|
+
AC_DEFINE([USE_MEMFD_CREATE], [0],
|
|
158
|
+
[Non-zero if memfd_create(3) should be used])
|
|
159
|
+
fi
|
|
160
|
+
|
|
138
161
|
dnl Check for klibc signal.
|
|
139
162
|
AC_CHECK_FUNC(signal)
|
|
140
163
|
if test "$ac_cv_func_signal" != yes; then
|
|
@@ -144,10 +167,18 @@ if test "$ac_cv_func_signal" != yes; then
|
|
|
144
167
|
fi
|
|
145
168
|
|
|
146
169
|
dnl Check for stat64 (dietlibc/klibc).
|
|
147
|
-
AC_CHECK_FUNC(stat64
|
|
170
|
+
AC_CHECK_DECL(stat64, AC_CHECK_FUNC(stat64))
|
|
171
|
+
if test "$ac_cv_func_stat64" != yes; then
|
|
148
172
|
AC_DEFINE(fstat64, fstat, [64-bit operations are the same as 32-bit])
|
|
149
173
|
AC_DEFINE(lstat64, lstat, [64-bit operations are the same as 32-bit])
|
|
150
174
|
AC_DEFINE(stat64, stat, [64-bit operations are the same as 32-bit])
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
AC_CHECK_FUNC(glob64,, [
|
|
178
|
+
AC_DEFINE(glob64_t, glob_t, [64-bit operations are the same as 32-bit])
|
|
179
|
+
AC_DEFINE(glob64, glob, [64-bit operations are the same as 32-bit])
|
|
180
|
+
AC_DEFINE(globfree64, globfree,
|
|
181
|
+
[64-bit operations are the same as 32-bit])
|
|
151
182
|
])
|
|
152
183
|
|
|
153
184
|
dnl OS X apparently has stat64 but not open64.
|
|
@@ -173,13 +204,25 @@ if test "$have_st_mtim" = "yes"; then
|
|
|
173
204
|
[Define if your `struct stat' has `st_mtim'])
|
|
174
205
|
fi
|
|
175
206
|
|
|
207
|
+
dnl F_DUPFD_CLOEXEC is a mandatory part of POSIX since Issue 7
|
|
208
|
+
AC_MSG_CHECKING(for F_DUPFD_CLOEXEC)
|
|
209
|
+
AC_COMPILE_IFELSE(
|
|
210
|
+
[AC_LANG_PROGRAM([#include <unistd.h>
|
|
211
|
+
#include <fcntl.h>],
|
|
212
|
+
[return fcntl(0, F_DUPFD_CLOEXEC, 0)])],
|
|
213
|
+
have_dupfd_cloexec=1, have_dupfd_cloexec=0)
|
|
214
|
+
AC_MSG_RESULT($(expr yes \& $have_dupfd_cloexec \| no))
|
|
215
|
+
AC_DEFINE_UNQUOTED([HAVE_F_DUPFD_CLOEXEC], [$have_dupfd_cloexec],
|
|
216
|
+
[Define to 1 your system supports F_DUPFD_CLOEXEC])
|
|
217
|
+
|
|
176
218
|
AC_ARG_WITH(libedit, AS_HELP_STRING(--with-libedit, [Compile with libedit support]))
|
|
177
219
|
use_libedit=
|
|
178
220
|
if test "$with_libedit" = "yes"; then
|
|
179
221
|
AC_CHECK_LIB(edit, history_init, [
|
|
180
222
|
AC_CHECK_HEADER([histedit.h], [use_libedit="yes"],
|
|
181
223
|
AC_MSG_ERROR(
|
|
182
|
-
[Can't find required header files.]))]
|
|
224
|
+
[Can't find required header files.]))], [
|
|
225
|
+
AC_MSG_ERROR([Can't find libedit.])])
|
|
183
226
|
fi
|
|
184
227
|
if test "$use_libedit" != "yes"; then
|
|
185
228
|
AC_DEFINE([SMALL], 1, [Define if you build with -DSMALL])
|
|
@@ -11,11 +11,11 @@ def libdash_library_path():
|
|
|
11
11
|
|
|
12
12
|
if LIBDASH_LIBRARY_PATH is not None:
|
|
13
13
|
return LIBDASH_LIBRARY_PATH
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
FILE_PATH = os.path.dirname(os.path.realpath(os.path.abspath(__file__)))
|
|
16
16
|
LIBDASH_LIBRARY_PATH = os.path.join(FILE_PATH, "libdash.so")
|
|
17
17
|
return LIBDASH_LIBRARY_PATH
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
EOF_NLEFT = -99; # libdash/src/input.c
|
|
20
20
|
|
|
21
21
|
class ParsingException(Exception):
|
|
@@ -83,8 +83,9 @@ def parse(inputPath, init=True):
|
|
|
83
83
|
|
|
84
84
|
# Last line did not have a newline
|
|
85
85
|
assert (len (lines [-1]) > 0 and (lines [-1][-1] != '\n'))
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
elif nleft_after != 0:
|
|
87
|
+
# we formerly asserted that `nleft_after != 0`, but this no longer holds
|
|
88
|
+
linno_after = linno_after + 1; # The last line wasn't counted
|
|
88
89
|
|
|
89
90
|
n_ptr = cast (n_ptr_C, POINTER (union_node))
|
|
90
91
|
new_ast = of_node (n_ptr)
|
|
@@ -15,6 +15,10 @@ STRING_OF_VAR_TYPE_DICT = {
|
|
|
15
15
|
"Length" : "#"
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
UNQUOTED = 0 # everything escaped
|
|
19
|
+
QUOTED = 1 # only escape special characters
|
|
20
|
+
HEREDOC = 2 # like QUOTED, but _don't_ escape double quotes
|
|
21
|
+
QUOTE_MODES = [UNQUOTED, QUOTED, HEREDOC]
|
|
18
22
|
|
|
19
23
|
# dash.ml
|
|
20
24
|
#
|
|
@@ -324,25 +328,27 @@ def escaped (param):
|
|
|
324
328
|
# "${" ^ name ^ (if nul then ":" else "") ^ string_of_var_type vt ^ string_of_arg a ^ "}"
|
|
325
329
|
# | Q a -> "\"" ^ string_of_arg a ^ "\""
|
|
326
330
|
# | B t -> "$(" ^ to_string t ^ ")"
|
|
327
|
-
def string_of_arg_char (c,
|
|
331
|
+
def string_of_arg_char (c, quote_mode=UNQUOTED):
|
|
328
332
|
(type, param) = c;
|
|
329
333
|
|
|
330
334
|
if (type == "E"):
|
|
331
335
|
char = chr (param);
|
|
332
336
|
|
|
333
|
-
## MMG 2021-09-20 It might be safe to move everything except for " in the second list, but no need to do it if the tests pass
|
|
337
|
+
## MMG 2021-09-20 It might be safe to move everything except for " in the second list, but no need to do it if the tests pass
|
|
338
|
+
## '!' dropped for bash non-interactive bash compatibility
|
|
334
339
|
## Chars to escape unconditionally
|
|
335
|
-
chars_to_escape = ["'", '"', '`', '(', ')', '{', '}', '$', '
|
|
340
|
+
chars_to_escape = ["'", '"', '`', '(', ')', '{', '}', '$', '&', '|', ';']
|
|
336
341
|
## Chars to escape only when not quoted
|
|
337
342
|
chars_to_escape_when_no_quotes = ['*', '?', '[', ']', '#', '<', '>', '~', ' ']
|
|
338
343
|
if char in chars_to_escape:
|
|
339
344
|
return '\\' + char
|
|
340
|
-
elif char in chars_to_escape_when_no_quotes and
|
|
345
|
+
elif char in chars_to_escape_when_no_quotes and quote_mode==UNQUOTED:
|
|
341
346
|
return '\\' + char
|
|
342
347
|
else:
|
|
343
348
|
return escaped (param)
|
|
344
349
|
elif (type == "C"):
|
|
345
|
-
|
|
350
|
+
# HEREDOC should never escape double quotes per POSIX 2.7.4
|
|
351
|
+
if quote_mode==QUOTED and chr(param) == '"':
|
|
346
352
|
return '\\"'
|
|
347
353
|
else:
|
|
348
354
|
return chr (param);
|
|
@@ -360,7 +366,7 @@ def string_of_arg_char (c, is_quoted=False):
|
|
|
360
366
|
print ("Unexpected param for T: %s" % param);
|
|
361
367
|
abort ();
|
|
362
368
|
elif (type == "A"):
|
|
363
|
-
return "$((" + string_of_arg (param,
|
|
369
|
+
return "$((" + string_of_arg (param, quote_mode) + "))";
|
|
364
370
|
elif (type == "V"):
|
|
365
371
|
assert (len (param) == 4);
|
|
366
372
|
if (param [0] == "Length"):
|
|
@@ -381,13 +387,20 @@ def string_of_arg_char (c, is_quoted=False):
|
|
|
381
387
|
else:
|
|
382
388
|
os.abort (); # For my own sanity
|
|
383
389
|
|
|
384
|
-
stri += string_of_var_type (vt) + string_of_arg (a,
|
|
390
|
+
stri += string_of_var_type (vt) + string_of_arg (a, quote_mode) + "}";
|
|
385
391
|
|
|
386
392
|
return stri;
|
|
387
393
|
elif (type == "Q"):
|
|
388
|
-
return "\"" + string_of_arg (param,
|
|
394
|
+
return "\"" + string_of_arg (param, quote_mode=QUOTED) + "\"";
|
|
389
395
|
elif (type == "B"):
|
|
390
|
-
|
|
396
|
+
body = to_string (param)
|
|
397
|
+
# to handle $( () )
|
|
398
|
+
try:
|
|
399
|
+
if body[0] == "(" and body[-1] == ")":
|
|
400
|
+
body = f" {body} "
|
|
401
|
+
except IndexError:
|
|
402
|
+
pass
|
|
403
|
+
return "$(" + body + ")"
|
|
391
404
|
else:
|
|
392
405
|
abort ();
|
|
393
406
|
|
|
@@ -395,21 +408,14 @@ def string_of_arg_char (c, is_quoted=False):
|
|
|
395
408
|
# and string_of_arg = function
|
|
396
409
|
# | [] -> ""
|
|
397
410
|
# | c :: a -> string_of_arg_char c ^ string_of_arg a
|
|
398
|
-
def string_of_arg (args,
|
|
411
|
+
def string_of_arg (args, quote_mode=UNQUOTED):
|
|
399
412
|
# print (args);
|
|
400
413
|
|
|
401
414
|
i = 0
|
|
402
415
|
text = []
|
|
403
416
|
while i < len(args):
|
|
404
|
-
c = string_of_arg_char(args[i],
|
|
405
|
-
|
|
406
|
-
# dash will parse '$?' as
|
|
407
|
-
# [(C, '$'), (E, '?')]
|
|
408
|
-
# but we don't normally want to escape ?
|
|
409
|
-
#
|
|
410
|
-
# so we check up after the fact: if the character after $ is escaped,
|
|
411
|
-
# we'll escape the $, too
|
|
412
|
-
if c == "$" and (i+1 < len(args)) and args[i+1][0] == "E":
|
|
417
|
+
c = string_of_arg_char(args[i], quote_mode=quote_mode)
|
|
418
|
+
if c == "$" and (i+1 < len(args)):
|
|
413
419
|
c = "\\$"
|
|
414
420
|
text.append(c)
|
|
415
421
|
|
|
@@ -526,7 +532,8 @@ def string_of_redir (redir):
|
|
|
526
532
|
elif (type == "Heredoc"):
|
|
527
533
|
(t, fd, a) = params;
|
|
528
534
|
|
|
529
|
-
|
|
535
|
+
# MMG 2022-08-23 not quite correct
|
|
536
|
+
heredoc = string_of_arg (a, quote_mode=HEREDOC);
|
|
530
537
|
marker = fresh_marker0 (heredoc);
|
|
531
538
|
|
|
532
539
|
stri = show_unless (0, fd) + "<<";
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: libdash
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Bindings for the dash shell as a library
|
|
5
|
+
Author: PaSh contributors
|
|
6
|
+
Author-email: Michael Greenberg <michael@greenberg.science>
|
|
7
|
+
License: Copyright (c) 1989-1994
|
|
8
|
+
The Regents of the University of California. All rights reserved.
|
|
9
|
+
Copyright (c) 1997 Christos Zoulas. All rights reserved.
|
|
10
|
+
Copyright (c) 1997-2005
|
|
11
|
+
Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
|
|
12
|
+
|
|
13
|
+
This code is derived from software contributed to Berkeley by Kenneth Almquist.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Redistribution and use in source and binary forms, with or without
|
|
17
|
+
modification, are permitted provided that the following conditions
|
|
18
|
+
are met:
|
|
19
|
+
1. Redistributions of source code must retain the above copyright
|
|
20
|
+
notice, this list of conditions and the following disclaimer.
|
|
21
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
22
|
+
notice, this list of conditions and the following disclaimer in the
|
|
23
|
+
documentation and/or other materials provided with the distribution.
|
|
24
|
+
3. Neither the name of the University nor the names of its contributors
|
|
25
|
+
may be used to endorse or promote products derived from this software
|
|
26
|
+
without specific prior written permission.
|
|
27
|
+
|
|
28
|
+
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
29
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
30
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
31
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
32
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
33
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
34
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
35
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
36
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
37
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
38
|
+
SUCH DAMAGE.
|
|
39
|
+
|
|
40
|
+
mksignames.c:
|
|
41
|
+
|
|
42
|
+
This file is not directly linked with dash. However, its output is.
|
|
43
|
+
|
|
44
|
+
Copyright (C) 1992 Free Software Foundation, Inc.
|
|
45
|
+
|
|
46
|
+
This file is part of GNU Bash, the Bourne Again SHell.
|
|
47
|
+
|
|
48
|
+
Bash is free software; you can redistribute it and/or modify it under
|
|
49
|
+
the terms of the GNU General Public License as published by the Free
|
|
50
|
+
Software Foundation; either version 2, or (at your option) any later
|
|
51
|
+
version.
|
|
52
|
+
|
|
53
|
+
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
54
|
+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
55
|
+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
56
|
+
for more details.
|
|
57
|
+
|
|
58
|
+
You should have received a copy of the GNU General Public License with
|
|
59
|
+
your Debian GNU/Linux system, in /usr/share/common-licenses/GPL, or with the
|
|
60
|
+
Debian GNU/Linux hello source package as the file COPYING. If not,
|
|
61
|
+
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
62
|
+
Boston, MA 02111 USA.
|
|
63
|
+
|
|
64
|
+
Project-URL: Homepage, https://github.com/binpash/libdash
|
|
65
|
+
Project-URL: Bug Tracker, https://github.com/binpash/libdash/issues
|
|
66
|
+
Classifier: Programming Language :: Python :: 3
|
|
67
|
+
Classifier: Topic :: System :: System Shells
|
|
68
|
+
Classifier: Operating System :: POSIX
|
|
69
|
+
Requires-Python: >=3.7
|
|
70
|
+
Description-Content-Type: text/markdown
|
|
71
|
+
License-File: COPYING
|
|
72
|
+
|
|
73
|
+
[](https://github.com/mgree/libdash/actions/workflows/build.yml)
|
|
74
|
+
|
|
75
|
+
*libdash* is a fork of the Linux Kernel's `dash` shell that builds a linkable library with extra exposed interfaces. The primary use of libdash is to parse shell scripts, but it could be used for more.
|
|
76
|
+
|
|
77
|
+
The Python bindings are packaged as the [`libdash` PyPi package](https://pypi.org/project/libdash/).
|
|
78
|
+
|
|
79
|
+
The OCaml bindings---packaged as the [`libdash` OPAM package](https://opam.ocaml.org/packages/libdash/)---include two executables, `shell_to_json` and `json_to_shell`, which let you conveniently parse POSIX shell scripts into a JSON AST.
|
|
80
|
+
|
|
81
|
+
# What are the dependencies?
|
|
82
|
+
|
|
83
|
+
The C code for dash should build on a wide variety of systems; it requires `libtool` and `autotools` (`aclocal`, `autoheader`, `automake`, `autoconf`). The library may not build on platforms with esoteric linkers; it's been tested on macOS and Linux.
|
|
84
|
+
|
|
85
|
+
The Python and OCaml bindings depend on being able to build the C code. See `libdash.opam` for details on the OCaml code's dependencies, which includes the build-time external dependencies. Python wheels have no need for these build-time dependencies, but building from a Python source distribution will only succeed when `libtool` and `autotools` are present.
|
|
86
|
+
|
|
87
|
+
The CI scripts (in `.github/workflows/build.yml`) give build details.
|
|
88
|
+
|
|
89
|
+
## How to build `libdash` from source
|
|
90
|
+
|
|
91
|
+
### Python
|
|
92
|
+
|
|
93
|
+
Run `python3 setup.py install`. On macOS, you must first install the build dependencies via `brew install libtool autoconf automake`.
|
|
94
|
+
|
|
95
|
+
You can test the Python bindings by running:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
cd python; make test
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### OCaml
|
|
102
|
+
|
|
103
|
+
Install the OPAM file: `opam pin add .` or `opam install .`. This will build the OCaml library and install it in your OPAM repository. There are tests in another directory; they will only build when libdash is actually installed.
|
|
104
|
+
|
|
105
|
+
You can test the OCaml bindings by running:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
cd ocaml; make test
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Testing
|
|
112
|
+
|
|
113
|
+
The tests use `test/round_trip.sh` to ensure that every tester file in `test/tests` round-trips correctly through parsing and pretty printing.
|
|
114
|
+
|
|
115
|
+
Additionally, you can run tests that compare the OCaml and Python implementations (after you've installed them both):
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
cd test; make
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
# How to use the parser
|
|
122
|
+
|
|
123
|
+
For Python, see [`python/rt.py`](https://github.com/mgree/libdash/blob/master/python/rt.py), an example tool that does a round-trip: shell syntax to AST back to shell syntax.
|
|
124
|
+
|
|
125
|
+
For OCaml, see [`ocaml/shell_to_json.ml`](https://github.com/mgree/libdash/blob/master/ocaml/shell_to_json.ml), a tool that parses shell syntax and produces JSON (using the [atdgen](https://opam.ocaml.org/packages/atdgen/) bindings).
|
|
126
|
+
|
|
127
|
+
The ideal low-level interface to use is `parsecmd_safe` in `parser.c`; you'll need to ensure that dash's initialization routines have been called and that the stack marks are managed correctly. Parsing the POSIX shell is a complicated affair: beyond the usual locale issues, aliases affect the lexer, so one must use `setalias` and `unalias` to manage any aliases that ought to exist.
|
|
128
|
+
|
|
129
|
+
# How work with the parsed nodes
|
|
130
|
+
|
|
131
|
+
The general AST is described in `nodes.h`. There are some tricky invariants around the precise formatting of control codes; the OCaml code shows some examples of working with the `args` fields in `ocaml/ast.ml`, which converts the C AST to an OCaml AST.
|
|
132
|
+
|
|
133
|
+
The OCaml tools `shell_to_json` and `json_to_shell` will produce JSON ASTs, allowing you to work with these ASTs in any language.
|
|
134
|
+
|
|
135
|
+
# Pretty printing
|
|
136
|
+
|
|
137
|
+
The pretty printer does its best to produce valid shell scripts, but it's possible to manually construct AST nodes that don't directly correspond to valid scripts.
|
|
138
|
+
|
|
139
|
+
For example, the Python AST `[[['Q', [['C', 34]]]]]` represents a quoted field containing a double quote character. Translated literally, this would yield the string `"""`, which is not a valid shell script. The pretty printer will instead automatically escape the inner quote, rendering `"\""`.
|
|
140
|
+
|
|
141
|
+
While the printer tries to get things right either way, you should use escapes to signal to the printer when to escape: you should use the Python AST `[[['Q', [['E', 34]]]]]` to mark the inner double quote as escaped.
|
|
142
|
+
|
|
143
|
+
# Known issues
|
|
144
|
+
|
|
145
|
+
We currently do not escape the character `!` (exclamation point). In an interactive shell, `!` is likely treated as a history substitution (and so should be escaped), but in a non-interactive shell, `!` is treated normally. We currently cater to non-interactive shells; eventually this behavior will be controllable.
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "libdash"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.0"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name="Michael Greenberg", email="michael@greenberg.science" },
|
|
6
|
+
{ name="PaSh contributors" },
|
|
6
7
|
]
|
|
8
|
+
license = { file = "COPYING" }
|
|
7
9
|
description = "Bindings for the dash shell as a library"
|
|
8
10
|
readme = "README.md"
|
|
9
|
-
license = { file="COPYING" }
|
|
10
11
|
requires-python = ">=3.7"
|
|
11
12
|
classifiers = [
|
|
12
13
|
"Programming Language :: Python :: 3",
|
|
13
14
|
"Topic :: System :: System Shells",
|
|
14
|
-
"License :: OSI Approved :: MIT License",
|
|
15
15
|
"Operating System :: POSIX",
|
|
16
16
|
]
|
|
17
17
|
|
|
18
|
+
|
|
18
19
|
[project.urls]
|
|
19
|
-
"Homepage" = "https://github.com/
|
|
20
|
-
"Bug Tracker" = "https://github.com/
|
|
20
|
+
"Homepage" = "https://github.com/binpash/libdash"
|
|
21
|
+
"Bug Tracker" = "https://github.com/binpash/libdash/issues"
|
|
21
22
|
|
|
22
23
|
[build-system]
|
|
23
24
|
requires = ["setuptools>=61.0"]
|