Give /bin/cat the ability to connect to and read unix-domain sockets
MFC after: 1 week
This commit is contained in:
parent
4c1fc1b219
commit
cbf2d71f0d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=83482
@ -58,7 +58,12 @@ is a single dash
|
|||||||
.Pq Sq \&-
|
.Pq Sq \&-
|
||||||
or absent,
|
or absent,
|
||||||
.Nm
|
.Nm
|
||||||
reads from the standard input.
|
reads from the standard input. If
|
||||||
|
.Ar file
|
||||||
|
is a unix domain socket,
|
||||||
|
.Nm
|
||||||
|
connects to it and then reads it until EOF. This complements the unix-domain
|
||||||
|
binding capability available in inetd.
|
||||||
.Pp
|
.Pp
|
||||||
The options are as follows:
|
The options are as follows:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
|
157
bin/cat/cat.c
157
bin/cat/cat.c
@ -50,6 +50,11 @@ static const char rcsid[] =
|
|||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#ifndef NO_UDOM_SUPPORT
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
@ -59,16 +64,21 @@ static const char rcsid[] =
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
int bflag, eflag, nflag, sflag, tflag, vflag;
|
int bflag, eflag, nflag, sflag, tflag, vflag;
|
||||||
int rval;
|
int rval;
|
||||||
const char *filename;
|
const char *filename;
|
||||||
|
|
||||||
void cook_args __P((char *argv[]));
|
|
||||||
void cook_buf __P((FILE *));
|
|
||||||
int main __P((int argc, char *argv[]));
|
int main __P((int argc, char *argv[]));
|
||||||
void raw_args __P((char *argv[]));
|
|
||||||
void raw_cat __P((int));
|
static void scanfiles __P((char **argv, int cooked));
|
||||||
|
static void cook_cat __P((FILE *));
|
||||||
|
static void raw_cat __P((int));
|
||||||
|
|
||||||
|
#ifndef NO_UDOM_SUPPORT
|
||||||
|
static int udom_open __P((const char *path, int flags, int modes));
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main(argc, argv)
|
main(argc, argv)
|
||||||
@ -110,42 +120,55 @@ main(argc, argv)
|
|||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
if (bflag || eflag || nflag || sflag || tflag || vflag)
|
if (bflag || eflag || nflag || sflag || tflag || vflag)
|
||||||
cook_args(argv);
|
scanfiles(argv, 1);
|
||||||
else
|
else
|
||||||
raw_args(argv);
|
scanfiles(argv, 0);
|
||||||
if (fclose(stdout))
|
if (fclose(stdout))
|
||||||
err(1, "stdout");
|
err(1, "stdout");
|
||||||
exit(rval);
|
exit(rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cook_args(argv)
|
scanfiles(argv, cooked)
|
||||||
char **argv;
|
char **argv;
|
||||||
|
int cooked;
|
||||||
{
|
{
|
||||||
register FILE *fp;
|
int i = 0;
|
||||||
|
char *path;
|
||||||
|
|
||||||
fp = stdin;
|
while ((path = argv[i]) != NULL || i == 0) {
|
||||||
filename = "stdin";
|
int fd;
|
||||||
do {
|
|
||||||
if (*argv) {
|
if (path == NULL || strcmp(path, "-") == 0) {
|
||||||
if (!strcmp(*argv, "-"))
|
filename = "stdin";
|
||||||
fp = stdin;
|
fd = 0;
|
||||||
else if ((fp = fopen(*argv, "r")) == NULL) {
|
} else {
|
||||||
warn("%s", *argv);
|
filename = path;
|
||||||
rval = 1;
|
fd = open(path, O_RDONLY);
|
||||||
++argv;
|
#ifndef NO_UDOM_SUPPORT
|
||||||
continue;
|
if (fd < 0 && errno == EOPNOTSUPP)
|
||||||
}
|
fd = udom_open(path, O_RDONLY, 0);
|
||||||
filename = *argv++;
|
#endif
|
||||||
}
|
}
|
||||||
cook_buf(fp);
|
if (fd < 0) {
|
||||||
if (fp != stdin)
|
warn("%s", path);
|
||||||
(void)fclose(fp);
|
rval = 1;
|
||||||
} while (*argv);
|
} else if (cooked) {
|
||||||
|
FILE *fp = fdopen(fd, "r");
|
||||||
|
cook_cat(fp);
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
raw_cat(fd);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
if (path == NULL)
|
||||||
|
break;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
cook_buf(fp)
|
cook_cat(fp)
|
||||||
register FILE *fp;
|
register FILE *fp;
|
||||||
{
|
{
|
||||||
register int ch, gobble, line, prev;
|
register int ch, gobble, line, prev;
|
||||||
@ -208,33 +231,7 @@ cook_buf(fp)
|
|||||||
err(1, "stdout");
|
err(1, "stdout");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
raw_args(argv)
|
|
||||||
char **argv;
|
|
||||||
{
|
|
||||||
register int fd;
|
|
||||||
|
|
||||||
fd = fileno(stdin);
|
|
||||||
filename = "stdin";
|
|
||||||
do {
|
|
||||||
if (*argv) {
|
|
||||||
if (!strcmp(*argv, "-"))
|
|
||||||
fd = fileno(stdin);
|
|
||||||
else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
|
|
||||||
warn("%s", *argv);
|
|
||||||
rval = 1;
|
|
||||||
++argv;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
filename = *argv++;
|
|
||||||
}
|
|
||||||
raw_cat(fd);
|
|
||||||
if (fd != fileno(stdin))
|
|
||||||
(void)close(fd);
|
|
||||||
} while (*argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
raw_cat(rfd)
|
raw_cat(rfd)
|
||||||
register int rfd;
|
register int rfd;
|
||||||
{
|
{
|
||||||
@ -261,3 +258,53 @@ raw_cat(rfd)
|
|||||||
rval = 1;
|
rval = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NO_UDOM_SUPPORT
|
||||||
|
|
||||||
|
static int
|
||||||
|
udom_open(path, flags, modes)
|
||||||
|
const char *path;
|
||||||
|
int flags;
|
||||||
|
int modes;
|
||||||
|
{
|
||||||
|
struct sockaddr_un sou;
|
||||||
|
int fd;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
bzero(&sou, sizeof(sou));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Construct the unix domain socket address and attempt to connect
|
||||||
|
*/
|
||||||
|
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
|
||||||
|
sou.sun_family = AF_UNIX;
|
||||||
|
snprintf(sou.sun_path, sizeof(sou.sun_path), "%s", path);
|
||||||
|
len = strlen(sou.sun_path);
|
||||||
|
len = offsetof(struct sockaddr_un, sun_path[len+1]);
|
||||||
|
|
||||||
|
if (connect(fd, (void *)&sou, len) < 0) {
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* handle the open flags by shutting down appropriate directions
|
||||||
|
*/
|
||||||
|
if (fd >= 0) {
|
||||||
|
switch(flags & O_ACCMODE) {
|
||||||
|
case O_RDONLY:
|
||||||
|
shutdown(fd, SHUT_WR);
|
||||||
|
break;
|
||||||
|
case O_WRONLY:
|
||||||
|
shutdown(fd, SHUT_RD);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user