fixed warnings when compiled with -Wwrite-strings
[reactos.git] / reactos / apps / utils / net / ftp / main.c
1 /*
2 * Copyright (c) 1985, 1989 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\
21 All rights reserved.\n";
22 #endif /* not lint */
23
24 #ifndef lint
25 static char sccsid[] = "@(#)main.c based on 5.13 (Berkeley) 3/14/89";
26 #endif /* not lint */
27
28 /*
29 * FTP User Program -- Command Interface.
30 */
31 #if !defined(WIN32)
32 #include <netdb.h>
33 #include <sys/socket.h>
34 #include <sys/ioctl.h>
35 #include <arpa/ftp.h>
36 #include <errno.h>
37 #include <pwd.h>
38 #endif
39 #include "ftp_var.h"
40 #include "prototypes.h"
41 #include <sys/types.h>
42
43 #include <io.h>
44 #include <fcntl.h>
45
46 #include <signal.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <ctype.h>
50
51
52 #if defined(sun) && !defined(FD_SET)
53 typedef int uid_t;
54 #endif
55
56 uid_t getuid();
57 void intr();
58 void lostpeer();
59 char *getlogin();
60
61 short portnum;
62
63 char home[128];
64 char *globerr;
65 int autologin;
66
67
68
69 /* Lot's of options... */
70 /*
71 * Options and other state info.
72 */
73 int trace; /* trace packets exchanged */
74 int hash; /* print # for each buffer transferred */
75 int sendport; /* use PORT cmd for each data connection */
76 int verbose; /* print messages coming back from server */
77 int connected; /* connected to server */
78 int fromatty; /* input is from a terminal */
79 int interactive; /* interactively prompt on m* cmds */
80 int debug; /* debugging level */
81 int bell; /* ring bell on cmd completion */
82 int doglob; /* glob local file names */
83 int proxy; /* proxy server connection active */
84 int passivemode;
85 int proxflag; /* proxy connection exists */
86 int sunique; /* store files on server with unique name */
87 int runique; /* store local files with unique name */
88 int mcase; /* map upper to lower case for mget names */
89 int ntflag; /* use ntin ntout tables for name translation */
90 int mapflag; /* use mapin mapout templates on file names */
91 int code; /* return/reply code for ftp command */
92 int crflag; /* if 1, strip car. rets. on ascii gets */
93 char pasv[64]; /* passive port for proxy data connection */
94 char *altarg; /* argv[1] with no shell-like preprocessing */
95 char ntin[17]; /* input translation table */
96 char ntout[17]; /* output translation table */
97 // #include <sys/param.h>
98 char mapin[MAXPATHLEN]; /* input map template */
99 char mapout[MAXPATHLEN]; /* output map template */
100 char typename[32]; /* name of file transfer type */
101 int type; /* file transfer type */
102 char structname[32]; /* name of file transfer structure */
103 int stru; /* file transfer structure */
104 char formname[32]; /* name of file transfer format */
105 int form; /* file transfer format */
106 char modename[32]; /* name of file transfer mode */
107 int mode; /* file transfer mode */
108 char bytename[32]; /* local byte size in ascii */
109 int bytesize; /* local byte size in binary */
110
111 jmp_buf toplevel; /* non-local goto stuff for cmd scanner */
112
113 char line[200]; /* input line buffer */
114 char *stringbase; /* current scan point in line buffer */
115 char argbuf[200]; /* argument storage buffer */
116 char *argbase; /* current storage point in arg buffer */
117 int margc; /* count of arguments on input line */
118 const char *margv[20]; /* args parsed from input line */
119 int cpend; /* flag: if != 0, then pending server reply */
120 int mflag; /* flag: if != 0, then active multi command */
121
122 int options; /* used during socket creation */
123
124 static const char *slurpstring();
125
126
127 int main(int argc, const char *argv[])
128 {
129 const char *cp;
130 int top;
131 #if 0
132 char homedir[MAXPATHLEN];
133 #endif
134
135 int err;
136 WORD wVerReq;
137
138 WSADATA WSAData;
139 struct servent *sp; /* service spec for tcp/ftp */
140
141 /* Disable output buffering, for the benefit of Emacs. */
142 //setbuf(stdout, NULL);
143
144 _fmode = O_BINARY; // This causes an error somewhere.
145
146 wVerReq = MAKEWORD(1,1);
147
148 err = WSAStartup(wVerReq, &WSAData);
149 if (err != 0)
150 {
151 fprintf(stderr, "Could not initialize Windows socket interface.");
152 exit(1);
153 }
154
155 sp = getservbyname("ftp", "tcp");
156 if (sp == 0) {
157 fprintf(stderr, "ftp: ftp/tcp: unknown service\n");
158 exit(1);
159 }
160
161 portnum = sp->s_port;
162
163
164 doglob = 1;
165 interactive = 1;
166 autologin = 1;
167 argc--, argv++;
168 while (argc > 0 && **argv == '-') {
169 for (cp = *argv + 1; *cp; cp++)
170 switch (*cp) {
171
172 case 'd':
173 options |= SO_DEBUG;
174 debug++;
175 break;
176
177 case 'v':
178 verbose++;
179 break;
180
181 case 't':
182 trace++;
183 break;
184
185 case 'i':
186 interactive = 0;
187 break;
188
189 case 'n':
190 autologin = 0;
191 break;
192
193 case 'g':
194 doglob = 0;
195 break;
196
197 default:
198 fprintf(stdout,
199 "ftp: %c: unknown option\n", *cp);
200 exit(1);
201 }
202 argc--, argv++;
203 }
204 // fromatty = isatty(fileno(stdin));
205 fromatty = 1; // Strengthen this test
206 /*
207 * Set up defaults for FTP.
208 */
209 (void) strcpy(typename, "ascii"), type = TYPE_A;
210 (void) strcpy(formname, "non-print"), form = FORM_N;
211 (void) strcpy(modename, "stream"), mode = MODE_S;
212 (void) strcpy(structname, "file"), stru = STRU_F;
213 (void) strcpy(bytename, "8"), bytesize = 8;
214 if (fromatty)
215 verbose++;
216 cpend = 0; /* no pending replies */
217 proxy = 0; /* proxy not active */
218 passivemode = 1; /* passive mode *is* active */
219 crflag = 1; /* strip c.r. on ascii gets */
220 /*
221 * Set up the home directory in case we're globbing.
222 */
223 #if 0
224 cp = getlogin();
225 if (cp != NULL) {
226 pw = getpwnam(cp);
227 }
228 if (pw == NULL)
229 pw = getpwuid(getuid());
230 if (pw != NULL) {
231 home = homedir;
232 (void) strcpy(home, pw->pw_dir);
233 }
234 #endif
235 strcpy(home, "C:/");
236 if (argc > 0) {
237 if (setjmp(toplevel))
238 exit(0);
239 // (void) signal(SIGINT, intr);
240 // (void) signal(SIGPIPE, lostpeer);
241 setpeer(argc + 1, argv - 1);
242 }
243 top = setjmp(toplevel) == 0;
244 if (top) {
245 // (void) signal(SIGINT, intr);
246 // (void) signal(SIGPIPE, lostpeer);
247 }
248 for (;;) {
249 cmdscanner(top);
250 top = 1;
251 }
252 }
253
254 void
255 intr()
256 {
257
258 longjmp(toplevel, 1);
259 }
260
261 void lostpeer(void)
262 {
263 extern int cout;
264 extern int data;
265
266 if (connected) {
267 if (cout != (int) NULL) {
268 closesocket(cout);
269 cout = (int) NULL;
270 }
271 if (data >= 0) {
272 (void) shutdown(data, 1+1);
273 (void) close(data);
274 data = -1;
275 }
276 connected = 0;
277 }
278 pswitch(1);
279 if (connected) {
280 if (cout != (int)NULL) {
281 closesocket(cout);
282 cout = (int) NULL;
283 }
284 connected = 0;
285 }
286 proxflag = 0;
287 pswitch(0);
288 }
289
290 /*char *
291 tail(filename)
292 char *filename;
293 {
294 register char *s;
295
296 while (*filename) {
297 s = rindex(filename, '/');
298 if (s == NULL)
299 break;
300 if (s[1])
301 return (s + 1);
302 *s = '\0';
303 }
304 return (filename);
305 }
306 */
307 /*
308 * Command parser.
309 */
310 void cmdscanner(top)
311 int top;
312 {
313 register struct cmd *c;
314
315 if (!top)
316 (void) putchar('\n');
317 for (;;) {
318 (void) fflush(stdout);
319 if (fromatty) {
320 printf("ftp> ");
321 (void) fflush(stdout);
322 }
323 if (gets(line) == 0) {
324 if (feof(stdin) || ferror(stdin))
325 quit();
326 break;
327 }
328 if (line[0] == 0)
329 break;
330 makeargv();
331 if (margc == 0) {
332 continue;
333 }
334 c = getcmd(margv[0]);
335 if (c == (struct cmd *)-1) {
336 printf("?Ambiguous command\n");
337 continue;
338 }
339 if (c == 0) {
340 printf("?Invalid command\n");
341 continue;
342 }
343 if (c->c_conn && !connected) {
344 printf ("Not connected.\n");
345 continue;
346 }
347 (*c->c_handler)(margc, margv);
348 if (bell && c->c_bell)
349 (void) putchar('\007');
350 if (c->c_handler != help)
351 break;
352 }
353 (void) fflush(stdout);
354 // (void) signal(SIGINT, intr);
355 // (void) signal(SIGPIPE, lostpeer);
356 }
357
358 struct cmd *
359 getcmd(name)
360 const char *name;
361 {
362 extern struct cmd cmdtab[];
363 const char *p, *q;
364 struct cmd *c, *found;
365 int nmatches, longest;
366
367 longest = 0;
368 nmatches = 0;
369 found = 0;
370 for (c = cmdtab; (p = c->c_name); c++) {
371 for (q = name; *q == *p++; q++)
372 if (*q == 0) /* exact match? */
373 return (c);
374 if (!*q) { /* the name was a prefix */
375 if (q - name > longest) {
376 longest = q - name;
377 nmatches = 1;
378 found = c;
379 } else if (q - name == longest)
380 nmatches++;
381 }
382 }
383 if (nmatches > 1)
384 return ((struct cmd *)-1);
385 return (found);
386 }
387
388 /*
389 * Slice a string up into argc/argv.
390 */
391
392 int slrflag;
393
394 void makeargv()
395 {
396 const char **argp;
397
398 margc = 0;
399 argp = margv;
400 stringbase = line; /* scan from first of buffer */
401 argbase = argbuf; /* store from first of buffer */
402 slrflag = 0;
403 while ((*argp++ = slurpstring()))
404 margc++;
405 }
406
407 /*
408 * Parse string into argbuf;
409 * implemented with FSM to
410 * handle quoting and strings
411 */
412 static const char *
413 slurpstring()
414 {
415 int got_one = 0;
416 register char *sb = stringbase;
417 register char *ap = argbase;
418 char *tmp = argbase; /* will return this if token found */
419
420 if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */
421 switch (slrflag) { /* and $ as token for macro invoke */
422 case 0:
423 slrflag++;
424 stringbase++;
425 return ((*sb == '!') ? "!" : "$");
426 /* NOTREACHED */
427 case 1:
428 slrflag++;
429 altarg = stringbase;
430 break;
431 default:
432 break;
433 }
434 }
435
436 S0:
437 switch (*sb) {
438
439 case '\0':
440 goto OUT1;
441
442 case ' ':
443 case '\t':
444 sb++; goto S0;
445
446 default:
447 switch (slrflag) {
448 case 0:
449 slrflag++;
450 break;
451 case 1:
452 slrflag++;
453 altarg = sb;
454 break;
455 default:
456 break;
457 }
458 goto S1;
459 }
460
461 S1:
462 switch (*sb) {
463
464 case ' ':
465 case '\t':
466 case '\0':
467 goto OUT1; /* end of token */
468
469 case '\\':
470 sb++; goto S2; /* slurp next character */
471
472 case '"':
473 sb++; goto S3; /* slurp quoted string */
474
475 default:
476 *ap++ = *sb++; /* add character to token */
477 got_one = 1;
478 goto S1;
479 }
480
481 S2:
482 switch (*sb) {
483
484 case '\0':
485 goto OUT1;
486
487 default:
488 *ap++ = *sb++;
489 got_one = 1;
490 goto S1;
491 }
492
493 S3:
494 switch (*sb) {
495
496 case '\0':
497 goto OUT1;
498
499 case '"':
500 sb++; goto S1;
501
502 default:
503 *ap++ = *sb++;
504 got_one = 1;
505 goto S3;
506 }
507
508 OUT1:
509 if (got_one)
510 *ap++ = '\0';
511 argbase = ap; /* update storage pointer */
512 stringbase = sb; /* update scan pointer */
513 if (got_one) {
514 return(tmp);
515 }
516 switch (slrflag) {
517 case 0:
518 slrflag++;
519 break;
520 case 1:
521 slrflag++;
522 altarg = (char *) 0;
523 break;
524 default:
525 break;
526 }
527 return((char *)0);
528 }
529
530 #define HELPINDENT (sizeof ("directory"))
531
532 /*
533 * Help command.
534 * Call each command handler with argc == 0 and argv[0] == name.
535 */
536 void help(argc, argv)
537 int argc;
538 char *argv[];
539 {
540 extern struct cmd cmdtab[];
541 register struct cmd *c;
542
543 if (argc == 1) {
544 register int i, j, w, k;
545 int columns, width = 0, lines;
546 extern int NCMDS;
547
548 printf("Commands may be abbreviated. Commands are:\n\n");
549 for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
550 int len = strlen(c->c_name);
551
552 if (len > width)
553 width = len;
554 }
555 width = (width + 8) &~ 7;
556 columns = 80 / width;
557 if (columns == 0)
558 columns = 1;
559 lines = (NCMDS + columns - 1) / columns;
560 for (i = 0; i < lines; i++) {
561 for (j = 0; j < columns; j++) {
562 c = cmdtab + j * lines + i;
563 if (c->c_name && (!proxy || c->c_proxy)) {
564 printf("%s", c->c_name);
565 }
566 else if (c->c_name) {
567 for (k=0; k < (int) strlen(c->c_name); k++) {
568 (void) putchar(' ');
569 }
570 }
571 if (c + lines >= &cmdtab[NCMDS]) {
572 printf("\n");
573 break;
574 }
575 w = strlen(c->c_name);
576 while (w < width) {
577 w = (w + 8) &~ 7;
578 (void) putchar('\t');
579 }
580 }
581 }
582 (void) fflush(stdout);
583 return;
584 }
585 while (--argc > 0) {
586 register char *arg;
587 arg = *++argv;
588 c = getcmd(arg);
589 if (c == (struct cmd *)-1)
590 printf("?Ambiguous help command %s\n", arg);
591 else if (c == (struct cmd *)0)
592 printf("?Invalid help command %s\n", arg);
593 else
594 printf("%-*s\t%s\n", HELPINDENT,
595 c->c_name, c->c_help);
596 }
597 (void) fflush(stdout);
598 }