Skip to content

Commit 2c64cb5

Browse files
author
Fadi Moukayed
committed
Populate repository
1 parent f131db7 commit 2c64cb5

File tree

10 files changed

+625
-2
lines changed

10 files changed

+625
-2
lines changed

CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
cmake_minimum_required(VERSION 3.9)
2+
project(bashext-socket VERSION 1.0 DESCRIPTION "BASH socket extension" LANGUAGES C)
3+
include(GNUInstallDirs)
4+
set(DEFAULT_BUILD_TYPE "Release")
5+
find_package(PkgConfig REQUIRED)
6+
pkg_check_modules(BASH REQUIRED IMPORTED_TARGET bash)
7+
add_library(bashext-socket SHARED
8+
src/accept.c
9+
src/socket.c
10+
src/alarm.c
11+
src/pause.c)
12+
set_target_properties(bashext-socket PROPERTIES
13+
VERSION ${PROJECT_VERSION} SOVERSION 1)
14+
target_link_libraries(bashext-socket PUBLIC PkgConfig::BASH)
15+
install(TARGETS bashext-socket
16+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

README.md

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,116 @@
1-
# bash-socket
2-
Loadable BASH extension for socket programming
1+
# bash-extensions
2+
3+
Loadable BASH extensions for socket programming.
4+
5+
## Loading the extension
6+
7+
`$ enable -f /usr/lib/x86_64-linux-gnu/libbashext-socket.so accept socket alarm pause`
8+
9+
## Provided functions
10+
11+
The extension provides the following functions
12+
13+
### accept(2)
14+
15+
```
16+
$ help accept
17+
accept: accept varname [socket]
18+
accept a connection on a socket.
19+
20+
Calls accept(2) on the given socket. The resulting file descriptor
21+
is written to the variable denoted by varname.
22+
if socket is not given, assumes 0 (STDIN).
23+
```
24+
25+
### socket(2)
26+
27+
```
28+
$ help socket
29+
socket: socket varname AF_UNIX|AF_INET|AF_INET6 SOCK_STREAM|SOCK_DGRAM local|peer PATH|ADDRESS [port] [queue]
30+
creates a socket.
31+
32+
Provides an interface for creating and using POSIX sockets
33+
The result socket handle is written to the variable denoted by varname.
34+
```
35+
36+
### alarm(2)
37+
38+
```
39+
$ help alarm
40+
alarm: alarm seconds [varname]
41+
Arranges for a SIGALRM to be delivered to the shell in seconds.
42+
If seconds is zero, any pending alarm is cancelled.
43+
If varname is given, it is set to the number of seconds remaining until any
44+
previously scheduled alarm was to be delivered, or zero if there was
45+
previously scheduled alarm.
46+
```
47+
48+
### pause(2)
49+
50+
```
51+
$ help pause
52+
pause: pause
53+
Suspends the shell until a signal is delivered.
54+
```
55+
56+
## Examples
57+
58+
### Forking AF\_UNIX server
59+
60+
Code (`echo-server.sh`):
61+
62+
```
63+
#!/bin/bash
64+
set -eu
65+
66+
enable -f "/usr/lib/$HOSTTYPE-$OSTYPE/libbashext-socket.so" socket accept
67+
68+
socket SOCK AF_UNIX SOCK_STREAM local "$1"
69+
70+
trap "trap - TERM && kill -- -$$ 2>/dev/null" INT TERM HUP QUIT EXIT
71+
72+
while accept FD "${SOCK}" 2>/dev/null
73+
do
74+
while read -r DATA
75+
do
76+
printf '%s\n' "${DATA}"
77+
done <&${FD} >&${FD} &
78+
exec {FD}>&-
79+
wait
80+
done
81+
```
82+
83+
Demo:
84+
85+
```
86+
$ bash socket-server.sh /tmp/sock &
87+
[1] 31281
88+
$ nc -N -U /tmp/sock <<< "Hello World"
89+
Hello World
90+
```
91+
92+
### Simple AF\_UNIX client
93+
94+
Code (`echo-client.sh`)
95+
96+
```
97+
#!/bin/bash
98+
set -eu
99+
100+
enable -f "/usr/lib/$HOSTTYPE-$OSTYPE/libbashext-socket.so" socket
101+
102+
socket SOCK AF_UNIX SOCK_STREAM peer "$1"
103+
104+
echo "Hello World!" >&${SOCK}
105+
read -r -u ${SOCK} REPLY
106+
echo "$REPLY"
107+
```
108+
109+
Demo:
110+
111+
```
112+
$ bash echo-server.sh /tmp/sock &
113+
[1] 12991
114+
$ bash echo-client.sh /tmp/sock
115+
Hello World!
116+
```

debian/changelog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
bash-ext-socket (1.0-1) unstable; urgency=medium
2+
3+
* Initial release
4+
5+
-- Fadi Moukayed <fadi.moukayed@rohde-schwarz.com> Sat, 04 Apr 2020 14:23:28 +0000

debian/control

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Source: bash-ext-socket
2+
Priority: optional
3+
Maintainer: Fadi Moukayed <fadi.moukayed@rohde-schwarz.com>
4+
Build-Depends: debhelper-compat (= 11), cmake, bash-builtins
5+
Standards-Version: 4.1.2
6+
Section: shells
7+
8+
Package: bash-ext-socket
9+
Architecture: any
10+
Multi-Arch: same
11+
Depends: ${shlibs:Depends}, ${misc:Depends}
12+
Description: BASH socket accept(3) extension
13+
This C extension provides an "accept"-builtin function, allowing BASH program to utilize socket file handles.

debian/copyright

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2+
Upstream-Name: bash-ext-socket
3+
4+
Files: *
5+
Copyright: 2020 Fadi Moukayed <fadi.moukayed@rohde-schwarz.com>
6+
License: MIT
7+
Permission is hereby granted, free of charge, to any person obtaining a
8+
copy of this software and associated documentation files (the "Software"),
9+
to deal in the Software without restriction, including without limitation
10+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
11+
and/or sell copies of the Software, and to permit persons to whom the
12+
Software is furnished to do so, subject to the following conditions:
13+
.
14+
The above copyright notice and this permission notice (including the next
15+
paragraph) shall be included in all copies or substantial portions of the
16+
Software.
17+
.
18+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24+
DEALINGS IN THE SOFTWARE.
25+
26+
Files: debian/*
27+
Copyright: 2020 Fadi Moukayed <fadi.moukayed@rohde-schwarz.com>
28+
License: MIT
29+
Permission is hereby granted, free of charge, to any person obtaining a
30+
copy of this software and associated documentation files (the "Software"),
31+
to deal in the Software without restriction, including without limitation
32+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
33+
and/or sell copies of the Software, and to permit persons to whom the
34+
Software is furnished to do so, subject to the following conditions:
35+
.
36+
The above copyright notice and this permission notice (including the next
37+
paragraph) shall be included in all copies or substantial portions of the
38+
Software.
39+
.
40+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
43+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
44+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
45+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
46+
DEALINGS IN THE SOFTWARE.

debian/rules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/make -f
2+
3+
%:
4+
dh $@

src/accept.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include "builtins.h"
2+
#include "config.h"
3+
#include "shell.h"
4+
#include "common.h"
5+
#include <errno.h>
6+
#include <stdio.h>
7+
#include <sys/socket.h>
8+
#include <sys/types.h>
9+
10+
static int
11+
accept_builtin(WORD_LIST *list)
12+
{
13+
if (list == NULL) {
14+
builtin_usage();
15+
return EX_USAGE;
16+
}
17+
18+
if (no_options(list)) {
19+
return EX_USAGE;
20+
}
21+
22+
const char *varname = list->word->word;
23+
24+
list = list->next;
25+
26+
/* Default to STDIN */
27+
int socket = 0;
28+
29+
/* Pick up socket file descriptor from argument if specified. */
30+
if (list != NULL) {
31+
if (sscanf(list->word->word, "%d", &socket) < 1) {
32+
builtin_error("invalid socket fd: %s", list->word->word);
33+
return EXECUTION_FAILURE;
34+
}
35+
list = list->next;
36+
}
37+
38+
if (list != NULL) {
39+
builtin_usage();
40+
return EX_USAGE;
41+
}
42+
43+
int accfd = accept(socket, NULL, NULL);
44+
if (accfd == -1) {
45+
builtin_error("%s", strerror(errno));
46+
return EXECUTION_FAILURE;
47+
}
48+
49+
/* Bind file description number to varname. */
50+
char buffer[32];
51+
int ret = snprintf(buffer, sizeof(buffer), "%d", accfd);
52+
if (ret < 0 || ((unsigned int)ret) >= sizeof(buffer)) {
53+
builtin_error("snprintf: %s", strerror(errno));
54+
return EXECUTION_FAILURE;
55+
}
56+
bind_variable(varname, buffer, 0);
57+
58+
return EXECUTION_SUCCESS;
59+
}
60+
61+
static char *const accept_doc[] = {
62+
"accept a connection on a socket.",
63+
"Calls accept(2) on the given socket. The resulting file descriptor",
64+
"is written to the variable denoted by varname.",
65+
"if socket is not given, assumes 0 (STDIN).", NULL
66+
};
67+
68+
struct builtin accept_struct = {
69+
.name = "accept",
70+
.function = accept_builtin,
71+
.flags = BUILTIN_ENABLED,
72+
.long_doc = accept_doc,
73+
.short_doc = "accept varname [socket]",
74+
.handle = NULL
75+
};

src/alarm.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#include "builtins.h"
2+
#include "config.h"
3+
#include "shell.h"
4+
#include "common.h"
5+
#include <errno.h>
6+
#include <stdio.h>
7+
#include <unistd.h>
8+
9+
static int
10+
alarm_builtin(WORD_LIST *list)
11+
{
12+
if (list == NULL) {
13+
builtin_usage();
14+
return EX_USAGE;
15+
}
16+
17+
if (no_options(list)) {
18+
return EX_USAGE;
19+
}
20+
21+
unsigned int seconds;
22+
23+
if (sscanf(list->word->word, "%u", &seconds) != 1) {
24+
builtin_error("invalid argument: %s", list->word->word);
25+
return EXECUTION_FAILURE;
26+
}
27+
28+
list = list->next;
29+
30+
unsigned int remaining = alarm(seconds);
31+
32+
if (list != NULL) {
33+
char buffer[16];
34+
int ret = snprintf(buffer, sizeof(buffer), "%u", remaining);
35+
if (ret < 0 || ((unsigned int)ret) >= sizeof(buffer)) {
36+
builtin_warning("snprintf: %s", strerror(errno));
37+
} else {
38+
bind_variable(list->word->word, buffer, 0);
39+
}
40+
}
41+
42+
return EXECUTION_SUCCESS;
43+
}
44+
45+
static char *const alarm_doc[] = {
46+
"Arranges for a SIGALRM to be delivered to the shell in seconds.",
47+
"If seconds is zero, any pending alarm is cancelled.",
48+
"If varname is given, it is set to the number of seconds remaining until any",
49+
"previously scheduled alarm was to be delivered, or zero if there was",
50+
"no previously scheduled alarm.", NULL
51+
};
52+
53+
struct builtin alarm_struct = {
54+
.name = "alarm",
55+
.function = alarm_builtin,
56+
.flags = BUILTIN_ENABLED,
57+
.long_doc = alarm_doc,
58+
.short_doc = "alarm seconds [varname]",
59+
.handle = NULL
60+
};

src/pause.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "builtins.h"
2+
#include "config.h"
3+
#include "shell.h"
4+
#include "common.h"
5+
#include <unistd.h>
6+
7+
static int
8+
pause_builtin(WORD_LIST *list)
9+
{
10+
if (no_options(list)) {
11+
return EX_USAGE;
12+
}
13+
/* Don't accept any arguments. */
14+
if (list != NULL) {
15+
builtin_usage();
16+
return EX_USAGE;
17+
}
18+
19+
(void)pause();
20+
21+
return EXECUTION_SUCCESS;
22+
}
23+
24+
static char *const pause_doc[] = {
25+
"Suspends the shell until a signal is delivered.", NULL
26+
};
27+
28+
struct builtin pause_struct = {
29+
.name = "pause",
30+
.function = pause_builtin,
31+
.flags = BUILTIN_ENABLED,
32+
.long_doc = pause_doc,
33+
.short_doc = "pause",
34+
.handle = NULL
35+
};

0 commit comments

Comments
 (0)