summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjaromil <jaromil@383723c8-4afa-0310-b8a8-b1afb83214fc>2003-07-15 14:14:23 (GMT)
committer jaromil <jaromil@383723c8-4afa-0310-b8a8-b1afb83214fc>2003-07-15 14:14:23 (GMT)
commited6f0921a2df3d02126149dee6e2bd407dc45b2f (patch)
tree60eeb534da888135c9b352a0841b311c2631bb0b
parent442ae266fe728449712c2b25372810a559e57803 (diff)
ftp upload fixed!
git-svn-id: svn://dyne.org/rastasoft/hasciicam@505 383723c8-4afa-0310-b8a8-b1afb83214fc
-rw-r--r--hasciicam/Makefile.am2
-rw-r--r--hasciicam/Makefile.in8
-rw-r--r--hasciicam/ftp.c299
-rw-r--r--hasciicam/ftp.h7
-rw-r--r--hasciicam/ftplib.c1295
-rw-r--r--hasciicam/ftplib.h125
-rw-r--r--hasciicam/hasciicam.c122
7 files changed, 1498 insertions, 360 deletions
diff --git a/hasciicam/Makefile.am b/hasciicam/Makefile.am
index f474332..2c97931 100644
--- a/hasciicam/Makefile.am
+++ b/hasciicam/Makefile.am
@@ -2,7 +2,7 @@ bin_PROGRAMS = hasciicam
hasciicam_SOURCES = \
hasciicam.c \
- ftp.c
+ ftplib.c
hasciicam_LDADD = @LIBS@
diff --git a/hasciicam/Makefile.in b/hasciicam/Makefile.in
index 0646320..46a2250 100644
--- a/hasciicam/Makefile.in
+++ b/hasciicam/Makefile.in
@@ -117,7 +117,7 @@ bin_PROGRAMS = hasciicam
hasciicam_SOURCES = \
hasciicam.c \
- ftp.c
+ ftplib.c
hasciicam_LDADD = @LIBS@
@@ -137,7 +137,7 @@ CONFIG_CLEAN_FILES =
bin_PROGRAMS = hasciicam$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS)
-am_hasciicam_OBJECTS = hasciicam.$(OBJEXT) ftp.$(OBJEXT)
+am_hasciicam_OBJECTS = hasciicam.$(OBJEXT) ftplib.$(OBJEXT)
hasciicam_OBJECTS = $(am_hasciicam_OBJECTS)
hasciicam_DEPENDENCIES =
hasciicam_LDFLAGS =
@@ -145,7 +145,7 @@ hasciicam_LDFLAGS =
DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
-@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/ftp.Po ./$(DEPDIR)/hasciicam.Po
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/ftplib.Po ./$(DEPDIR)/hasciicam.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
@@ -231,7 +231,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ftplib.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hasciicam.Po@am__quote@
distclean-depend:
diff --git a/hasciicam/ftp.c b/hasciicam/ftp.c
deleted file mode 100644
index 8babc84..0000000
--- a/hasciicam/ftp.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * (c) 1998-2000 Gerd Knorr
- *
- * functions to handle ftp uploads using the ftp utility
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-
-#include "config.h"
-#include "ftp.h"
-
-/* ---------------------------------------------------------------------- */
-/* FTP stuff */
-
-int ftp_connected;
-int ftp_debug;
-
-static int ftp_pty, ftp_pid;
-static char tty_name[32];
-static int userbreak = 0;
-
-static void ftp_send (int argc, ...);
-static int ftp_recv (void);
-
-static int
-open_pty ()
-{
-#ifdef HAVE_GETPT
- int master;
- char *slave;
-
- if (-1 == (master = getpt ()))
- return -1;
- if (-1 == grantpt (master) ||
- -1 == unlockpt (master) || NULL == (slave = ptsname (master)))
- {
- close (master);
- return -1;
- }
- strcpy (tty_name, slave);
- return master;
-#else
- static char pty_name[32];
- static char s1[] = "pqrs";
- static char s2[] = "0123456789abcdef";
-
- char *p1, *p2;
- int pty;
-
- for (p1 = s1; *p1; p1++)
- {
- for (p2 = s2; *p2; p2++)
- {
- sprintf (pty_name, "/dev/pty%c%c", *p1, *p2);
- sprintf (tty_name, "/dev/tty%c%c", *p1, *p2);
- if (-1 == access (tty_name, R_OK | W_OK))
- continue;
- if (-1 != (pty = open (pty_name, O_RDWR)))
- return pty;
- }
- }
- return -1;
-#endif
-}
-
-void
-ftp_init (int passive)
-{
- static char *noauto[] = { "ftp", "-n", NULL };
-
- if (-1 == (ftp_pty = open_pty ()))
- {
- fprintf (stderr, "can't grab pty\n");
- exit (1);
- }
- switch (ftp_pid = fork ())
- {
- case -1:
- perror ("fork");
- exit (1);
- case 0:
- /* child */
- close (ftp_pty);
- close (0);
- close (1);
- close (2);
- setsid ();
- open (tty_name, O_RDWR);
- dup (0);
- dup (0);
-#ifndef HAVE_SGI
- unsetenv ("LANG"); /* need english messages from ftp */
-#endif
- execvp (noauto[0], noauto);
- perror ("execvp");
- exit (1);
- default:
- /* parent */
- break;
- }
- ftp_recv ();
-
- /* initialisation */
- if (passive)
- {
- ftp_send (1, "pass");
- ftp_recv ();
- }
- return;
-}
-
-void
-ftp_send (int argc, ...)
-{
- va_list ap;
- char line[256], *arg;
- int length, i;
-
- va_start (ap, argc);
- memset (line, 0, 256);
- length = 0;
- for (i = 0; i < argc; i++)
- {
- if (i)
- line[length++] = ' ';
- arg = va_arg (ap, char *);
- length += strlen (arg);
- strcat (line, arg);
- }
- line[length++] = '\n';
- va_end (ap);
-
- if (ftp_debug)
- fprintf (stderr, ">> %s", line);
- if (length != write (ftp_pty, line, length))
- {
- fprintf (stderr, "ftp: write error\n");
- exit (1);
- }
-}
-
-int
-ftp_recv ()
-{
- char line[512], *p, *n;
- int length, done, status, ret = 0;
- fd_set set;
-
- for (done = 0; !done;)
- {
- FD_ZERO (&set);
- FD_SET (ftp_pty, &set);
- select (ftp_pty + 1, &set, NULL, NULL, NULL);
-
- switch (length = read (ftp_pty, line, 511))
- {
- case -1:
- perror ("ftp: read error");
- exit (1);
- case 0:
- fprintf (stderr, "ftp: EOF\n");
- exit (1);
- }
- line[length] = 0;
-
- for (p = line; p && *p; p = n)
- {
- /* split into lines */
- if (NULL != (n = strchr (p, '\n'))
- || NULL != (n = strchr (p, '\r')))
- *(n++) = 0;
- else
- n = NULL;
- if (ftp_debug)
- fprintf (stderr, "<< %s\n", p);
-
- /* prompt? */
- if (NULL != strstr (p, "ftp>"))
- {
- done = 1;
- }
-
- /* line dropped ? */
- if (NULL != strstr (p, "closed connection"))
- {
- fprintf (stderr, "ftp: lost connection\n");
- ftp_connected = 0;
- }
- if (NULL != strstr (p, "Not connected"))
- {
- if (ftp_connected)
- fprintf (stderr, "ftp: lost connection\n");
- ftp_connected = 0;
- }
-
- /* status? */
- if (1 == sscanf (p, "%d", &status))
- {
- ret = status;
- }
- }
- }
- return ret;
-}
-
-void
-ftp_connect (char *host, char *user, char *pass, char *dir)
-{
- int delay = 0, status;
-
- // for (;;)
- while(userbreak < 1)
- {
- /* Wiederholungsversuche mit wachsendem Intervall, 10 min max. */
- if (delay)
- {
- fprintf (stderr, "ftp: connect failed, sleeping %d sec\n", delay);
- sleep (delay);
- delay *= 2;
- if (delay > 600)
- delay = 600;
- }
- else
- {
- delay = 5;
- }
-
- /* (re-) connect */
- ftp_send (1, "close");
- ftp_recv ();
- ftp_send (2, "open", host);
- status = ftp_recv ();
- if (230 == status)
- {
- fprintf (stderr, "ftp: connected to %s, login ok\n", host);
- ftp_connected = 1;
- goto login_ok;
- }
- if (220 != status && 530 != status)
- continue;
-
- fprintf (stderr, "ftp: connected to %s\n", host);
- ftp_connected = 1;
-
- /* login */
- ftp_send (3, "user", user, pass);
- if (230 != ftp_recv ())
- {
- if (!ftp_connected)
- continue;
- fprintf (stderr, "ftp: login incorrect\n");
- exit (1);
- }
-
- login_ok:
- fprintf(stderr, "ftp: login successful\n");
- /* set directory */
- ftp_send (2, "cd", dir);
-
- if (250 != ftp_recv ())
- {
- if (!ftp_connected)
- continue;
- fprintf(stderr,"ftp: cd %s failed, ignoring directory path\n",dir);
- }
-
- /* initialisation */
- ftp_send (1, "bin");
- ftp_recv ();
- ftp_send (1, "umask 022");
- ftp_recv ();
-
- /* ok */
- break;
- }
-}
-
-void
-ftp_upload (char *local, char *remote, char *tmp)
-{
- ftp_send (3, "put", local, tmp);
- ftp_recv ();
- ftp_send (3, "rename", tmp, remote);
- ftp_recv ();
-}
-
-void
-ftp_close ()
-{
- if(ftp_connected) ftp_send(1,"quit");
- close(ftp_pty);
- userbreak = 1;
-}
diff --git a/hasciicam/ftp.h b/hasciicam/ftp.h
deleted file mode 100644
index 3b29b94..0000000
--- a/hasciicam/ftp.h
+++ /dev/null
@@ -1,7 +0,0 @@
-extern int ftp_connected;
-extern int ftp_debug;
-
-void ftp_init(int passive);
-void ftp_connect(char *host, char *user, char *pass, char *dir);
-void ftp_upload(char *local, char *remote, char *tmp);
-void ftp_close();
diff --git a/hasciicam/ftplib.c b/hasciicam/ftplib.c
new file mode 100644
index 0000000..9089a5b
--- /dev/null
+++ b/hasciicam/ftplib.c
@@ -0,0 +1,1295 @@
+/***************************************************************************/
+/* */
+/* ftplib.c - callable ftp access routines */
+/* Copyright (C) 1996-2000 Thomas Pfau, pfau@cnj.digex.net */
+/* 73 Catherine Street, South Bound Brook, NJ, 08880 */
+/* */
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Library General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2 of the License, or (at your option) any later version. */
+/* */
+/* This library 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 */
+/* Library General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU Library General Public */
+/* License along with this progam; if not, write to the */
+/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
+/* Boston, MA 02111-1307, USA. */
+/* */
+/***************************************************************************/
+
+#if defined(__unix__) || defined(__VMS)
+#include <unistd.h>
+#endif
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#if defined(__unix__)
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#elif defined(VMS)
+#include <types.h>
+#include <socket.h>
+#include <in.h>
+#include <netdb.h>
+#include <inet.h>
+#elif defined(_WIN32)
+#include <winsock.h>
+#endif
+
+#define BUILDING_LIBRARY
+#include "ftplib.h"
+
+#if defined(_WIN32)
+#define SETSOCKOPT_OPTVAL_TYPE (const char *)
+#else
+#define SETSOCKOPT_OPTVAL_TYPE (void *)
+#endif
+
+#define FTPLIB_BUFSIZ 8192
+#define ACCEPT_TIMEOUT 30
+
+#define FTPLIB_CONTROL 0
+#define FTPLIB_READ 1
+#define FTPLIB_WRITE 2
+
+#if !defined FTPLIB_DEFMODE
+#define FTPLIB_DEFMODE FTPLIB_PASSIVE
+#endif
+
+struct NetBuf {
+ char *cput,*cget;
+ int handle;
+ int cavail,cleft;
+ char *buf;
+ int dir;
+ netbuf *ctrl;
+ netbuf *data;
+ int cmode;
+ struct timeval idletime;
+ FtpCallback idlecb;
+ void *idlearg;
+ int xfered;
+ int cbbytes;
+ int xfered1;
+ char response[256];
+};
+
+static char *version =
+ "ftplib Release 3.1-1 9/16/00, copyright 1996-2000 Thomas Pfau";
+
+GLOBALDEF int ftplib_debug = 0;
+
+#if defined(__unix__) || defined(VMS)
+#define net_read read
+#define net_write write
+#define net_close close
+#elif defined(_WIN32)
+#define net_read(x,y,z) recv(x,y,z,0)
+#define net_write(x,y,z) send(x,y,z,0)
+#define net_close closesocket
+#endif
+
+#if defined(NEED_MEMCCPY)
+/*
+ * VAX C does not supply a memccpy routine so I provide my own
+ */
+void *memccpy(void *dest, const void *src, int c, size_t n)
+{
+ int i=0;
+ const unsigned char *ip=src;
+ unsigned char *op=dest;
+
+ while (i < n)
+ {
+ if ((*op++ = *ip++) == c)
+ break;
+ i++;
+ }
+ if (i == n)
+ return NULL;
+ return op;
+}
+#endif
+#if defined(NEED_STRDUP)
+/*
+ * strdup - return a malloc'ed copy of a string
+ */
+char *strdup(const char *src)
+{
+ int l = strlen(src) + 1;
+ char *dst = malloc(l);
+ if (dst)
+ strcpy(dst,src);
+ return dst;
+}
+#endif
+
+/*
+ * socket_wait - wait for socket to receive or flush data
+ *
+ * return 1 if no user callback, otherwise, return value returned by
+ * user callback
+ */
+static int socket_wait(netbuf *ctl)
+{
+ fd_set fd,*rfd = NULL,*wfd = NULL;
+ struct timeval tv;
+ int rv = 0;
+ if ((ctl->dir == FTPLIB_CONTROL) || (ctl->idlecb == NULL))
+ return 1;
+ if (ctl->dir == FTPLIB_WRITE)
+ wfd = &fd;
+ else
+ rfd = &fd;
+ FD_ZERO(&fd);
+ do
+ {
+ FD_SET(ctl->handle,&fd);
+ tv = ctl->idletime;
+ rv = select(ctl->handle+1, rfd, wfd, NULL, &tv);
+ if (rv == -1)
+ {
+ rv = 0;
+ strncpy(ctl->ctrl->response, strerror(errno),
+ sizeof(ctl->ctrl->response));
+ break;
+ }
+ else if (rv > 0)
+ {
+ rv = 1;
+ break;
+ }
+ }
+ while ((rv = ctl->idlecb(ctl, ctl->xfered, ctl->idlearg)));
+ return rv;
+}
+
+/*
+ * read a line of text
+ *
+ * return -1 on error or bytecount
+ */
+static int readline(char *buf,int max,netbuf *ctl)
+{
+ int x,retval = 0;
+ char *end,*bp=buf;
+ int eof = 0;
+
+ if ((ctl->dir != FTPLIB_CONTROL) && (ctl->dir != FTPLIB_READ))
+ return -1;
+ if (max == 0)
+ return 0;
+ do
+ {
+ if (ctl->cavail > 0)
+ {
+ x = (max >= ctl->cavail) ? ctl->cavail : max-1;
+ end = memccpy(bp,ctl->cget,'\n',x);
+ if (end != NULL)
+ x = end - bp;
+ retval += x;
+ bp += x;
+ *bp = '\0';
+ max -= x;
+ ctl->cget += x;
+ ctl->cavail -= x;
+ if (end != NULL)
+ {
+ bp -= 2;
+ if (strcmp(bp,"\r\n") == 0)
+ {
+ *bp++ = '\n';
+ *bp++ = '\0';
+ --retval;
+ }
+ break;
+ }
+ }
+ if (max == 1)
+ {
+ *buf = '\0';
+ break;
+ }
+ if (ctl->cput == ctl->cget)
+ {
+ ctl->cput = ctl->cget = ctl->buf;
+ ctl->cavail = 0;
+ ctl->cleft = FTPLIB_BUFSIZ;
+ }
+ if (eof)
+ {
+ if (retval == 0)
+ retval = -1;
+ break;
+ }
+ if (!socket_wait(ctl))
+ return retval;
+ if ((x = net_read(ctl->handle,ctl->cput,ctl->cleft)) == -1)
+ {
+ perror("read");
+ retval = -1;
+ break;
+ }
+ if (x == 0)
+ eof = 1;
+ ctl->cleft -= x;
+ ctl->cavail += x;
+ ctl->cput += x;
+ }
+ while (1);
+ return retval;
+}
+
+/*
+ * write lines of text
+ *
+ * return -1 on error or bytecount
+ */
+static int writeline(char *buf, int len, netbuf *nData)
+{
+ int x, nb=0, w;
+ char *ubp = buf, *nbp;
+ char lc=0;
+
+ if (nData->dir != FTPLIB_WRITE)
+ return -1;
+ nbp = nData->buf;
+ for (x=0; x < len; x++)
+ {
+ if ((*ubp == '\n') && (lc != '\r'))
+ {
+ if (nb == FTPLIB_BUFSIZ)
+ {
+ if (!socket_wait(nData))
+ return x;
+ w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
+ if (w != FTPLIB_BUFSIZ)
+ {
+ printf("net_write(1) returned %d, errno = %d\n", w, errno);
+ return(-1);
+ }
+ nb = 0;
+ }
+ nbp[nb++] = '\r';
+ }
+ if (nb == FTPLIB_BUFSIZ)
+ {
+ if (!socket_wait(nData))
+ return x;
+ w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
+ if (w != FTPLIB_BUFSIZ)
+ {
+ printf("net_write(2) returned %d, errno = %d\n", w, errno);
+ return(-1);
+ }
+ nb = 0;
+ }
+ nbp[nb++] = lc = *ubp++;
+ }
+ if (nb)
+ {
+ if (!socket_wait(nData))
+ return x;
+ w = net_write(nData->handle, nbp, nb);
+ if (w != nb)
+ {
+ printf("net_write(3) returned %d, errno = %d\n", w, errno);
+ return(-1);
+ }
+ }
+ return len;
+}
+
+/*
+ * read a response from the server
+ *
+ * return 0 if first char doesn't match
+ * return 1 if first char matches
+ */
+static int readresp(char c, netbuf *nControl)
+{
+ char match[5];
+ if (readline(nControl->response,256,nControl) == -1)
+ {
+ perror("Control socket read failed");
+ return 0;
+ }
+ if (ftplib_debug > 1)
+ fprintf(stderr,"%s",nControl->response);
+ if (nControl->response[3] == '-')
+ {
+ strncpy(match,nControl->response,3);
+ match[3] = ' ';
+ match[4] = '\0';
+ do
+ {
+ if (readline(nControl->response,256,nControl) == -1)
+ {
+ perror("Control socket read failed");
+ return 0;
+ }
+ if (ftplib_debug > 1)
+ fprintf(stderr,"%s",nControl->response);
+ }
+ while (strncmp(nControl->response,match,4));
+ }
+ if (nControl->response[0] == c)
+ return 1;
+ return 0;
+}
+
+/*
+ * FtpInit for stupid operating systems that require it (Windows NT)
+ */
+GLOBALDEF void FtpInit(void)
+{
+#if defined(_WIN32)
+ WORD wVersionRequested;
+ WSADATA wsadata;
+ int err;
+ wVersionRequested = MAKEWORD(1,1);
+ if ((err = WSAStartup(wVersionRequested,&wsadata)) != 0)
+ fprintf(stderr,"Network failed to start: %d\n",err);
+#endif
+}
+
+/*
+ * FtpLastResponse - return a pointer to the last response received
+ */
+GLOBALDEF char *FtpLastResponse(netbuf *nControl)
+{
+ if ((nControl) && (nControl->dir == FTPLIB_CONTROL))
+ return nControl->response;
+ return NULL;
+}
+
+/*
+ * FtpConnect - connect to remote server
+ *
+ * return 1 if connected, 0 if not
+ */
+GLOBALDEF int FtpConnect(const char *host, netbuf **nControl)
+{
+ int sControl;
+ struct sockaddr_in sin;
+ struct hostent *phe;
+ struct servent *pse;
+ int on=1;
+ netbuf *ctrl;
+ char *lhost;
+ char *pnum;
+
+ memset(&sin,0,sizeof(sin));
+ sin.sin_family = AF_INET;
+ lhost = strdup(host);
+ pnum = strchr(lhost,':');
+ if (pnum == NULL)
+ {
+#if defined(VMS)
+ sin.sin_port = htons(21);
+#else
+ if ((pse = getservbyname("ftp","tcp")) == NULL)
+ {
+ perror("getservbyname");
+ return 0;
+ }
+ sin.sin_port = pse->s_port;
+#endif
+ }
+ else
+ {
+ *pnum++ = '\0';
+ if (isdigit(*pnum))
+ sin.sin_port = htons(atoi(pnum));
+ else
+ {
+ pse = getservbyname(pnum,"tcp");
+ sin.sin_port = pse->s_port;
+ }
+ }
+ if ((sin.sin_addr.s_addr = inet_addr(lhost)) == -1)
+ {
+ if ((phe = gethostbyname(lhost)) == NULL)
+ {
+ perror("gethostbyname");
+ return 0;
+ }
+ memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
+ }
+ free(lhost);
+ sControl = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sControl == -1)
+ {
+ perror("socket");
+ return 0;
+ }
+ if (setsockopt(sControl,SOL_SOCKET,SO_REUSEADDR,
+ SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1)
+ {
+ perror("setsockopt");
+ net_close(sControl);
+ return 0;
+ }
+ if (connect(sControl, (struct sockaddr *)&sin, sizeof(sin)) == -1)
+ {
+ perror("connect");
+ net_close(sControl);
+ return 0;
+ }
+ ctrl = calloc(1,sizeof(netbuf));
+ if (ctrl == NULL)
+ {
+ perror("calloc");
+ net_close(sControl);
+ return 0;
+ }
+ ctrl->buf = malloc(FTPLIB_BUFSIZ);
+ if (ctrl->buf == NULL)
+ {
+ perror("calloc");
+ net_close(sControl);
+ free(ctrl);
+ return 0;
+ }
+ ctrl->handle = sControl;
+ ctrl->dir = FTPLIB_CONTROL;
+ ctrl->ctrl = NULL;
+ ctrl->cmode = FTPLIB_DEFMODE;
+ ctrl->idlecb = NULL;
+ ctrl->idletime.tv_sec = ctrl->idletime.tv_usec = 0;
+ ctrl->idlearg = NULL;
+ ctrl->xfered = 0;
+ ctrl->xfered1 = 0;
+ ctrl->cbbytes = 0;
+ if (readresp('2', ctrl) == 0)
+ {
+ net_close(sControl);
+ free(ctrl->buf);
+ free(ctrl);
+ return 0;
+ }
+ *nControl = ctrl;
+ return 1;
+}
+
+/*
+ * FtpOptions - change connection options
+ *
+ * returns 1 if successful, 0 on error
+ */
+GLOBALDEF int FtpOptions(int opt, long val, netbuf *nControl)
+{
+ int v,rv=0;
+ switch (opt)
+ {
+ case FTPLIB_CONNMODE:
+ v = (int) val;
+ if ((v == FTPLIB_PASSIVE) || (v == FTPLIB_PORT))
+ {
+ nControl->cmode = v;
+ rv = 1;
+ }
+ break;
+ case FTPLIB_CALLBACK:
+ nControl->idlecb = (FtpCallback) val;
+ rv = 1;
+ break;
+ case FTPLIB_IDLETIME:
+ v = (int) val;
+ rv = 1;
+ nControl->idletime.tv_sec = v / 1000;
+ nControl->idletime.tv_usec = (v % 1000) * 1000;
+ break;
+ case FTPLIB_CALLBACKARG:
+ rv = 1;
+ nControl->idlearg = (void *) val;
+ break;
+ case FTPLIB_CALLBACKBYTES:
+ rv = 1;
+ nControl->cbbytes = (int) val;
+ break;
+ }
+ return rv;
+}
+
+/*
+ * FtpSendCmd - send a command and wait for expected response
+ *
+ * return 1 if proper response received, 0 otherwise
+ */
+static int FtpSendCmd(const char *cmd, char expresp, netbuf *nControl)
+{
+ char buf[256];
+ if (nControl->dir != FTPLIB_CONTROL)
+ return 0;
+ if (ftplib_debug > 2)
+ fprintf(stderr,"%s\n",cmd);
+ if ((strlen(cmd) + 3) > sizeof(buf))
+ return 0;
+ sprintf(buf,"%s\r\n",cmd);
+ if (net_write(nControl->handle,buf,strlen(buf)) <= 0)
+ {
+ perror("write");
+ return 0;
+ }
+ return readresp(expresp, nControl);
+}
+
+/*
+ * FtpLogin - log in to remote server
+ *
+ * return 1 if logged in, 0 otherwise
+ */
+GLOBALDEF int FtpLogin(const char *user, const char *pass, netbuf *nControl)
+{
+ char tempbuf[64];
+
+ if (((strlen(user) + 7) > sizeof(tempbuf)) ||
+ ((strlen(pass) + 7) > sizeof(tempbuf)))
+ return 0;
+ sprintf(tempbuf,"USER %s",user);
+ if (!FtpSendCmd(tempbuf,'3',nControl))
+ {
+ if (nControl->response[0] == '2')
+ return 1;
+ return 0;
+ }
+ sprintf(tempbuf,"PASS %s",pass);
+ return FtpSendCmd(tempbuf,'2',nControl);
+}
+
+/*
+ * FtpOpenPort - set up data connection
+ *
+ * return 1 if successful, 0 otherwise
+ */
+static int FtpOpenPort(netbuf *nControl, netbuf **nData, int mode, int dir)
+{
+ int sData;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+ } sin;
+ struct linger lng = { 0, 0 };
+ unsigned int l;
+ int on=1;
+ netbuf *ctrl;
+ char *cp;
+ unsigned int v[6];
+ char buf[256];
+
+ if (nControl->dir != FTPLIB_CONTROL)
+ return -1;
+ if ((dir != FTPLIB_READ) && (dir != FTPLIB_WRITE))
+ {
+ sprintf(nControl->response, "Invalid direction %d\n", dir);
+ return -1;
+ }
+ if ((mode != FTPLIB_ASCII) && (mode != FTPLIB_IMAGE))
+ {
+ sprintf(nControl->response, "Invalid mode %c\n", mode);
+ return -1;
+ }
+ l = sizeof(sin);
+ if (nControl->cmode == FTPLIB_PASSIVE)
+ {
+ memset(&sin, 0, l);
+ sin.in.sin_family = AF_INET;
+ if (!FtpSendCmd("PASV",'2',nControl))
+ return -1;
+ cp = strchr(nControl->response,'(');
+ if (cp == NULL)
+ return -1;
+ cp++;
+ sscanf(cp,"%u,%u,%u,%u,%u,%u",&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]);
+ sin.sa.sa_data[2] = v[2];
+ sin.sa.sa_data[3] = v[3];
+ sin.sa.sa_data[4] = v[4];
+ sin.sa.sa_data[5] = v[5];
+ sin.sa.sa_data[0] = v[0];
+ sin.sa.sa_data[1] = v[1];
+ }
+ else
+ {
+ if (getsockname(nControl->handle, &sin.sa, &l) < 0)
+ {
+ perror("getsockname");
+ return 0;
+ }
+ }
+ sData = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
+ if (sData == -1)
+ {
+ perror("socket");
+ return -1;
+ }
+ if (setsockopt(sData,SOL_SOCKET,SO_REUSEADDR,
+ SETSOCKOPT_OPTVAL_TYPE &on,sizeof(on)) == -1)
+ {
+ perror("setsockopt");
+ net_close(sData);
+ return -1;
+ }
+ if (setsockopt(sData,SOL_SOCKET,SO_LINGER,
+ SETSOCKOPT_OPTVAL_TYPE &lng,sizeof(lng)) == -1)
+ {
+ perror("setsockopt");
+ net_close(sData);
+ return -1;
+ }
+ if (nControl->cmode == FTPLIB_PASSIVE)
+ {
+ if (connect(sData, &sin.sa, sizeof(sin.sa)) == -1)
+ {
+ perror("connect");
+ net_close(sData);
+ return -1;
+ }
+ }
+ else
+ {
+ sin.in.sin_port = 0;
+ if (bind(sData, &sin.sa, sizeof(sin)) == -1)
+ {
+ perror("bind");
+ net_close(sData);
+ return 0;
+ }
+ if (listen(sData, 1) < 0)
+ {
+ perror("listen");
+ net_close(sData);
+ return 0;
+ }
+ if (getsockname(sData, &sin.sa, &l) < 0)
+ return 0;
+ sprintf(buf, "PORT %d,%d,%d,%d,%d,%d",
+ (unsigned char) sin.sa.sa_data[2],
+ (unsigned char) sin.sa.sa_data[3],
+ (unsigned char) sin.sa.sa_data[4],
+ (unsigned char) sin.sa.sa_data[5],
+ (unsigned char) sin.sa.sa_data[0],
+ (unsigned char) sin.sa.sa_data[1]);
+ if (!FtpSendCmd(buf,'2',nControl))
+ {
+ net_close(sData);
+ return 0;
+ }
+ }
+ ctrl = calloc(1,sizeof(netbuf));
+ if (ctrl == NULL)
+ {
+ perror("calloc");
+ net_close(sData);
+ return -1;
+ }
+ if ((mode == 'A') && ((ctrl->buf = malloc(FTPLIB_BUFSIZ)) == NULL))
+ {
+ perror("calloc");
+ net_close(sData);
+ free(ctrl);
+ return -1;
+ }
+ ctrl->handle = sData;
+ ctrl->dir = dir;
+ ctrl->idletime = nControl->idletime;
+ ctrl->idlearg = nControl->idlearg;
+ ctrl->xfered = 0;
+ ctrl->xfered1 = 0;
+ ctrl->cbbytes = nControl->cbbytes;
+ if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec || ctrl->cbbytes)
+ ctrl->idlecb = nControl->idlecb;
+ else
+ ctrl->idlecb = NULL;
+ *nData = ctrl;
+ return 1;
+}
+
+/*
+ * FtpAcceptConnection - accept connection from server
+ *
+ * return 1 if successful, 0 otherwise
+ */
+static int FtpAcceptConnection(netbuf *nData, netbuf *nControl)
+{
+ int sData;
+ struct sockaddr addr;
+ unsigned int l;
+ int i;
+ struct timeval tv;
+ fd_set mask;
+ int rv;
+
+ FD_ZERO(&mask);
+ FD_SET(nControl->handle, &mask);
+ FD_SET(nData->handle, &mask);
+ tv.tv_usec = 0;
+ tv.tv_sec = ACCEPT_TIMEOUT;
+ i = nControl->handle;
+ if (i < nData->handle)
+ i = nData->handle;
+ i = select(i+1, &mask, NULL, NULL, &tv);
+ if (i == -1)
+ {
+ strncpy(nControl->response, strerror(errno),
+ sizeof(nControl->response));
+ net_close(nData->handle);
+ nData->handle = 0;
+ rv = 0;
+ }
+ else if (i == 0)
+ {
+ strcpy(nControl->response, "timed out waiting for connection");
+ net_close(nData->handle);
+ nData->handle = 0;
+ rv = 0;
+ }
+ else
+ {
+ if (FD_ISSET(nData->handle, &mask))
+ {
+ l = sizeof(addr);
+ sData = accept(nData->handle, &addr, &l);
+ i = errno;
+ net_close(nData->handle);
+ if (sData > 0)
+ {
+ rv = 1;
+ nData->handle = sData;
+ }
+ else
+ {
+ strncpy(nControl->response, strerror(i),
+ sizeof(nControl->response));
+ nData->handle = 0;
+ rv = 0;
+ }
+ }
+ else if (FD_ISSET(nControl->handle, &mask))
+ {
+ net_close(nData->handle);
+ nData->handle = 0;
+ readresp('2', nControl);
+ rv = 0;
+ }
+ }
+ return rv;
+}
+
+/*
+ * FtpAccess - return a handle for a data stream
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl,
+ netbuf **nData)
+{
+ char buf[256];
+ int dir;
+ if ((path == NULL) &&
+ ((typ == FTPLIB_FILE_WRITE) || (typ == FTPLIB_FILE_READ)))
+ {
+ sprintf(nControl->response,
+ "Missing path argument for file transfer\n");
+ return 0;
+ }
+ sprintf(buf, "TYPE %c", mode);
+ if (!FtpSendCmd(buf, '2', nControl))
+ return 0;
+ switch (typ)
+ {
+ case FTPLIB_DIR:
+ strcpy(buf,"NLST");
+ dir = FTPLIB_READ;
+ break;
+ case FTPLIB_DIR_VERBOSE:
+ strcpy(buf,"LIST");
+ dir = FTPLIB_READ;
+ break;
+ case FTPLIB_FILE_READ:
+ strcpy(buf,"RETR");
+ dir = FTPLIB_READ;
+ break;
+ case FTPLIB_FILE_WRITE:
+ strcpy(buf,"STOR");
+ dir = FTPLIB_WRITE;
+ break;
+ default:
+ sprintf(nControl->response, "Invalid open type %d\n", typ);
+ return 0;
+ }
+ if (path != NULL)
+ {
+ int i = strlen(buf);
+ buf[i++] = ' ';
+ if ((strlen(path) + i) >= sizeof(buf))
+ return 0;
+ strcpy(&buf[i],path);
+ }
+ if (FtpOpenPort(nControl, nData, mode, dir) == -1)
+ return 0;
+ if (!FtpSendCmd(buf, '1', nControl))
+ {
+ FtpClose(*nData);
+ *nData = NULL;
+ return 0;
+ }
+ (*nData)->ctrl = nControl;
+ nControl->data = *nData;
+ if (nControl->cmode == FTPLIB_PORT)
+ {
+ if (!FtpAcceptConnection(*nData,nControl))
+ {
+ FtpClose(*nData);
+ *nData = NULL;
+ nControl->data = NULL;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * FtpRead - read from a data connection
+ */
+GLOBALDEF int FtpRead(void *buf, int max, netbuf *nData)
+{
+ int i;
+ if (nData->dir != FTPLIB_READ)
+ return 0;
+ if (nData->buf)
+ i = readline(buf, max, nData);
+ else
+ {
+ i = socket_wait(nData);
+ if (i != 1)
+ return 0;
+ i = net_read(nData->handle, buf, max);
+ }
+ if (i == -1)
+ return 0;
+ nData->xfered += i;
+ if (nData->idlecb && nData->cbbytes)
+ {
+ nData->xfered1 += i;
+ if (nData->xfered1 > nData->cbbytes)
+ {
+ if (nData->idlecb(nData, nData->xfered, nData->idlearg) == 0)
+ return 0;
+ nData->xfered1 = 0;
+ }
+ }
+ return i;
+}
+
+/*
+ * FtpWrite - write to a data connection
+ */
+GLOBALDEF int FtpWrite(void *buf, int len, netbuf *nData)
+{
+ int i;
+ if (nData->dir != FTPLIB_WRITE)
+ return 0;
+ if (nData->buf)
+ i = writeline(buf, len, nData);
+ else
+ {
+ socket_wait(nData);
+ i = net_write(nData->handle, buf, len);
+ }
+ if (i == -1)
+ return 0;
+ nData->xfered += i;
+ if (nData->idlecb && nData->cbbytes)
+ {
+ nData->xfered1 += i;
+ if (nData->xfered1 > nData->cbbytes)
+ {
+ nData->idlecb(nData, nData->xfered, nData->idlearg);
+ nData->xfered1 = 0;
+ }
+ }
+ return i;
+}
+
+/*
+ * FtpClose - close a data connection
+ */
+GLOBALDEF int FtpClose(netbuf *nData)
+{
+ netbuf *ctrl;
+ switch (nData->dir)
+ {
+ case FTPLIB_WRITE:
+ /* potential problem - if buffer flush fails, how to notify user? */
+ if (nData->buf != NULL)
+ writeline(NULL, 0, nData);
+ case FTPLIB_READ:
+ if (nData->buf)
+ free(nData->buf);
+ shutdown(nData->handle,2);
+ net_close(nData->handle);
+ ctrl = nData->ctrl;
+ free(nData);
+ if (ctrl)
+ {
+ ctrl->data = NULL;
+ return(readresp('2', ctrl));
+ }
+ return 1;
+ case FTPLIB_CONTROL:
+ if (nData->data)
+ {
+ nData->ctrl = NULL;
+ FtpClose(nData);
+ }
+ net_close(nData->handle);
+ free(nData);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * FtpSite - send a SITE command
+ *
+ * return 1 if command successful, 0 otherwise
+ */
+GLOBALDEF int FtpSite(const char *cmd, netbuf *nControl)
+{
+ char buf[256];
+
+ if ((strlen(cmd) + 7) > sizeof(buf))
+ return 0;
+ sprintf(buf,"SITE %s",cmd);
+ if (!FtpSendCmd(buf,'2',nControl))
+ return 0;
+ return 1;
+}
+
+/*
+ * FtpSysType - send a SYST command
+ *
+ * Fills in the user buffer with the remote system type. If more
+ * information from the response is required, the user can parse
+ * it out of the response buffer returned by FtpLastResponse().
+ *
+ * return 1 if command successful, 0 otherwise
+ */
+GLOBALDEF int FtpSysType(char *buf, int max, netbuf *nControl)
+{
+ int l = max;
+ char *b = buf;
+ char *s;
+ if (!FtpSendCmd("SYST",'2',nControl))
+ return 0;
+ s = &nControl->response[4];
+ while ((--l) && (*s != ' '))
+ *b++ = *s++;
+ *b++ = '\0';
+ return 1;
+}
+
+/*
+ * FtpMkdir - create a directory at server
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpMkdir(const char *path, netbuf *nControl)
+{
+ char buf[256];
+
+ if ((strlen(path) + 6) > sizeof(buf))
+ return 0;
+ sprintf(buf,"MKD %s",path);
+ if (!FtpSendCmd(buf,'2', nControl))
+ return 0;
+ return 1;
+}
+
+/*
+ * FtpChdir - change path at remote
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpChdir(const char *path, netbuf *nControl)
+{
+ char buf[256];
+
+ if ((strlen(path) + 6) > sizeof(buf))
+ return 0;
+ sprintf(buf,"CWD %s",path);
+ if (!FtpSendCmd(buf,'2',nControl))
+ return 0;
+ return 1;
+}
+
+/*
+ * FtpCDUp - move to parent directory at remote
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpCDUp(netbuf *nControl)
+{
+ if (!FtpSendCmd("CDUP",'2',nControl))
+ return 0;
+ return 1;
+}
+
+/*
+ * FtpRmdir - remove directory at remote
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpRmdir(const char *path, netbuf *nControl)
+{
+ char buf[256];
+
+ if ((strlen(path) + 6) > sizeof(buf))
+ return 0;
+ sprintf(buf,"RMD %s",path);
+ if (!FtpSendCmd(buf,'2',nControl))
+ return 0;
+ return 1;
+}
+
+/*
+ * FtpPwd - get working directory at remote
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpPwd(char *path, int max, netbuf *nControl)
+{
+ int l = max;
+ char *b = path;
+ char *s;
+ if (!FtpSendCmd("PWD",'2',nControl))
+ return 0;
+ s = strchr(nControl->response, '"');
+ if (s == NULL)
+ return 0;
+ s++;
+ while ((--l) && (*s) && (*s != '"'))
+ *b++ = *s++;
+ *b++ = '\0';
+ return 1;
+}
+
+/*
+ * FtpXfer - issue a command and transfer data
+ *
+ * return 1 if successful, 0 otherwise
+ */
+static int FtpXfer(const char *localfile, const char *path,
+ netbuf *nControl, int typ, int mode)
+{
+ int l,c;
+ char *dbuf;
+ FILE *local = NULL;
+ netbuf *nData;
+ int rv=1;
+
+ if (localfile != NULL)
+ {
+ char ac[4] = "w";
+ if (typ == FTPLIB_FILE_WRITE)
+ ac[0] = 'r';
+ if (mode == FTPLIB_IMAGE)
+ ac[1] = 'b';
+ local = fopen(localfile, ac);
+ if (local == NULL)
+ {
+ strncpy(nControl->response, strerror(errno),
+ sizeof(nControl->response));
+ return 0;
+ }
+ }
+ if (local == NULL)
+ local = (typ == FTPLIB_FILE_WRITE) ? stdin : stdout;
+ if (!FtpAccess(path, typ, mode, nControl, &nData))
+ return 0;
+ dbuf = malloc(FTPLIB_BUFSIZ);
+ if (typ == FTPLIB_FILE_WRITE)
+ {
+ while ((l = fread(dbuf, 1, FTPLIB_BUFSIZ, local)) > 0)
+ if ((c = FtpWrite(dbuf, l, nData)) < l)
+ {
+ printf("short write: passed %d, wrote %d\n", l, c);
+ rv = 0;
+ break;
+ }
+ }
+ else
+ {
+ while ((l = FtpRead(dbuf, FTPLIB_BUFSIZ, nData)) > 0)
+ if (fwrite(dbuf, 1, l, local) <= 0)
+ {
+ perror("localfile write");
+ rv = 0;
+ break;
+ }
+ }
+ free(dbuf);
+ fflush(local);
+ if (localfile != NULL)
+ fclose(local);
+ FtpClose(nData);
+ return rv;
+}
+
+/*
+ * FtpNlst - issue an NLST command and write response to output
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpNlst(const char *outputfile, const char *path,
+ netbuf *nControl)
+{
+ return FtpXfer(outputfile, path, nControl, FTPLIB_DIR, FTPLIB_ASCII);
+}
+
+/*
+ * FtpDir - issue a LIST command and write response to output
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpDir(const char *outputfile, const char *path, netbuf *nControl)
+{
+ return FtpXfer(outputfile, path, nControl, FTPLIB_DIR_VERBOSE, FTPLIB_ASCII);
+}
+
+/*
+ * FtpSize - determine the size of a remote file
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpSize(const char *path, int *size, char mode, netbuf *nControl)
+{
+ char cmd[256];
+ int resp,sz,rv=1;
+
+ if ((strlen(path) + 7) > sizeof(cmd))
+ return 0;
+ sprintf(cmd, "TYPE %c", mode);
+ if (!FtpSendCmd(cmd, '2', nControl))
+ return 0;
+ sprintf(cmd,"SIZE %s",path);
+ if (!FtpSendCmd(cmd,'2',nControl))
+ rv = 0;
+ else
+ {
+ if (sscanf(nControl->response, "%d %d", &resp, &sz) == 2)
+ *size = sz;
+ else
+ rv = 0;
+ }
+ return rv;
+}
+
+/*
+ * FtpModDate - determine the modification date of a remote file
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpModDate(const char *path, char *dt, int max, netbuf *nControl)
+{
+ char buf[256];
+ int rv = 1;
+
+ if ((strlen(path) + 7) > sizeof(buf))
+ return 0;
+ sprintf(buf,"MDTM %s",path);
+ if (!FtpSendCmd(buf,'2',nControl))
+ rv = 0;
+ else
+ strncpy(dt, &nControl->response[4], max);
+ return rv;
+}
+
+/*
+ * FtpGet - issue a GET command and write received data to output
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpGet(const char *outputfile, const char *path,
+ char mode, netbuf *nControl)
+{
+ return FtpXfer(outputfile, path, nControl, FTPLIB_FILE_READ, mode);
+}
+
+/*
+ * FtpPut - issue a PUT command and send data from input
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpPut(const char *inputfile, const char *path, char mode,
+ netbuf *nControl)
+{
+ return FtpXfer(inputfile, path, nControl, FTPLIB_FILE_WRITE, mode);
+}
+
+/*
+ * FtpRename - rename a file at remote
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpRename(const char *src, const char *dst, netbuf *nControl)
+{
+ char cmd[256];
+
+ if (((strlen(src) + 7) > sizeof(cmd)) ||
+ ((strlen(dst) + 7) > sizeof(cmd)))
+ return 0;
+ sprintf(cmd,"RNFR %s",src);
+ if (!FtpSendCmd(cmd,'3',nControl))
+ return 0;
+ sprintf(cmd,"RNTO %s",dst);
+ if (!FtpSendCmd(cmd,'2',nControl))
+ return 0;
+ return 1;
+}
+
+/*
+ * FtpDelete - delete a file at remote
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF int FtpDelete(const char *fnm, netbuf *nControl)
+{
+ char cmd[256];
+
+ if ((strlen(fnm) + 7) > sizeof(cmd))
+ return 0;
+ sprintf(cmd,"DELE %s",fnm);
+ if (!FtpSendCmd(cmd,'2', nControl))
+ return 0;
+ return 1;
+}
+
+/*
+ * FtpQuit - disconnect from remote
+ *
+ * return 1 if successful, 0 otherwise
+ */
+GLOBALDEF void FtpQuit(netbuf *nControl)
+{
+ if (nControl->dir != FTPLIB_CONTROL)
+ return;
+ FtpSendCmd("QUIT",'2',nControl);
+ net_close(nControl->handle);
+ free(nControl->buf);
+ free(nControl);
+}
diff --git a/hasciicam/ftplib.h b/hasciicam/ftplib.h
new file mode 100644
index 0000000..c281b72
--- /dev/null
+++ b/hasciicam/ftplib.h
@@ -0,0 +1,125 @@
+/***************************************************************************/
+/* */
+/* ftplib.h - header file for callable ftp access routines */
+/* Copyright (C) 1996, 1997 Thomas Pfau, pfau@cnj.digex.net */
+/* 73 Catherine Street, South Bound Brook, NJ, 08880 */
+/* */
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Library General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2 of the License, or (at your option) any later version. */
+/* */
+/* This library 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 */
+/* Library General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU Library General Public */
+/* License along with this progam; if not, write to the */
+/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
+/* Boston, MA 02111-1307, USA. */
+/* */
+/***************************************************************************/
+
+#if !defined(__FTPLIB_H)
+#define __FTPLIB_H
+
+#if defined(__unix__) || defined(VMS)
+#define GLOBALDEF
+#define GLOBALREF extern
+#elif defined(_WIN32)
+#if defined BUILDING_LIBRARY
+#define GLOBALDEF __declspec(dllexport)
+#define GLOBALREF __declspec(dllexport)
+#else
+#define GLOBALREF __declspec(dllimport)
+#endif
+#endif
+
+/* FtpAccess() type codes */
+#define FTPLIB_DIR 1
+#define FTPLIB_DIR_VERBOSE 2
+#define FTPLIB_FILE_READ 3
+#define FTPLIB_FILE_WRITE 4
+
+/* FtpAccess() mode codes */
+#define FTPLIB_ASCII 'A'
+#define FTPLIB_IMAGE 'I'
+#define FTPLIB_TEXT FTPLIB_ASCII
+#define FTPLIB_BINARY FTPLIB_IMAGE
+
+/* connection modes */
+#define FTPLIB_PASSIVE 1
+#define FTPLIB_PORT 2
+
+/* connection option names */
+#define FTPLIB_CONNMODE 1
+#define FTPLIB_CALLBACK 2
+#define FTPLIB_IDLETIME 3
+#define FTPLIB_CALLBACKARG 4
+#define FTPLIB_CALLBACKBYTES 5
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct NetBuf netbuf;
+typedef int (*FtpCallback)(netbuf *nControl, int xfered, void *arg);
+
+/* v1 compatibility stuff */
+#if !defined(_FTPLIB_NO_COMPAT)
+netbuf *DefaultNetbuf;
+
+#define ftplib_lastresp FtpLastResponse(DefaultNetbuf)
+#define ftpInit FtpInit
+#define ftpOpen(x) FtpConnect(x, &DefaultNetbuf)
+#define ftpLogin(x,y) FtpLogin(x, y, DefaultNetbuf)
+#define ftpSite(x) FtpSite(x, DefaultNetbuf)
+#define ftpMkdir(x) FtpMkdir(x, DefaultNetbuf)
+#define ftpChdir(x) FtpChdir(x, DefaultNetbuf)
+#define ftpRmdir(x) FtpRmdir(x, DefaultNetbuf)
+#define ftpNlst(x, y) FtpNlst(x, y, DefaultNetbuf)
+#define ftpDir(x, y) FtpDir(x, y, DefaultNetbuf)
+#define ftpGet(x, y, z) FtpGet(x, y, z, DefaultNetbuf)
+#define ftpPut(x, y, z) FtpPut(x, y, z, DefaultNetbuf)
+#define ftpRename(x, y) FtpRename(x, y, DefaultNetbuf)
+#define ftpDelete(x) FtpDelete(x, DefaultNetbuf)
+#define ftpQuit() FtpQuit(DefaultNetbuf)
+#endif /* (_FTPLIB_NO_COMPAT) */
+/* end v1 compatibility stuff */
+
+GLOBALREF int ftplib_debug;
+GLOBALREF void FtpInit(void);
+GLOBALREF char *FtpLastResponse(netbuf *nControl);
+GLOBALREF int FtpConnect(const char *host, netbuf **nControl);
+GLOBALREF int FtpOptions(int opt, long val, netbuf *nControl);
+GLOBALREF int FtpLogin(const char *user, const char *pass, netbuf *nControl);
+GLOBALREF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl,
+ netbuf **nData);
+GLOBALREF int FtpRead(void *buf, int max, netbuf *nData);
+GLOBALREF int FtpWrite(void *buf, int len, netbuf *nData);
+GLOBALREF int FtpClose(netbuf *nData);
+GLOBALREF int FtpSite(const char *cmd, netbuf *nControl);
+GLOBALREF int FtpSysType(char *buf, int max, netbuf *nControl);
+GLOBALREF int FtpMkdir(const char *path, netbuf *nControl);
+GLOBALREF int FtpChdir(const char *path, netbuf *nControl);
+GLOBALREF int FtpCDUp(netbuf *nControl);
+GLOBALREF int FtpRmdir(const char *path, netbuf *nControl);
+GLOBALREF int FtpPwd(char *path, int max, netbuf *nControl);
+GLOBALREF int FtpNlst(const char *output, const char *path, netbuf *nControl);
+GLOBALREF int FtpDir(const char *output, const char *path, netbuf *nControl);
+GLOBALREF int FtpSize(const char *path, int *size, char mode, netbuf *nControl);
+GLOBALREF int FtpModDate(const char *path, char *dt, int max, netbuf *nControl);
+GLOBALREF int FtpGet(const char *output, const char *path, char mode,
+ netbuf *nControl);
+GLOBALREF int FtpPut(const char *input, const char *path, char mode,
+ netbuf *nControl);
+GLOBALREF int FtpRename(const char *src, const char *dst, netbuf *nControl);
+GLOBALREF int FtpDelete(const char *fnm, netbuf *nControl);
+GLOBALREF void FtpQuit(netbuf *nControl);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* __FTPLIB_H */
diff --git a/hasciicam/hasciicam.c b/hasciicam/hasciicam.c
index f422f03..812546a 100644
--- a/hasciicam/hasciicam.c
+++ b/hasciicam/hasciicam.c
@@ -42,7 +42,7 @@
#include <config.h>
#include <aalib.h>
-#include <ftp.h>
+#include <ftplib.h>
/* hasciicam modes */
#define LIVE 0
@@ -59,7 +59,7 @@ char *version =
char *help =
/* "\x1B" "c" <--- SCREEN CLEANING ESCAPE CODE
why here? just a reminder for a shamanic secret told by bernie@codewiz.org */
-"Usage: hasciicam [options]\n"
+"Usage: hasciicam [options] [rendering options] [aalib options]\n"
"options:\n"
"-h --help this help\n"
"-H --aahelp aalib complete help\n"
@@ -71,7 +71,7 @@ char *help =
"-n --norm norm: pal|ntsc|secam|auto - default auto\n"
"-s --size ascii image size WxH - default 96x72\n"
"-o --aafile dumped file - default hasciicam.[txt|html]\n"
-"-f --ftp ie: user@ftp.host.it:/dir - default none\n"
+"-f --ftp ie: [$]user%pass@host:dir - default none\n"
"-D --daemon run in background - default foregrond\n"
"-U --uid setuid (int) - default current\n"
"-G --gid setgid (int) - default current\n"
@@ -152,6 +152,7 @@ char ftp_host[256];
char ftp_dir[256];
char ftp_pass[256];
int ftp_passive;
+netbuf *ftpconn = NULL;
int uid = -1;
int gid = -1;
@@ -160,6 +161,7 @@ int gid = -1;
unsigned char *image = NULL; /* mmapped */
char aafile[256];
+
/* declare the sighandler */
void quitproc (int Sig);
volatile sig_atomic_t userbreak;
@@ -211,7 +213,6 @@ int palette;
unsigned char *grey;
int YtoRGB[256];
-
void YUV422_to_grey(unsigned char *src, unsigned char *dst, int w, int h) {
int c,cc;
for (c=0,cc=0;c<vid_geo.size;c++,cc+=2)
@@ -412,6 +413,8 @@ config_init (int argc, char *argv[]) {
aa_geo.bright = 50;
aa_geo.contrast = 10;
aa_geo.gamma = 10;
+
+ ftp_passive = 0;
do {
res = getopt_long (argc, argv, short_options, long_options, NULL);
@@ -570,43 +573,41 @@ config_init (int argc, char *argv[]) {
}
if (useftp) {
+ /* i have to say i'm quite proud of the parsers i write :) */
char *p, *pp;
- p = ftp;
+ p = pp = ftp;
+ /* exclamation at the beginning for passive mode */
+ if(*p == ':') { ftp_passive = 1; p++; pp++; }
+
+ /* get the user and check if a password has been specified */
while (*p != '@') {
- if ((ftp - p) < 32)
- p++;
+ if(*p == '%') { /* pass found, get it */
+ *p = '\0'; strncpy(ftp_pass,pp,256);
+ pp = p+1;
+ }
+ if ((p - pp) < 256) p++;
else {
fprintf (stderr,"Error: malformed ftp command: %s\n", ftp);
- exit (0);
- }
- }
- *p = '\0';
- strncpy(ftp_user,ftp,256);
- p++;
- pp = p;
+ exit (0); }
+ } /* here we have the username */
+ *p = '\0'; strncpy(ftp_user,pp,256);
+ p++; pp = p;
while (*p != ':') {
- if ((pp - p) < 64)
- p++;
+ if ((pp - p) < 256) p++;
else {
fprintf (stderr,"Error: malformed ftp command: %s\n", ftp);
- exit (0);
- }
- }
-
- *p = '\0';
- strncpy(ftp_host,pp,256);
- p++;
- pp = p;
-
- while (*p != '\0') {
- if ((pp - p) < 64)
- p++;
+ exit (0); }
+ } /* here the host */
+ *p = '\0'; strncpy(ftp_host,pp,256);
+ p++; pp = p;
+
+ while (*p != '\0' && *p != '\n') {
+ if ((pp - p) < 256) p++;
else {
fprintf (stderr,"Error: malformed ftp command: %s\n", ftp);
- exit (0);
- }
+ exit (0); }
}
if((pp-p)==0) strcpy(ftp_dir,".");
else strncpy(ftp_dir,pp,256);
@@ -635,10 +636,12 @@ main (int argc, char **argv) {
/* initialize aalib default params */
memcpy (&ascii_hwparms, &aa_defparams, sizeof (struct aa_hardware_params));
ascii_rndparms = aa_getrenderparams();
+ // memcpy (&ascii_rndparms,&aa_defrenderparams,sizeof(struct aa_renderparams));
- /* gathering line commands */
+ /* gathering aalib commandline options */
aa_parseoptions (&ascii_hwparms, ascii_rndparms, &argc, argv);
+ /* and hasciicam options */
config_init (argc, argv);
/* detect and init video device */
@@ -668,8 +671,6 @@ main (int argc, char **argv) {
ascii_save.file = NULL;
fprintf (stderr, "using HTML mode dumping to file %s\n", aafile);
- if (useftp)
- fprintf (stderr, " ftp-pushing on %s%s\n", ftp_host, ftp_dir);
break;
case TEXT:
@@ -678,8 +679,6 @@ main (int argc, char **argv) {
ascii_save.file = NULL;
fprintf (stderr, "using TEXT mode dumping to file %s\n", aafile);
- if (useftp)
- fprintf (stderr, " ftp-pushing on ftp://%s%s\n", ftp_host, ftp_dir);
break;
@@ -700,22 +699,41 @@ main (int argc, char **argv) {
exit(-1);
}
-/* ftp init *//* untested with new code changes */
- if (useftp)
+ while (useftp)
{
char temp[160];
- ftp_init (0);
- sprintf (temp, "password for %s@%s : ", ftp_user, ftp_host);
- strncpy(ftp_pass, getpass(temp), 256);
- ftp_connect (ftp_host, ftp_user, ftp_pass, ftp_dir);
+ fprintf (stderr, "ftp push on ftp://%s@%s:%s\n", ftp_user, ftp_host, ftp_dir);
+
+ FtpInit();
+ if(!FtpConnect(ftp_host,&ftpconn)) {
+ fprintf(stderr,"Unable to connect to host %s\n", ftp_host);
+ useftp = 0; break;
+ }
+ if(ftp_passive)
+ if(!FtpOptions(FTPLIB_CONNMODE,FTPLIB_PASSIVE,ftpconn)) {
+ fprintf(stderr,"Unable to activate passive mode: %s\n",FtpLastResponse(ftpconn));
+ useftp = 0; break;
+ }
+ if(!strchr(ftp,'%')) {
+ sprintf (temp, "password for %s@%s : ", ftp_user, ftp_host);
+ strncpy(ftp_pass, getpass(temp), 256);
+ }
+ if(!FtpLogin(ftp_user, ftp_pass, ftpconn)) {
+ fprintf(stderr,"Login Failure: %s\n",FtpLastResponse(ftpconn));
+ useftp = 0; break;
+ }
+ if(!FtpChdir(ftp_dir,ftpconn)) {
+ fprintf(stderr,"Change directory failed: %s\n",FtpLastResponse(ftpconn));
+ useftp = 0; break;
+ }
+ break;
}
- /* setting ascii rendering parameters */
- // memcpy(&ascii_rndparms,&aa_defrenderparams,sizeof(struct aa_renderparams));
ascii_rndparms->bright = aa_geo.bright;
ascii_rndparms->contrast = aa_geo.contrast;
ascii_rndparms->gamma = aa_geo.gamma;
+ // those are left to be setted by aalib options
// ascii_rndparms->dither = AA_FLOYD_S;
// ascii_rndparms->inversion = invert;
// ascii_rndparms->randomval = 0;
@@ -732,27 +750,33 @@ main (int argc, char **argv) {
memcpy (aa_image (ascii_context), grey, vid_geo.size);
aa_render (ascii_context, ascii_rndparms, 0, 0,
vid_geo.w,vid_geo.h);
- // aa_scrwidth(ascii_context), aa_scrheight(ascii_context));
aa_flush (ascii_context);
if (useftp) {
- if (!ftp_connected)
- ftp_connect (ftp_host, ftp_user, ftp_pass, ftp_dir);
+ // if (!ftp_connected)
+ // ftp_connect (ftp_host, ftp_user, ftp_pass, ftp_dir);
/* scolopendro is the tmp file being renamed
it is called so for hystorical reasons */
- ftp_upload (aafile, aafile, "scolopendro");
+ // ftp_upload (aafile, aafile, "scolopendro");
+ if(!FtpPut(aafile,"scolopendro",FTPLIB_ASCII,ftpconn))
+ fprintf(stderr,"Error in ftp put: %s\n",FtpLastResponse(ftpconn));
+ if(!FtpRename("scolopendro",aafile,ftpconn))
+ fprintf(stderr,"Error in ftp rename %s\n",FtpLastResponse(ftpconn));
}
if (mode != LIVE) sleep (refresh);
}
/* CLEAN EXIT */
+
+ if(useftp)
+ FtpClose(ftpconn);
aa_close(ascii_context);
// free(ascii_rndparms);
free (grey);
-
+
if (dev > 0) close (dev);
if (image != NULL)
@@ -768,7 +792,7 @@ quitproc (int Sig)
{
fprintf (stderr, "interrupt caught, exiting.\n");
- ftp_close();
+
userbreak = 1;
}