Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmain.c
Go to the documentation of this file.
00001 /* 00002 * Copyright (c) 1985, 1989 Regents of the University of California. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms are permitted 00006 * provided that the above copyright notice and this paragraph are 00007 * duplicated in all such forms and that any documentation, 00008 * advertising materials, and other materials related to such 00009 * distribution and use acknowledge that the software was developed 00010 * by the University of California, Berkeley. The name of the 00011 * University may not be used to endorse or promote products derived 00012 * from this software without specific prior written permission. 00013 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00014 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00015 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00016 */ 00017 00018 #ifndef lint 00019 char copyright[] = 00020 "@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\ 00021 All rights reserved.\n"; 00022 #endif /* not lint */ 00023 00024 #ifndef lint 00025 static char sccsid[] = "@(#)main.c based on 5.13 (Berkeley) 3/14/89"; 00026 #endif /* not lint */ 00027 00028 /* 00029 * FTP User Program -- Command Interface. 00030 */ 00031 #include "precomp.h" 00032 00033 #if defined(sun) && !defined(FD_SET) 00034 typedef int uid_t; 00035 #endif 00036 00037 uid_t getuid(void); 00038 void intr(void); 00039 void lostpeer(void); 00040 char *getlogin(void); 00041 00042 short portnum; 00043 00044 char home[128]; 00045 char *globerr; 00046 int autologin; 00047 00048 00049 00050 /* Lot's of options... */ 00051 /* 00052 * Options and other state info. 00053 */ 00054 int trace; /* trace packets exchanged */ 00055 int hash; /* print # for each buffer transferred */ 00056 //int sendport; /* use PORT cmd for each data connection */ 00057 int verbose; /* print messages coming back from server */ 00058 int connected; /* connected to server */ 00059 int fromatty; /* input is from a terminal */ 00060 int interactive; /* interactively prompt on m* cmds */ 00061 int debug; /* debugging level */ 00062 int bell; /* ring bell on cmd completion */ 00063 int doglob; /* glob local file names */ 00064 int proxy; /* proxy server connection active */ 00065 int passivemode; 00066 int proxflag; /* proxy connection exists */ 00067 int sunique; /* store files on server with unique name */ 00068 int runique; /* store local files with unique name */ 00069 int mcase; /* map upper to lower case for mget names */ 00070 int ntflag; /* use ntin ntout tables for name translation */ 00071 int mapflag; /* use mapin mapout templates on file names */ 00072 int code; /* return/reply code for ftp command */ 00073 int crflag; /* if 1, strip car. rets. on ascii gets */ 00074 char pasv[64]; /* passive port for proxy data connection */ 00075 char *altarg; /* argv[1] with no shell-like preprocessing */ 00076 char ntin[17]; /* input translation table */ 00077 char ntout[17]; /* output translation table */ 00078 // #include <sys/param.h> 00079 char mapin[MAXPATHLEN]; /* input map template */ 00080 char mapout[MAXPATHLEN]; /* output map template */ 00081 char typename[32]; /* name of file transfer type */ 00082 int type; /* file transfer type */ 00083 char structname[32]; /* name of file transfer structure */ 00084 int stru; /* file transfer structure */ 00085 char formname[32]; /* name of file transfer format */ 00086 int form; /* file transfer format */ 00087 char modename[32]; /* name of file transfer mode */ 00088 int mode; /* file transfer mode */ 00089 char bytename[32]; /* local byte size in ascii */ 00090 int bytesize; /* local byte size in binary */ 00091 00092 jmp_buf toplevel; /* non-local goto stuff for cmd scanner */ 00093 00094 char line[200]; /* input line buffer */ 00095 char *stringbase; /* current scan point in line buffer */ 00096 char argbuf[200]; /* argument storage buffer */ 00097 char *argbase; /* current storage point in arg buffer */ 00098 int margc; /* count of arguments on input line */ 00099 const char *margv[20]; /* args parsed from input line */ 00100 int cpend; /* flag: if != 0, then pending server reply */ 00101 int mflag; /* flag: if != 0, then active multi command */ 00102 00103 int options; /* used during socket creation */ 00104 00105 int macnum; /* number of defined macros */ 00106 struct macel macros[16]; 00107 char macbuf[4096]; 00108 00109 /* 00110 * Need to start a listen on the data channel 00111 * before we send the command, otherwise the 00112 * server's connect may fail. 00113 */ 00114 int sendport = -1; 00115 00116 static const char *slurpstring(); 00117 00118 00119 int main(int argc, const char *argv[]) 00120 { 00121 const char *cp; 00122 int top; 00123 #if 0 00124 char homedir[MAXPATHLEN]; 00125 #endif 00126 00127 int err; 00128 WORD wVerReq; 00129 00130 WSADATA WSAData; 00131 struct servent *sp; /* service spec for tcp/ftp */ 00132 00133 /* Disable output buffering, for the benefit of Emacs. */ 00134 //setbuf(stdout, NULL); 00135 00136 _fmode = O_BINARY; // This causes an error somewhere. 00137 00138 wVerReq = MAKEWORD(1,1); 00139 00140 err = WSAStartup(wVerReq, &WSAData); 00141 if (err != 0) 00142 { 00143 fprintf(stderr, "Could not initialize Windows socket interface."); 00144 exit(1); 00145 } 00146 00147 sp = getservbyname("ftp", "tcp"); 00148 if (sp == 0) { 00149 fprintf(stderr, "ftp: ftp/tcp: unknown service\n"); 00150 exit(1); 00151 } 00152 00153 portnum = sp->s_port; 00154 00155 00156 doglob = 1; 00157 interactive = 1; 00158 autologin = 1; 00159 argc--, argv++; 00160 while (argc > 0 && **argv == '-') { 00161 for (cp = *argv + 1; *cp; cp++) 00162 switch (*cp) { 00163 00164 case 'd': 00165 options |= SO_DEBUG; 00166 debug++; 00167 break; 00168 00169 case 'v': 00170 verbose++; 00171 break; 00172 00173 case 't': 00174 trace++; 00175 break; 00176 00177 case 'i': 00178 interactive = 0; 00179 break; 00180 00181 case 'n': 00182 autologin = 0; 00183 break; 00184 00185 case 'g': 00186 doglob = 0; 00187 break; 00188 00189 default: 00190 fprintf(stdout, 00191 "ftp: %c: unknown option\n", *cp); 00192 exit(1); 00193 } 00194 argc--, argv++; 00195 } 00196 // fromatty = isatty(fileno(stdin)); 00197 fromatty = 1; // Strengthen this test 00198 /* 00199 * Set up defaults for FTP. 00200 */ 00201 (void) strcpy(typename, "ascii"), type = TYPE_A; 00202 (void) strcpy(formname, "non-print"), form = FORM_N; 00203 (void) strcpy(modename, "stream"), mode = MODE_S; 00204 (void) strcpy(structname, "file"), stru = STRU_F; 00205 (void) strcpy(bytename, "8"), bytesize = 8; 00206 if (fromatty) 00207 verbose++; 00208 cpend = 0; /* no pending replies */ 00209 proxy = 0; /* proxy not active */ 00210 passivemode = 1; /* passive mode *is* active */ 00211 crflag = 1; /* strip c.r. on ascii gets */ 00212 /* 00213 * Set up the home directory in case we're globbing. 00214 */ 00215 #if 0 00216 cp = getlogin(); 00217 if (cp != NULL) { 00218 pw = getpwnam(cp); 00219 } 00220 if (pw == NULL) 00221 pw = getpwuid(getuid()); 00222 if (pw != NULL) { 00223 home = homedir; 00224 (void) strcpy(home, pw->pw_dir); 00225 } 00226 #endif 00227 strcpy(home, "C:/"); 00228 if (argc > 0) { 00229 if (setjmp(toplevel)) 00230 exit(0); 00231 // (void) signal(SIGINT, intr); 00232 // (void) signal(SIGPIPE, lostpeer); 00233 setpeer(argc + 1, argv - 1); 00234 } 00235 top = setjmp(toplevel) == 0; 00236 if (top) { 00237 // (void) signal(SIGINT, intr); 00238 // (void) signal(SIGPIPE, lostpeer); 00239 } 00240 for (;;) { 00241 cmdscanner(top); 00242 top = 1; 00243 } 00244 } 00245 00246 void intr(void) 00247 { 00248 longjmp(toplevel, 1); 00249 } 00250 00251 void lostpeer(void) 00252 { 00253 extern SOCKET cout; 00254 extern int data; 00255 00256 if (connected) { 00257 if (cout) { 00258 closesocket(cout); 00259 cout = 0; 00260 } 00261 if (data >= 0) { 00262 (void) shutdown(data, 1+1); 00263 (void) close(data); 00264 data = -1; 00265 } 00266 connected = 0; 00267 } 00268 pswitch(1); 00269 if (connected) { 00270 if (cout) { 00271 closesocket(cout); 00272 cout = 0; 00273 } 00274 connected = 0; 00275 } 00276 proxflag = 0; 00277 pswitch(0); 00278 } 00279 00280 /*char * 00281 tail(char *filename) 00282 { 00283 register char *s; 00284 00285 while (*filename) { 00286 s = rindex(filename, '/'); 00287 if (s == NULL) 00288 break; 00289 if (s[1]) 00290 return (s + 1); 00291 *s = '\0'; 00292 } 00293 return (filename); 00294 } 00295 */ 00296 /* 00297 * Command parser. 00298 */ 00299 void cmdscanner(int top) 00300 { 00301 register struct cmd *c; 00302 00303 if (!top) 00304 (void) putchar('\n'); 00305 for (;;) { 00306 (void) fflush(stdout); 00307 if (fromatty) { 00308 printf("ftp> "); 00309 (void) fflush(stdout); 00310 } 00311 if (gets(line) == 0) { 00312 if (feof(stdin) || ferror(stdin)) 00313 quit(0, NULL); 00314 break; 00315 } 00316 if (line[0] == 0) 00317 break; 00318 makeargv(); 00319 if (margc == 0) { 00320 continue; 00321 } 00322 c = getcmd(margv[0]); 00323 if (c == (struct cmd *)-1) { 00324 printf("?Ambiguous command\n"); 00325 continue; 00326 } 00327 if (c == 0) { 00328 printf("?Invalid command\n"); 00329 continue; 00330 } 00331 if (c->c_conn && !connected) { 00332 printf ("Not connected.\n"); 00333 continue; 00334 } 00335 (*c->c_handler)(margc, margv); 00336 if (bell && c->c_bell) 00337 (void) putchar('\007'); 00338 if (c->c_handler != help) 00339 break; 00340 } 00341 (void) fflush(stdout); 00342 // (void) signal(SIGINT, intr); 00343 // (void) signal(SIGPIPE, lostpeer); 00344 } 00345 00346 struct cmd * 00347 getcmd(const char *name) 00348 { 00349 extern struct cmd cmdtab[]; 00350 const char *p, *q; 00351 struct cmd *c, *found; 00352 int nmatches, longest; 00353 00354 longest = 0; 00355 nmatches = 0; 00356 found = 0; 00357 for (c = cmdtab; (p = c->c_name); c++) { 00358 for (q = name; *q == *p++; q++) 00359 if (*q == 0) /* exact match? */ 00360 return (c); 00361 if (!*q) { /* the name was a prefix */ 00362 if (q - name > longest) { 00363 longest = q - name; 00364 nmatches = 1; 00365 found = c; 00366 } else if (q - name == longest) 00367 nmatches++; 00368 } 00369 } 00370 if (nmatches > 1) 00371 return ((struct cmd *)-1); 00372 return (found); 00373 } 00374 00375 /* 00376 * Slice a string up into argc/argv. 00377 */ 00378 00379 int slrflag; 00380 00381 void makeargv(void) 00382 { 00383 const char **argp; 00384 00385 margc = 0; 00386 argp = margv; 00387 stringbase = line; /* scan from first of buffer */ 00388 argbase = argbuf; /* store from first of buffer */ 00389 slrflag = 0; 00390 while ((*argp++ = slurpstring())) 00391 margc++; 00392 } 00393 00394 /* 00395 * Parse string into argbuf; 00396 * implemented with FSM to 00397 * handle quoting and strings 00398 */ 00399 static const char * 00400 slurpstring(void) 00401 { 00402 int got_one = 0; 00403 register char *sb = stringbase; 00404 register char *ap = argbase; 00405 char *tmp = argbase; /* will return this if token found */ 00406 00407 if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */ 00408 switch (slrflag) { /* and $ as token for macro invoke */ 00409 case 0: 00410 slrflag++; 00411 stringbase++; 00412 return ((*sb == '!') ? "!" : "$"); 00413 /* NOTREACHED */ 00414 case 1: 00415 slrflag++; 00416 altarg = stringbase; 00417 break; 00418 default: 00419 break; 00420 } 00421 } 00422 00423 S0: 00424 switch (*sb) { 00425 00426 case '\0': 00427 goto OUT1; 00428 00429 case ' ': 00430 case '\t': 00431 sb++; goto S0; 00432 00433 default: 00434 switch (slrflag) { 00435 case 0: 00436 slrflag++; 00437 break; 00438 case 1: 00439 slrflag++; 00440 altarg = sb; 00441 break; 00442 default: 00443 break; 00444 } 00445 goto S1; 00446 } 00447 00448 S1: 00449 switch (*sb) { 00450 00451 case ' ': 00452 case '\t': 00453 case '\0': 00454 goto OUT1; /* end of token */ 00455 00456 case '\\': 00457 sb++; goto S2; /* slurp next character */ 00458 00459 case '"': 00460 sb++; goto S3; /* slurp quoted string */ 00461 00462 default: 00463 *ap++ = *sb++; /* add character to token */ 00464 got_one = 1; 00465 goto S1; 00466 } 00467 00468 S2: 00469 switch (*sb) { 00470 00471 case '\0': 00472 goto OUT1; 00473 00474 default: 00475 *ap++ = *sb++; 00476 got_one = 1; 00477 goto S1; 00478 } 00479 00480 S3: 00481 switch (*sb) { 00482 00483 case '\0': 00484 goto OUT1; 00485 00486 case '"': 00487 sb++; goto S1; 00488 00489 default: 00490 *ap++ = *sb++; 00491 got_one = 1; 00492 goto S3; 00493 } 00494 00495 OUT1: 00496 if (got_one) 00497 *ap++ = '\0'; 00498 argbase = ap; /* update storage pointer */ 00499 stringbase = sb; /* update scan pointer */ 00500 if (got_one) { 00501 return(tmp); 00502 } 00503 switch (slrflag) { 00504 case 0: 00505 slrflag++; 00506 break; 00507 case 1: 00508 slrflag++; 00509 altarg = (char *) 0; 00510 break; 00511 default: 00512 break; 00513 } 00514 return((char *)0); 00515 } 00516 00517 #define HELPINDENT (sizeof ("directory")) 00518 00519 /* 00520 * Help command. 00521 * Call each command handler with argc == 0 and argv[0] == name. 00522 */ 00523 void help(int argc, const char *argv[]) 00524 { 00525 extern struct cmd cmdtab[]; 00526 struct cmd *c; 00527 00528 if (argc == 1) { 00529 register int i, j, w, k; 00530 int columns, width = 0, lines; 00531 extern int NCMDS; 00532 00533 printf("Commands may be abbreviated. Commands are:\n\n"); 00534 for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 00535 int len = strlen(c->c_name); 00536 00537 if (len > width) 00538 width = len; 00539 } 00540 width = (width + 8) &~ 7; 00541 columns = 80 / width; 00542 if (columns == 0) 00543 columns = 1; 00544 lines = (NCMDS + columns - 1) / columns; 00545 for (i = 0; i < lines; i++) { 00546 for (j = 0; j < columns; j++) { 00547 c = cmdtab + j * lines + i; 00548 if (c->c_name && (!proxy || c->c_proxy)) { 00549 printf("%s", c->c_name); 00550 } 00551 else if (c->c_name) { 00552 for (k=0; k < (int) strlen(c->c_name); k++) { 00553 (void) putchar(' '); 00554 } 00555 } 00556 if (c + lines >= &cmdtab[NCMDS]) { 00557 printf("\n"); 00558 break; 00559 } 00560 w = strlen(c->c_name); 00561 while (w < width) { 00562 w = (w + 8) &~ 7; 00563 (void) putchar('\t'); 00564 } 00565 } 00566 } 00567 (void) fflush(stdout); 00568 return; 00569 } 00570 while (--argc > 0) { 00571 const char *arg; 00572 arg = *++argv; 00573 c = getcmd(arg); 00574 if (c == (struct cmd *)-1) 00575 printf("?Ambiguous help command %s\n", arg); 00576 else if (c == (struct cmd *)0) 00577 printf("?Invalid help command %s\n", arg); 00578 else 00579 printf("%-*s\t%s\n", (int)HELPINDENT, 00580 c->c_name, c->c_help); 00581 } 00582 (void) fflush(stdout); 00583 } Generated on Sun May 27 2012 04:16:38 for ReactOS by
1.7.6.1
|