Subject: bin/10019: command line upload for ftp(1)
To: None <gnats-bugs@gnats.netbsd.org>
From: None <sab@ansic.net>
List: netbsd-bugs
Date: 04/30/2000 07:59:15
>Number:         10019
>Category:       bin
>Synopsis:       uploading files to ftp servers without using ftp interactivly
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Apr 30 08:00:01 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Scott Aaron Bamford
>Release:        NetBSD-current sup'd 30 April 2000
>Organization:
                              ("`-''-/").___..--''"`-._
 ------------------------------ `6_6  )   `-.  (     ).`-.__.`)
         sab@ansic.net |        (_Y_.)'  ._   )  `._ `. ``-..-'
  sab@zeekuschrist.com |      _..`--'_..-_/  /--'_.' ,'
 --------------------------- (il),-''  (li),'  ((!.-' ----
>Environment:
	
>Description:
	
Most of my use of ftp is to upload files to remote sites.  This patch adds
a ftp [-u url] file [...] option to ftp(1) to suport uploading of files
from the commandline.

usage: ftp -u ftp://some.address/incoming/ *.c
       ftp -u some.address:incoming/newfilename oldfilename

adds autoput.c, and changes Makefile, main.c, ftp_var.h and ftp.1

>How-To-Repeat:
	
>Fix:
	

diff -urN /usr/src/usr.bin/ftp/Makefile ftp/Makefile
--- /usr/src/usr.bin/ftp/Makefile	Sun Dec 12 12:18:36 1999
+++ ftp/Makefile	Sun Apr 30 15:12:40 2000
@@ -2,8 +2,8 @@
 #	from: @(#)Makefile	8.2 (Berkeley) 4/3/94
 
 PROG=	ftp
-SRCS=	cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c main.c ruserpass.c \
-	util.c
+SRCS=	autoput.c cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c main.c \
+	ruserpass.c util.c
 
 # Uncomment the following to provide defaults for gate-ftp operation
 #
diff -urN /usr/src/usr.bin/ftp/autoput.c ftp/autoput.c
--- /usr/src/usr.bin/ftp/autoput.c	Thu Jan  1 01:00:00 1970
+++ ftp/autoput.c	Sun Apr 30 15:09:29 2000
@@ -0,0 +1,108 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2000 Scott Aaron Bamford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD$");
+#endif /* not lint */
+
+/*
+ * FTP User Program - Command line upload
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ftp_var.h"
+
+int
+auto_put(int argc, char **argv, char *uploadserver)
+{
+	char *uargv[4];
+	char *upload_serverpath;
+	char *pathsep;
+	int uargc;
+	int rval;
+
+	uargv[0] = xstrdup("mput");
+	uargv[1] = uargv[2] = uargv[3] = NULL;
+	uargc = 2;
+	pathsep = NULL;
+	rval = 0;
+
+	/* make sure we always pass a dir to auto_fetch */
+	upload_serverpath = xstrdup(uploadserver);
+	if(uploadserver[strlen(uploadserver)-1] != '/'){
+		if (argc>1) {
+			free(upload_serverpath);
+			upload_serverpath = malloc(strlen(uploadserver) +2);
+			if(upload_serverpath == NULL)
+				err(1,
+		   "Unable to allocate memory for string copy"
+				);
+			strcat(strcpy(upload_serverpath, uploadserver), "/");
+		} else {
+			/* treat as path/filename */
+			strcpy(uargv[0], "put");
+			pathsep = strrchr(upload_serverpath, '/');
+			if (pathsep == NULL) {
+				pathsep = strrchr(upload_serverpath, ':');
+				uargv[2] = xstrdup(pathsep+1);
+				*(++pathsep) = '/';
+			} else 
+				uargv[2] = xstrdup(pathsep+1);
+			*(pathsep+1) = '\0';
+			++uargc;
+		}
+	}
+		
+	/* connect and cwd */		 
+	rval = auto_fetch(1, &upload_serverpath);
+	free(upload_serverpath);
+	if(rval >= 0)
+		goto cleanup_auto_put;
+
+	/* XXX : is this the best way? */
+	if (uargc==3) {
+		uargv[1]=argv[0];
+		put(uargc, uargv);
+		goto cleanup_auto_put;
+	}
+
+	for(; argv[0] != NULL; argv++) {
+		uargv[1] =argv[0];	
+		mput(uargc, uargv);
+	}
+
+cleanup_auto_put:
+	free(uargv[0]);
+	if (uargv[2] != NULL)
+		free(uargv[2]);
+
+	return (rval);
+}
diff -urN /usr/src/usr.bin/ftp/ftp.1 ftp/ftp.1
--- /usr/src/usr.bin/ftp/ftp.1	Wed Jan 12 20:11:09 2000
+++ ftp/ftp.1	Sun Apr 30 15:40:17 2000
@@ -118,6 +118,12 @@
 .Op http://[\fIuser\fR[:\fIpassword\fR]@]\fIhost\fR[:\fIport\fR]/\fIpath\fR
 .Ek
 .Op Ar \&.\&.\&.
+.Nm ""
+.Op Fl u Ar  [ftp://[\fIuser\fR[:\fIpassword\fR]@]\fIhost\fR[:\fIport\fR]/\fIpath\fR[/[file]]] | [\fIuser\fR@]\fIhost\fR:[\fIpath\fR][/[\fIfile\fR]]
+.Bk -words
+file
+.Ek
+.Op Ar \&.\&.\&.
 .Sh DESCRIPTION
 .Nm
 is the user interface to the Internet standard File Transfer Protocol.
@@ -238,6 +244,20 @@
 Refer to
 .Ic rate
 for more information.
+.It Xo
+.Fl u 
+.Ar url
+.Ar file
+.Op \&.\&.\&.
+.Xc
+Upload files on the command line to
+.Ar url
+where
+.Ar url
+is one of the ftp url as suported by auto-fecth with an optional filename for
+singal file uploads.  And
+.Ar file
+is one or more local files to be uploaded.
 .It Fl v
 Enable
 .Ic verbose
@@ -889,7 +909,7 @@
 Interactive prompting
 occurs during multiple file transfers to allow the
 user to selectively retrieve or store files.
-If prompting is turned off (default is on), any
+if prompting is turned off (default is on), any
 .Ic mget
 or
 .Ic mput
diff -urN /usr/src/usr.bin/ftp/ftp_var.h ftp/ftp_var.h
--- /usr/src/usr.bin/ftp/ftp_var.h	Mon Feb 14 03:31:30 2000
+++ ftp/ftp_var.h	Sun Apr 30 13:39:44 2000
@@ -252,6 +252,7 @@
 GLOBAL	int	epsv4;		/* use EPSV/EPRT on IPv4 connections */
 GLOBAL	int	epsv4bad;	/* EPSV doesn't work on the current server */
 GLOBAL	int	editing;	/* command line editing enabled */
+GLOBAL	int	upload_cmdline;	/* upload flag set from command line */
 
 #ifndef NO_EDITCOMPLETE
 GLOBAL	EditLine *el;		/* editline(3) status structure */
diff -urN /usr/src/usr.bin/ftp/main.c ftp/main.c
--- /usr/src/usr.bin/ftp/main.c	Sun Nov 28 12:20:24 1999
+++ ftp/main.c	Sun Apr 30 15:39:17 2000
@@ -148,7 +148,9 @@
 	struct passwd *pw = NULL;
 	char *cp, *ep, *anonuser, *anonpass;
 	int dumbterm, s, len;
+	char *upload_server;
 
+	upload_server = NULL;
 	ftpport = "ftp";
 	httpport = "http";
 	gateport = NULL;
@@ -169,6 +171,7 @@
 	data = -1;
 	outfile = NULL;
 	restartautofetch = 0;
+	upload_cmdline = 0;
 #ifndef NO_EDITCOMPLETE
 	editing = 0;
 	el = NULL;
@@ -270,7 +273,7 @@
 		}
 	}
 
-	while ((ch = getopt(argc, argv, "Aadefgino:pP:r:RtT:vV")) != -1) {
+	while ((ch = getopt(argc, argv, "Aadefgino:pP:r:RtT:u:vV")) != -1) {
 		switch (ch) {
 		case 'A':
 			activefallback = 0;
@@ -337,6 +340,16 @@
 			trace = 1;
 			break;
 
+		case 'u':
+		{
+			/* XXX : if i move this under 'T' we get a segv. */
+			upload_cmdline = 1;
+			interactive = 0;
+			upload_server = xstrdup(optarg);
+
+			break;
+		}
+
 		case 'T':
 		{
 			int targc;
@@ -441,7 +454,11 @@
 #endif
 
 	if (argc > 0) {
-		if (strchr(argv[0], ':') != NULL && ! isipv6addr(argv[0])) {
+		if (upload_cmdline) {
+			rval = auto_put(argc, argv, upload_server);
+			exit(rval);
+		} else if (strchr(argv[0], ':') != NULL 
+			   && ! isipv6addr(argv[0])) {
 			rval = auto_fetch(argc, argv);
 			if (rval >= 0)		/* -1 == connected and cd-ed */
 				exit(rval);
@@ -963,6 +980,8 @@
 "usage: %s [-AadefginpRtvV] [-o outfile] [-P port] [-r retry] [-T dir,max[,inc]\n"
 "       [[user@]host [port]] [host:path[/]] [file:///file]\n"
 "       [ftp://[user[:pass]@]host[:port]/path[/]]\n"
-"       [http://[user[:pass]@]host[:port]/path] [...]\n", __progname);
+"       [http://[user[:pass]@]host[:port]/path] [...]\n"
+"       %s [-u [ftp://[user[:password]@]host[:port]/path[/[file]]] |\n"
+"       [user@]host:[path][/[file]]]] file [...]\n", __progname, __progname);
 	exit(1);
 }
>Release-Note:
>Audit-Trail:
>Unformatted:
 >System: NetBSD blip.fish.poo 1.4U NetBSD 1.4U (BLIP-$Revision: 1.311 $) #13: Thu Mar 16 13:38:45 GMT 2000 sab@blip.fish.poo:/usr/src/sys/arch/i386/compile/BLIP i386