Skip to content

Commit

Permalink
allow nc to build on linux and os x
Browse files Browse the repository at this point in the history
  • Loading branch information
busterb committed Sep 13, 2015
1 parent 627b026 commit 8c90be2
Show file tree
Hide file tree
Showing 16 changed files with 603 additions and 20 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ include/pqueue.h
include/tls.h
include/openssl/*.h

!/apps/nc/readpassphrase.c
/apps/nc/*.h
/apps/nc/*.c
/apps/nc/nc*
Expand Down
19 changes: 14 additions & 5 deletions apps/nc/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
include $(top_srcdir)/Makefile.am.common

if HOST_OPENBSD

if HAVE_POLL
if BUILD_NC

noinst_PROGRAMS = nc

Expand All @@ -11,15 +9,26 @@ EXTRA_DIST = nc.1
nc_LDADD = $(PLATFORM_LDADD) $(PROG_LDADD)
nc_LDADD += $(top_builddir)/tls/libtls.la

CPPFLAGS += -I$(top_srcdir)/apps/nc/compat

nc_SOURCES = atomicio.c
nc_SOURCES += netcat.c
nc_SOURCES += socks.c
noinst_HEADERS = atomicio.h
noinst_HEADERS += compat/sys/socket.h

if !HAVE_STRTONUM
nc_SOURCES += strtonum.c
nc_SOURCES += compat/socket.c

if !HAVE_ACCEPT4
nc_SOURCES += compat/accept4.c
endif

if !HAVE_READPASSPHRASE
nc_SOURCES += compat/readpassphrase.c
endif

if !HAVE_STRTONUM
nc_SOURCES += compat/strtonum.c
endif

endif
17 changes: 17 additions & 0 deletions apps/nc/compat/accept4.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <sys/socket.h>
#include <fcntl.h>

int
accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
{
int rets = accept(s, addr, addrlen);
if (rets == -1)
return s;

if (flags & SOCK_CLOEXEC) {
flags = fcntl(s, F_GETFD);
fcntl(rets, F_SETFD, flags | FD_CLOEXEC);
}

return rets;
}
205 changes: 205 additions & 0 deletions apps/nc/compat/readpassphrase.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/* $OpenBSD: readpassphrase.c,v 1.22 2010/01/13 10:20:54 dtucker Exp $ */

/*
* Copyright (c) 2000-2002, 2007 Todd C. Miller <[email protected]>
*
* Permission to use, copy, modify, and 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.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/

/* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */

#include <termios.h>
#include <signal.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

#include <readpassphrase.h>

#ifndef _PATH_TTY
# define _PATH_TTY "/dev/tty"
#endif

#ifdef TCSASOFT
# define _T_FLUSH (TCSAFLUSH|TCSASOFT)
#else
# define _T_FLUSH (TCSAFLUSH)
#endif

/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
#if !defined(_POSIX_VDISABLE) && defined(VDISABLE)
# define _POSIX_VDISABLE VDISABLE
#endif

#ifndef _NSIG
# ifdef NSIG
# define _NSIG NSIG
# else
# define _NSIG 128
# endif
#endif

static volatile sig_atomic_t signo[_NSIG];

static void handler(int);

char *
readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
{
ssize_t bytes_written = 0;
ssize_t nr;
int input, output, save_errno, i, need_restart;
char ch, *p, *end;
struct termios term, oterm;
struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
struct sigaction savetstp, savettin, savettou, savepipe;

/* I suppose we could alloc on demand in this case (XXX). */
if (bufsiz == 0) {
errno = EINVAL;
return(NULL);
}

restart:
for (i = 0; i < _NSIG; i++)
signo[i] = 0;
nr = -1;
save_errno = 0;
need_restart = 0;
/*
* Read and write to /dev/tty if available. If not, read from
* stdin and write to stderr unless a tty is required.
*/
if ((flags & RPP_STDIN) ||
(input = output = open(_PATH_TTY, O_RDWR)) == -1) {
if (flags & RPP_REQUIRE_TTY) {
errno = ENOTTY;
return(NULL);
}
input = STDIN_FILENO;
output = STDERR_FILENO;
}

/*
* Catch signals that would otherwise cause the user to end
* up with echo turned off in the shell. Don't worry about
* things like SIGXCPU and SIGVTALRM for now.
*/
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0; /* don't restart system calls */
sa.sa_handler = handler;
(void)sigaction(SIGALRM, &sa, &savealrm);
(void)sigaction(SIGHUP, &sa, &savehup);
(void)sigaction(SIGINT, &sa, &saveint);
(void)sigaction(SIGPIPE, &sa, &savepipe);
(void)sigaction(SIGQUIT, &sa, &savequit);
(void)sigaction(SIGTERM, &sa, &saveterm);
(void)sigaction(SIGTSTP, &sa, &savetstp);
(void)sigaction(SIGTTIN, &sa, &savettin);
(void)sigaction(SIGTTOU, &sa, &savettou);

/* Turn off echo if possible. */
if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
memcpy(&term, &oterm, sizeof(term));
if (!(flags & RPP_ECHO_ON))
term.c_lflag &= ~(ECHO | ECHONL);
#ifdef VSTATUS
if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
term.c_cc[VSTATUS] = _POSIX_VDISABLE;
#endif
(void)tcsetattr(input, _T_FLUSH, &term);
} else {
memset(&term, 0, sizeof(term));
term.c_lflag |= ECHO;
memset(&oterm, 0, sizeof(oterm));
oterm.c_lflag |= ECHO;
}

/* No I/O if we are already backgrounded. */
if (signo[SIGTTOU] != 1 && signo[SIGTTIN] != 1) {
if (!(flags & RPP_STDIN))
bytes_written = write(output, prompt, strlen(prompt));
end = buf + bufsiz - 1;
p = buf;
while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
if (p < end) {
if ((flags & RPP_SEVENBIT))
ch &= 0x7f;
if (isalpha(ch)) {
if ((flags & RPP_FORCELOWER))
ch = (char)tolower(ch);
if ((flags & RPP_FORCEUPPER))
ch = (char)toupper(ch);
}
*p++ = ch;
}
}
*p = '\0';
save_errno = errno;
if (!(term.c_lflag & ECHO))
bytes_written = write(output, "\n", 1);
}

(void) bytes_written;

/* Restore old terminal settings and signals. */
if (memcmp(&term, &oterm, sizeof(term)) != 0) {
while (tcsetattr(input, _T_FLUSH, &oterm) == -1 &&
errno == EINTR)
continue;
}
(void)sigaction(SIGALRM, &savealrm, NULL);
(void)sigaction(SIGHUP, &savehup, NULL);
(void)sigaction(SIGINT, &saveint, NULL);
(void)sigaction(SIGQUIT, &savequit, NULL);
(void)sigaction(SIGPIPE, &savepipe, NULL);
(void)sigaction(SIGTERM, &saveterm, NULL);
(void)sigaction(SIGTSTP, &savetstp, NULL);
(void)sigaction(SIGTTIN, &savettin, NULL);
(void)sigaction(SIGTTOU, &savettou, NULL);
if (input != STDIN_FILENO)
(void)close(input);

/*
* If we were interrupted by a signal, resend it to ourselves
* now that we have restored the signal handlers.
*/
for (i = 0; i < _NSIG; i++) {
if (signo[i]) {
kill(getpid(), i);
switch (i) {
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
need_restart = 1;
}
}
}
if (need_restart)
goto restart;

if (save_errno)
errno = save_errno;
return(nr == -1 ? NULL : buf);
}

static void handler(int s)
{
signo[s] = 1;
}
29 changes: 29 additions & 0 deletions apps/nc/compat/socket.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#define SOCKET_FLAGS_PRIV

#include <sys/socket.h>

#ifdef NEED_SOCKET_FLAGS

#include <fcntl.h>

int
_socket(int domain, int type, int protocol)
{
int s = socket(domain, type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK), protocol);
int flags;
if (s == -1)
return s;

if (type & SOCK_CLOEXEC) {
flags = fcntl(s, F_GETFD);
fcntl(s, F_SETFD, flags | FD_CLOEXEC);
}

if (type & SOCK_NONBLOCK) {
flags = fcntl(s, F_GETFL);
fcntl(s, F_SETFL, flags | O_NONBLOCK);
}
return s;
}

#endif
65 changes: 65 additions & 0 deletions apps/nc/compat/strtonum.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* $OpenBSD: strtonum.c,v 1.7 2013/04/17 18:40:58 tedu Exp $ */

/*
* Copyright (c) 2004 Ted Unangst and Todd Miller
* All rights reserved.
*
* Permission to use, copy, modify, and 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 <errno.h>
#include <limits.h>
#include <stdlib.h>

#define INVALID 1
#define TOOSMALL 2
#define TOOLARGE 3

long long
strtonum(const char *numstr, long long minval, long long maxval,
const char **errstrp)
{
long long ll = 0;
int error = 0;
char *ep;
struct errval {
const char *errstr;
int err;
} ev[4] = {
{ NULL, 0 },
{ "invalid", EINVAL },
{ "too small", ERANGE },
{ "too large", ERANGE },
};

ev[0].err = errno;
errno = 0;
if (minval > maxval) {
error = INVALID;
} else {
ll = strtoll(numstr, &ep, 10);
if (numstr == ep || *ep != '\0')
error = INVALID;
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
error = TOOSMALL;
else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
error = TOOLARGE;
}
if (errstrp != NULL)
*errstrp = ev[error].errstr;
errno = ev[error].err;
if (error)
ll = 0;

return (ll);
}
31 changes: 31 additions & 0 deletions apps/nc/compat/sys/socket.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Public domain
* sys/socket.h compatibility shim
*/

#ifndef _WIN32
#include_next <sys/socket.h>

#if !defined(SOCK_NONBLOCK) || !defined(SOCK_CLOEXEC)
#define NEED_SOCKET_FLAGS
int _socket(int domain, int type, int protocol);
#ifndef SOCKET_FLAGS_PRIV
#define socket(d, t, p) _socket(d, t, p)
#endif
#endif

#ifndef SOCK_NONBLOCK
#define SOCK_NONBLOCK 0x4000 /* set O_NONBLOCK */
#endif

#ifndef SOCK_CLOEXEC
#define SOCK_CLOEXEC 0x8000 /* set FD_CLOEXEC */
#endif

#ifndef HAVE_ACCEPT4
int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags);
#endif

#else
#include <win32netcompat.h>
#endif
Loading

0 comments on commit 8c90be2

Please sign in to comment.