aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhpa <hpa>2003-02-03 01:29:00 +0000
committerhpa <hpa>2003-02-03 01:29:00 +0000
commit8796832723e68c46d186e99d6f06fc0cdaad10c4 (patch)
tree9609917a3df8b43f94dbfd991ff0ef5570498837
parentcabc969c25d6a66238f29089944499733645a98c (diff)
downloadtftp-hpa-8796832723e68c46d186e99d6f06fc0cdaad10c4.tar.gz
Support running the TFTP client from the command linetftp-hpa-0.33
-rw-r--r--CHANGES5
-rw-r--r--tftp/main.c158
-rw-r--r--tftp/tftp.1.in8
3 files changed, 111 insertions, 60 deletions
diff --git a/CHANGES b/CHANGES
index cfd7e15..a6b0dec 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,11 @@ Changes in 0.33:
Configuration fix: readline needs termcap.
+ Support running the tftp client from the command line. For
+ example:
+
+ tftp -m binary -c get hostname:file
+
Changes in 0.32:
Better error messages; including the capability to send a
diff --git a/tftp/main.c b/tftp/main.c
index 7f383fa..661796c 100644
--- a/tftp/main.c
+++ b/tftp/main.c
@@ -186,70 +186,110 @@ char *xstrdup(const char *);
int
main(int argc, char *argv[])
{
- struct sockaddr_in s_in;
- int c;
- int pargc;
- char **pargv;
-
- while ((c = getopt(argc, argv, "Vv")) != -1) {
- switch (c) {
- case 'v':
- verbose = 1;
- break;
- case 'V':
- /* Print version and configuration to stdout and exit */
- printf("%s\n", TFTP_CONFIG_STR);
- exit(0);
- default:
- fprintf(stderr, "Usage: %s [-v] [host]\n", argv[0]);
- exit(EX_USAGE);
- }
- }
+ struct sockaddr_in s_in;
+ int o;
+ int pargc;
+ int iscmd = 0;
+ char **pargv;
- pargc = argc - (optind-1);
- pargv = argv + (optind-1);
-
- sp = getservbyname("tftp", "udp");
- if (sp == 0) {
- /* Use canned values */
- fprintf(stderr, "tftp: tftp/udp: unknown service, faking it...\n");
- sp = xmalloc(sizeof(struct servent));
- sp->s_name = (char *)"tftp";
- sp->s_aliases = NULL;
- sp->s_port = htons(IPPORT_TFTP);
- sp->s_proto = (char *)"udp";
- exit(1);
- }
- f = socket(AF_INET, SOCK_DGRAM, 0);
- if (f < 0) {
- perror("tftp: socket");
- exit(3);
- }
- bzero((char *)&s_in, sizeof (s_in));
- s_in.sin_family = AF_INET;
- if (bind(f, (struct sockaddr *)&s_in, sizeof (s_in)) < 0) {
- perror("tftp: bind");
- exit(1);
- }
- mode = MODE_DEFAULT;
- bsd_signal(SIGINT, intr);
- if (pargc > 1) {
- if (sigsetjmp(toplevel,1) != 0)
- exit(0);
- setpeer(pargc, pargv);
- }
- if (sigsetjmp(toplevel,1) != 0)
- (void)putchar('\n');
+ mode = MODE_DEFAULT;
+
+ while ((o = getopt(argc, argv, "chm:Vv")) != -1) {
+ switch (o) {
+ case 'v':
+ verbose = 1;
+ break;
+ case 'V':
+ /* Print version and configuration to stdout and exit */
+ printf("%s\n", TFTP_CONFIG_STR);
+ exit(0);
+ case 'm':
+ {
+ const struct modes *p;
+ for ( p = modes ; p->m_name ; p++ ) {
+ if (!strcmp(optarg, p->m_name))
+ break;
+ }
+ if (p->m_name) {
+ settftpmode(p);
+ } else {
+ fprintf(stderr, "%s: invalid mode: %s\n", argv[0], optarg);
+ exit(EX_USAGE);
+ }
+ }
+ break;
+ case 'c':
+ iscmd = 1;
+ break;
+ case 'h':
+ default:
+ fprintf(stderr, "Usage: %s [-v][-m mode] [-c command|host]\n", argv[0]);
+ exit(o == 'h' ? 0 : EX_USAGE);
+ }
+ }
+
+ pargc = argc - (optind-1);
+ pargv = argv + (optind-1);
+
+ sp = getservbyname("tftp", "udp");
+ if (sp == 0) {
+ /* Use canned values */
+ if (verbose)
+ fprintf(stderr, "tftp: tftp/udp: unknown service, faking it...\n");
+ sp = xmalloc(sizeof(struct servent));
+ sp->s_name = (char *)"tftp";
+ sp->s_aliases = NULL;
+ sp->s_port = htons(IPPORT_TFTP);
+ sp->s_proto = (char *)"udp";
+ }
+ port = sp->s_port; /* Default port */
+ f = socket(AF_INET, SOCK_DGRAM, 0);
+ if (f < 0) {
+ perror("tftp: socket");
+ exit(EX_OSERR);
+ }
+ bzero((char *)&s_in, sizeof (s_in));
+ s_in.sin_family = AF_INET;
+ if (bind(f, (struct sockaddr *)&s_in, sizeof (s_in)) < 0) {
+ perror("tftp: bind");
+ exit(EX_OSERR);
+ }
+ bsd_signal(SIGINT, intr);
+ if (pargc > 1) {
+ if ( iscmd ) {
+ /* -c specified; execute command and exit */
+ struct cmd *c;
+
+ if (sigsetjmp(toplevel,1) != 0)
+ exit(EX_UNAVAILABLE);
+
+ c = getcmd(pargv[1]);
+ if ( c == (struct cmd *)-1 || c == (struct cmd *)0 ) {
+ fprintf(stderr, "%s: invalid command: %s\n", argv[0], pargv[1]);
+ exit(EX_USAGE);
+ }
+ (*c->handler)(pargc-1, pargv+1);
+ exit(0);
+ } else {
+ /* No -c */
+ if (sigsetjmp(toplevel,1) != 0)
+ exit(0);
+ setpeer(pargc, pargv);
+ }
+ }
+ if (sigsetjmp(toplevel,1) != 0)
+ (void)putchar('\n');
+
#ifdef WITH_READLINE
#ifdef HAVE_READLINE_HISTORY_H
- using_history();
+ using_history();
#endif
#endif
-
- command();
-
- return 0; /* Never reached */
+
+ command();
+
+ return 0; /* Never reached */
}
char *hostname;
@@ -438,7 +478,7 @@ put(int argc, char *argv[])
herror((char *)NULL);
return;
}
- bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, hp->h_length);
+ bcopy(hp->h_addr, &peeraddr.sin_addr, hp->h_length);
peeraddr.sin_family = hp->h_addrtype;
connected = 1;
hostname = xstrdup(hp->h_name);
diff --git a/tftp/tftp.1.in b/tftp/tftp.1.in
index 7df6ca0..9994cf4 100644
--- a/tftp/tftp.1.in
+++ b/tftp/tftp.1.in
@@ -31,7 +31,7 @@
.\" SUCH DAMAGE.
.\"
.\"----------------------------------------------------------------------- */
-.TH TFTP 1 "13 November 2001" "tftp-hpa @@VERSION@@" "UNIX User's Manual"
+.TH TFTP 1 "2 February 2003" "tftp-hpa @@VERSION@@" "User's Manual"
.SH NAME
.B tftp
\- IPv4 Trivial File Transfer Protocol client
@@ -55,6 +55,12 @@ as the default host for future transfers (see the
command below.)
.SH OPTIONS
.TP
+\fB\-c\fP \fIcommand\fP
+Execute \fIcommand\fP as if it had been entered on the tftp prompt.
+.TP
+\fB\-m\fP \fImode\fP
+Set the default transfer mode to \fImode\fP. This is usually used with \-c.
+.TP
.B \-v
Default to verbose mode.
.TP