Adding upstream version 5.2.37.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
parent
cf91100bce
commit
fa1b3d3922
1435 changed files with 757174 additions and 0 deletions
245
examples/loadables/accept.c
Normal file
245
examples/loadables/accept.c
Normal file
|
@ -0,0 +1,245 @@
|
|||
/* accept - listen for and accept a remote network connection on a given port */
|
||||
|
||||
/*
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "bashtypes.h"
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include "typemax.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "loadables.h"
|
||||
|
||||
static int accept_bind_variable (char *, int);
|
||||
|
||||
int
|
||||
accept_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
SHELL_VAR *v;
|
||||
intmax_t iport;
|
||||
int opt;
|
||||
char *tmoutarg, *fdvar, *rhostvar, *rhost, *bindaddr;
|
||||
unsigned short uport;
|
||||
int servsock, clisock;
|
||||
struct sockaddr_in server, client;
|
||||
socklen_t clientlen;
|
||||
struct timeval timeval;
|
||||
struct linger linger = { 0, 0 };
|
||||
|
||||
rhostvar = tmoutarg = fdvar = rhost = bindaddr = (char *)NULL;
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "b:r:t:v:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'b':
|
||||
bindaddr = list_optarg;
|
||||
break;
|
||||
case 'r':
|
||||
rhostvar = list_optarg;
|
||||
break;
|
||||
case 't':
|
||||
tmoutarg = list_optarg;
|
||||
break;
|
||||
case 'v':
|
||||
fdvar = list_optarg;
|
||||
break;
|
||||
CASE_HELPOPT;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
list = loptend;
|
||||
|
||||
/* Validate input and variables */
|
||||
if (tmoutarg)
|
||||
{
|
||||
long ival, uval;
|
||||
opt = uconvert (tmoutarg, &ival, &uval, (char **)0);
|
||||
if (opt == 0 || ival < 0 || uval < 0)
|
||||
{
|
||||
builtin_error ("%s: invalid timeout specification", tmoutarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
timeval.tv_sec = ival;
|
||||
timeval.tv_usec = uval;
|
||||
/* XXX - should we warn if ival == uval == 0 ? */
|
||||
}
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
if (legal_number (list->word->word, &iport) == 0 || iport < 0 || iport > TYPE_MAXIMUM (unsigned short))
|
||||
{
|
||||
builtin_error ("%s: invalid port number", list->word->word);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
uport = (unsigned short)iport;
|
||||
|
||||
if (fdvar == 0)
|
||||
fdvar = "ACCEPT_FD";
|
||||
|
||||
unbind_variable (fdvar);
|
||||
if (rhostvar)
|
||||
unbind_variable (rhostvar);
|
||||
|
||||
if ((servsock = socket (AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
|
||||
{
|
||||
builtin_error ("cannot create socket: %s", strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
memset ((char *)&server, 0, sizeof (server));
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(uport);
|
||||
server.sin_addr.s_addr = bindaddr ? inet_addr (bindaddr) : htonl(INADDR_ANY);
|
||||
|
||||
if (server.sin_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
builtin_error ("invalid address: %s", strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
opt = 1;
|
||||
setsockopt (servsock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof (opt));
|
||||
setsockopt (servsock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof (linger));
|
||||
|
||||
if (bind (servsock, (struct sockaddr *)&server, sizeof (server)) < 0)
|
||||
{
|
||||
builtin_error ("socket bind failure: %s", strerror (errno));
|
||||
close (servsock);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (listen (servsock, 1) < 0)
|
||||
{
|
||||
builtin_error ("listen failure: %s", strerror (errno));
|
||||
close (servsock);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (tmoutarg)
|
||||
{
|
||||
fd_set iofds;
|
||||
|
||||
FD_ZERO(&iofds);
|
||||
FD_SET(servsock, &iofds);
|
||||
|
||||
opt = select (servsock+1, &iofds, 0, 0, &timeval);
|
||||
if (opt < 0)
|
||||
builtin_error ("select failure: %s", strerror (errno));
|
||||
if (opt <= 0)
|
||||
{
|
||||
close (servsock);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
clientlen = sizeof (client);
|
||||
if ((clisock = accept (servsock, (struct sockaddr *)&client, &clientlen)) < 0)
|
||||
{
|
||||
builtin_error ("client accept failure: %s", strerror (errno));
|
||||
close (servsock);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
close (servsock);
|
||||
|
||||
accept_bind_variable (fdvar, clisock);
|
||||
if (rhostvar)
|
||||
{
|
||||
rhost = inet_ntoa (client.sin_addr);
|
||||
v = builtin_bind_variable (rhostvar, rhost, 0);
|
||||
if (v == 0 || readonly_p (v) || noassign_p (v))
|
||||
builtin_error ("%s: cannot set variable", rhostvar);
|
||||
}
|
||||
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
accept_bind_variable (varname, intval)
|
||||
char *varname;
|
||||
int intval;
|
||||
{
|
||||
SHELL_VAR *v;
|
||||
char ibuf[INT_STRLEN_BOUND (int) + 1], *p;
|
||||
|
||||
p = fmtulong (intval, 10, ibuf, sizeof (ibuf), 0);
|
||||
v = builtin_bind_variable (varname, p, 0); /* XXX */
|
||||
if (v == 0 || readonly_p (v) || noassign_p (v))
|
||||
builtin_error ("%s: cannot set variable", varname);
|
||||
return (v != 0);
|
||||
}
|
||||
|
||||
char *accept_doc[] = {
|
||||
"Accept a network connection on a specified port.",
|
||||
""
|
||||
"This builtin allows a bash script to act as a TCP/IP server.",
|
||||
"",
|
||||
"Options, if supplied, have the following meanings:",
|
||||
" -b address use ADDRESS as the IP address to listen on; the",
|
||||
" default is INADDR_ANY",
|
||||
" -t timeout wait TIMEOUT seconds for a connection. TIMEOUT may",
|
||||
" be a decimal number including a fractional portion",
|
||||
" -v varname store the numeric file descriptor of the connected",
|
||||
" socket into VARNAME. The default VARNAME is ACCEPT_FD",
|
||||
" -r rhost store the IP address of the remote host into the shell",
|
||||
" variable RHOST, in dotted-decimal notation",
|
||||
"",
|
||||
"If successful, the shell variable ACCEPT_FD, or the variable named by the",
|
||||
"-v option, will be set to the fd of the connected socket, suitable for",
|
||||
"use as 'read -u$ACCEPT_FD'. RHOST, if supplied, will hold the IP address",
|
||||
"of the remote client. The return status is 0.",
|
||||
"",
|
||||
"On failure, the return status is 1 and ACCEPT_FD (or VARNAME) and RHOST,",
|
||||
"if supplied, will be unset.",
|
||||
"",
|
||||
"The server socket fd will be closed before accept returns.",
|
||||
(char *) NULL
|
||||
};
|
||||
|
||||
struct builtin accept_struct = {
|
||||
"accept", /* builtin name */
|
||||
accept_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
accept_doc, /* array of long documentation strings. */
|
||||
"accept [-b address] [-t timeout] [-v varname] [-r addrvar ] port", /* usage synopsis; becomes short_doc */
|
||||
0 /* reserved for internal use */
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue