|
Lines 22-27
Link Here
|
| 22 |
#include <sys/socket.h> |
22 |
#include <sys/socket.h> |
| 23 |
#include <sys/param.h> |
23 |
#include <sys/param.h> |
| 24 |
|
24 |
|
|
|
25 |
#include <ctype.h> |
| 25 |
#include <errno.h> |
26 |
#include <errno.h> |
| 26 |
#include <glob.h> |
27 |
#include <glob.h> |
| 27 |
#include <histedit.h> |
28 |
#include <histedit.h> |
|
Lines 334-477
infer_path(const char *p, char **ifp)
Link Here
|
| 334 |
} |
335 |
} |
| 335 |
|
336 |
|
| 336 |
static int |
337 |
static int |
| 337 |
parse_getput_flags(const char **cpp, int *pflag) |
338 |
parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag) |
| 338 |
{ |
339 |
{ |
| 339 |
const char *cp = *cpp; |
340 |
extern int optind, optreset, opterr; |
|
|
341 |
int ch; |
| 340 |
|
342 |
|
| 341 |
/* Check for flags */ |
343 |
optind = optreset = 1; |
| 342 |
if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) { |
344 |
opterr = 0; |
| 343 |
switch (cp[1]) { |
345 |
|
|
|
346 |
*pflag = 0; |
| 347 |
while ((ch = getopt(argc, argv, "Pp")) != -1) { |
| 348 |
switch (ch) { |
| 344 |
case 'p': |
349 |
case 'p': |
| 345 |
case 'P': |
350 |
case 'P': |
| 346 |
*pflag = 1; |
351 |
*pflag = 1; |
| 347 |
break; |
352 |
break; |
| 348 |
default: |
353 |
default: |
| 349 |
error("Invalid flag -%c", cp[1]); |
354 |
error("%s: Invalid flag -%c", cmd, ch); |
| 350 |
return(-1); |
355 |
return -1; |
| 351 |
} |
|
|
| 352 |
cp += 2; |
| 353 |
*cpp = cp + strspn(cp, WHITESPACE); |
| 354 |
} |
| 355 |
|
| 356 |
return(0); |
| 357 |
} |
| 358 |
|
| 359 |
static int |
| 360 |
parse_ls_flags(const char **cpp, int *lflag) |
| 361 |
{ |
| 362 |
const char *cp = *cpp; |
| 363 |
|
| 364 |
/* Defaults */ |
| 365 |
*lflag = LS_NAME_SORT; |
| 366 |
|
| 367 |
/* Check for flags */ |
| 368 |
if (cp++[0] == '-') { |
| 369 |
for (; strchr(WHITESPACE, *cp) == NULL; cp++) { |
| 370 |
switch (*cp) { |
| 371 |
case 'l': |
| 372 |
*lflag &= ~VIEW_FLAGS; |
| 373 |
*lflag |= LS_LONG_VIEW; |
| 374 |
break; |
| 375 |
case '1': |
| 376 |
*lflag &= ~VIEW_FLAGS; |
| 377 |
*lflag |= LS_SHORT_VIEW; |
| 378 |
break; |
| 379 |
case 'n': |
| 380 |
*lflag &= ~VIEW_FLAGS; |
| 381 |
*lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW; |
| 382 |
break; |
| 383 |
case 'S': |
| 384 |
*lflag &= ~SORT_FLAGS; |
| 385 |
*lflag |= LS_SIZE_SORT; |
| 386 |
break; |
| 387 |
case 't': |
| 388 |
*lflag &= ~SORT_FLAGS; |
| 389 |
*lflag |= LS_TIME_SORT; |
| 390 |
break; |
| 391 |
case 'r': |
| 392 |
*lflag |= LS_REVERSE_SORT; |
| 393 |
break; |
| 394 |
case 'f': |
| 395 |
*lflag &= ~SORT_FLAGS; |
| 396 |
break; |
| 397 |
case 'a': |
| 398 |
*lflag |= LS_SHOW_ALL; |
| 399 |
break; |
| 400 |
default: |
| 401 |
error("Invalid flag -%c", *cp); |
| 402 |
return(-1); |
| 403 |
} |
| 404 |
} |
356 |
} |
| 405 |
*cpp = cp + strspn(cp, WHITESPACE); |
|
|
| 406 |
} |
357 |
} |
| 407 |
|
358 |
|
| 408 |
return(0); |
359 |
return optind; |
| 409 |
} |
360 |
} |
| 410 |
|
361 |
|
| 411 |
static int |
362 |
static int |
| 412 |
get_pathname(const char **cpp, char **path) |
363 |
parse_ls_flags(char **argv, int argc, int *lflag) |
| 413 |
{ |
364 |
{ |
| 414 |
const char *cp = *cpp, *end; |
365 |
extern int optind, optreset, opterr; |
| 415 |
char quot; |
366 |
int ch; |
| 416 |
u_int i, j; |
|
|
| 417 |
|
| 418 |
cp += strspn(cp, WHITESPACE); |
| 419 |
if (!*cp) { |
| 420 |
*cpp = cp; |
| 421 |
*path = NULL; |
| 422 |
return (0); |
| 423 |
} |
| 424 |
|
367 |
|
| 425 |
*path = xmalloc(strlen(cp) + 1); |
368 |
optind = optreset = 1; |
|
|
369 |
opterr = 0; |
| 426 |
|
370 |
|
| 427 |
/* Check for quoted filenames */ |
371 |
*lflag = LS_NAME_SORT; |
| 428 |
if (*cp == '\"' || *cp == '\'') { |
372 |
while ((ch = getopt(argc, argv, "1Saflnrt")) != -1) { |
| 429 |
quot = *cp++; |
373 |
switch (ch) { |
| 430 |
|
374 |
case '1': |
| 431 |
/* Search for terminating quote, unescape some chars */ |
375 |
*lflag &= ~VIEW_FLAGS; |
| 432 |
for (i = j = 0; i <= strlen(cp); i++) { |
376 |
*lflag |= LS_SHORT_VIEW; |
| 433 |
if (cp[i] == quot) { /* Found quote */ |
377 |
break; |
| 434 |
i++; |
378 |
case 'S': |
| 435 |
(*path)[j] = '\0'; |
379 |
*lflag &= ~SORT_FLAGS; |
| 436 |
break; |
380 |
*lflag |= LS_SIZE_SORT; |
| 437 |
} |
381 |
break; |
| 438 |
if (cp[i] == '\0') { /* End of string */ |
382 |
case 'a': |
| 439 |
error("Unterminated quote"); |
383 |
*lflag |= LS_SHOW_ALL; |
| 440 |
goto fail; |
384 |
break; |
| 441 |
} |
385 |
case 'f': |
| 442 |
if (cp[i] == '\\') { /* Escaped characters */ |
386 |
*lflag &= ~SORT_FLAGS; |
| 443 |
i++; |
387 |
break; |
| 444 |
if (cp[i] != '\'' && cp[i] != '\"' && |
388 |
case 'l': |
| 445 |
cp[i] != '\\') { |
389 |
*lflag &= ~VIEW_FLAGS; |
| 446 |
error("Bad escaped character '\\%c'", |
390 |
*lflag |= LS_LONG_VIEW; |
| 447 |
cp[i]); |
391 |
break; |
| 448 |
goto fail; |
392 |
case 'n': |
| 449 |
} |
393 |
*lflag &= ~VIEW_FLAGS; |
| 450 |
} |
394 |
*lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW; |
| 451 |
(*path)[j++] = cp[i]; |
395 |
break; |
|
|
396 |
case 'r': |
| 397 |
*lflag |= LS_REVERSE_SORT; |
| 398 |
break; |
| 399 |
case 't': |
| 400 |
*lflag &= ~SORT_FLAGS; |
| 401 |
*lflag |= LS_TIME_SORT; |
| 402 |
break; |
| 403 |
default: |
| 404 |
error("ls: Invalid flag -%c", ch); |
| 405 |
return -1; |
| 452 |
} |
406 |
} |
| 453 |
|
|
|
| 454 |
if (j == 0) { |
| 455 |
error("Empty quotes"); |
| 456 |
goto fail; |
| 457 |
} |
| 458 |
*cpp = cp + i + strspn(cp + i, WHITESPACE); |
| 459 |
} else { |
| 460 |
/* Read to end of filename */ |
| 461 |
end = strpbrk(cp, WHITESPACE); |
| 462 |
if (end == NULL) |
| 463 |
end = strchr(cp, '\0'); |
| 464 |
*cpp = end + strspn(end, WHITESPACE); |
| 465 |
|
| 466 |
memcpy(*path, cp, end - cp); |
| 467 |
(*path)[end - cp] = '\0'; |
| 468 |
} |
407 |
} |
| 469 |
return (0); |
|
|
| 470 |
|
408 |
|
| 471 |
fail: |
409 |
return optind; |
| 472 |
xfree(*path); |
|
|
| 473 |
*path = NULL; |
| 474 |
return (-1); |
| 475 |
} |
410 |
} |
| 476 |
|
411 |
|
| 477 |
static int |
412 |
static int |
|
Lines 854-868
do_globbed_ls(struct sftp_conn *conn, ch
Link Here
|
| 854 |
return (0); |
789 |
return (0); |
| 855 |
} |
790 |
} |
| 856 |
|
791 |
|
|
|
792 |
/* |
| 793 |
* Undo escaping of glob sequences in place. Used to undo extra escaping |
| 794 |
* applied in makeargv() when the string is destined for a function that |
| 795 |
* does not glob it. |
| 796 |
*/ |
| 797 |
static void |
| 798 |
undo_glob_escape(char *s) |
| 799 |
{ |
| 800 |
size_t i, j; |
| 801 |
|
| 802 |
for (i = j = 0;;) { |
| 803 |
if (s[i] == '\0') { |
| 804 |
s[j] = '\0'; |
| 805 |
return; |
| 806 |
} |
| 807 |
if (s[i] != '\\') { |
| 808 |
s[j++] = s[i++]; |
| 809 |
continue; |
| 810 |
} |
| 811 |
/* s[i] == '\\' */ |
| 812 |
++i; |
| 813 |
switch (s[i]) { |
| 814 |
case '?': |
| 815 |
case '[': |
| 816 |
case '*': |
| 817 |
case '\\': |
| 818 |
s[j++] = s[i++]; |
| 819 |
break; |
| 820 |
case '\0': |
| 821 |
s[j++] = '\\'; |
| 822 |
s[j] = '\0'; |
| 823 |
return; |
| 824 |
default: |
| 825 |
s[j++] = '\\'; |
| 826 |
s[j++] = s[i++]; |
| 827 |
break; |
| 828 |
} |
| 829 |
} |
| 830 |
} |
| 831 |
|
| 832 |
/* |
| 833 |
* Split a string into an argument vector using sh(1)-style quoting, |
| 834 |
* comment and escaping rules, but with some tweaks to handle glob(3) |
| 835 |
* wildcards. |
| 836 |
* Returns NULL on error or up to MAXARGS in static buffer (NULL terminated) |
| 837 |
*/ |
| 838 |
#define MAXARGS 128 |
| 839 |
#define MAXARGLEN 8192 |
| 840 |
static char ** |
| 841 |
makeargv(const char *arg, int *argcp) |
| 842 |
{ |
| 843 |
int argc, quot; |
| 844 |
size_t i, j; |
| 845 |
static char argvs[MAXARGLEN]; |
| 846 |
static char *argv[MAXARGS + 1]; |
| 847 |
enum { MA_START, MA_SQUOTE, MA_DQUOTE, MA_UNQUOTED } state, q; |
| 848 |
|
| 849 |
*argcp = argc = 0; |
| 850 |
if (strlen(arg) > sizeof(argvs) - 1) { |
| 851 |
args_too_longs: |
| 852 |
error("string too long"); |
| 853 |
return NULL; |
| 854 |
} |
| 855 |
state = MA_START; |
| 856 |
i = j = 0; |
| 857 |
for (;;) { |
| 858 |
if (isspace(arg[i])) { |
| 859 |
if (state == MA_UNQUOTED) { |
| 860 |
/* Terminate current argument */ |
| 861 |
argvs[j++] = '\0'; |
| 862 |
argc++; |
| 863 |
state = MA_START; |
| 864 |
} else if (state != MA_START) |
| 865 |
argvs[j++] = arg[i]; |
| 866 |
} else if (arg[i] == '"' || arg[i] == '\'') { |
| 867 |
q = arg[i] == '"' ? MA_DQUOTE : MA_SQUOTE; |
| 868 |
if (state == MA_START) { |
| 869 |
argv[argc] = argvs + j; |
| 870 |
state = q; |
| 871 |
} else if (state == MA_UNQUOTED) |
| 872 |
state = q; |
| 873 |
else if (state == q) |
| 874 |
state = MA_UNQUOTED; |
| 875 |
else |
| 876 |
argvs[j++] = arg[i]; |
| 877 |
} else if (arg[i] == '\\') { |
| 878 |
if (state == MA_SQUOTE || state == MA_DQUOTE) { |
| 879 |
quot = state == MA_SQUOTE ? '\'' : '"'; |
| 880 |
/* Unescape quote we are in */ |
| 881 |
/* XXX support \n and friends? */ |
| 882 |
if (arg[i + 1] == quot) { |
| 883 |
i++; |
| 884 |
argvs[j++] = arg[i]; |
| 885 |
} else if (arg[i + 1] == '?' || |
| 886 |
arg[i + 1] == '[' || arg[i + 1] == '*') { |
| 887 |
/* |
| 888 |
* Special case for sftp: append |
| 889 |
* double-escaped glob sequence - |
| 890 |
* glob will undo one level of |
| 891 |
* escaping. NB. string can grow here. |
| 892 |
*/ |
| 893 |
if (j >= sizeof(argvs) - 5) |
| 894 |
goto args_too_longs; |
| 895 |
argvs[j++] = '\\'; |
| 896 |
argvs[j++] = arg[i++]; |
| 897 |
argvs[j++] = '\\'; |
| 898 |
argvs[j++] = arg[i]; |
| 899 |
} else { |
| 900 |
argvs[j++] = arg[i++]; |
| 901 |
argvs[j++] = arg[i]; |
| 902 |
} |
| 903 |
} else { |
| 904 |
if (state == MA_START) { |
| 905 |
argv[argc] = argvs + j; |
| 906 |
state = MA_UNQUOTED; |
| 907 |
} |
| 908 |
if (arg[i + 1] == '?' || arg[i + 1] == '[' || |
| 909 |
arg[i + 1] == '*' || arg[i + 1] == '\\') { |
| 910 |
/* |
| 911 |
* Special case for sftp: append |
| 912 |
* escaped glob sequence - |
| 913 |
* glob will undo one level of |
| 914 |
* escaping. |
| 915 |
*/ |
| 916 |
argvs[j++] = arg[i++]; |
| 917 |
argvs[j++] = arg[i]; |
| 918 |
} else { |
| 919 |
/* Unescape everything */ |
| 920 |
/* XXX support \n and friends? */ |
| 921 |
i++; |
| 922 |
argvs[j++] = arg[i]; |
| 923 |
} |
| 924 |
} |
| 925 |
} else if (arg[i] == '#') { |
| 926 |
if (state == MA_SQUOTE || state == MA_DQUOTE) |
| 927 |
argvs[j++] = arg[i]; |
| 928 |
else |
| 929 |
goto string_done; |
| 930 |
} else if (arg[i] == '\0') { |
| 931 |
if (state == MA_SQUOTE || state == MA_DQUOTE) { |
| 932 |
error("Unterminated quoted argument"); |
| 933 |
return NULL; |
| 934 |
} |
| 935 |
string_done: |
| 936 |
if (state == MA_UNQUOTED) { |
| 937 |
argvs[j++] = '\0'; |
| 938 |
argc++; |
| 939 |
} |
| 940 |
break; |
| 941 |
} else { |
| 942 |
if (state == MA_START) { |
| 943 |
argv[argc] = argvs + j; |
| 944 |
state = MA_UNQUOTED; |
| 945 |
} |
| 946 |
if ((state == MA_SQUOTE || state == MA_DQUOTE) && |
| 947 |
(arg[i] == '?' || arg[i] == '[' || arg[i] == '*')) { |
| 948 |
/* |
| 949 |
* Special case for sftp: escape quoted |
| 950 |
* glob(3) wildcards. NB. string can grow |
| 951 |
* here. |
| 952 |
*/ |
| 953 |
if (j >= sizeof(argvs) - 3) |
| 954 |
goto args_too_longs; |
| 955 |
argvs[j++] = '\\'; |
| 956 |
argvs[j++] = arg[i]; |
| 957 |
} else |
| 958 |
argvs[j++] = arg[i]; |
| 959 |
} |
| 960 |
i++; |
| 961 |
} |
| 962 |
*argcp = argc; |
| 963 |
return argv; |
| 964 |
} |
| 965 |
|
| 857 |
static int |
966 |
static int |
| 858 |
parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, |
967 |
parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, |
| 859 |
unsigned long *n_arg, char **path1, char **path2) |
968 |
unsigned long *n_arg, char **path1, char **path2) |
| 860 |
{ |
969 |
{ |
| 861 |
const char *cmd, *cp = *cpp; |
970 |
const char *cmd, *cp = *cpp; |
| 862 |
char *cp2; |
971 |
char *cp2, **argv; |
| 863 |
int base = 0; |
972 |
int base = 0; |
| 864 |
long l; |
973 |
long l; |
| 865 |
int i, cmdnum; |
974 |
int i, cmdnum, optidx, argc; |
| 866 |
|
975 |
|
| 867 |
/* Skip leading whitespace */ |
976 |
/* Skip leading whitespace */ |
| 868 |
cp = cp + strspn(cp, WHITESPACE); |
977 |
cp = cp + strspn(cp, WHITESPACE); |
|
Lines 878-894
parse_args(const char **cpp, int *pflag,
Link Here
|
| 878 |
cp++; |
987 |
cp++; |
| 879 |
} |
988 |
} |
| 880 |
|
989 |
|
| 881 |
/* Figure out which command we have */ |
990 |
if ((argv = makeargv(cp, &argc)) == NULL) |
| 882 |
for (i = 0; cmds[i].c; i++) { |
991 |
return -1; |
| 883 |
int cmdlen = strlen(cmds[i].c); |
|
|
| 884 |
|
992 |
|
| 885 |
/* Check for command followed by whitespace */ |
993 |
/* Figure out which command we have */ |
| 886 |
if (!strncasecmp(cp, cmds[i].c, cmdlen) && |
994 |
for (i = 0; cmds[i].c != NULL; i++) { |
| 887 |
strchr(WHITESPACE, cp[cmdlen])) { |
995 |
if (strcasecmp(cmds[i].c, argv[0]) == 0) |
| 888 |
cp += cmdlen; |
|
|
| 889 |
cp = cp + strspn(cp, WHITESPACE); |
| 890 |
break; |
996 |
break; |
| 891 |
} |
|
|
| 892 |
} |
997 |
} |
| 893 |
cmdnum = cmds[i].n; |
998 |
cmdnum = cmds[i].n; |
| 894 |
cmd = cmds[i].c; |
999 |
cmd = cmds[i].c; |
|
Lines 899-938
parse_args(const char **cpp, int *pflag,
Link Here
|
| 899 |
cmdnum = I_SHELL; |
1004 |
cmdnum = I_SHELL; |
| 900 |
} else if (cmdnum == -1) { |
1005 |
} else if (cmdnum == -1) { |
| 901 |
error("Invalid command."); |
1006 |
error("Invalid command."); |
| 902 |
return (-1); |
1007 |
return -1; |
| 903 |
} |
1008 |
} |
| 904 |
|
1009 |
|
| 905 |
/* Get arguments and parse flags */ |
1010 |
/* Get arguments and parse flags */ |
| 906 |
*lflag = *pflag = *n_arg = 0; |
1011 |
*lflag = *pflag = *n_arg = 0; |
| 907 |
*path1 = *path2 = NULL; |
1012 |
*path1 = *path2 = NULL; |
|
|
1013 |
optidx = 1; |
| 908 |
switch (cmdnum) { |
1014 |
switch (cmdnum) { |
| 909 |
case I_GET: |
1015 |
case I_GET: |
| 910 |
case I_PUT: |
1016 |
case I_PUT: |
| 911 |
if (parse_getput_flags(&cp, pflag)) |
1017 |
if ((optidx = parse_getput_flags(cmd, argv, argc, pflag)) == -1) |
| 912 |
return(-1); |
1018 |
return -1; |
| 913 |
/* Get first pathname (mandatory) */ |
1019 |
/* Get first pathname (mandatory) */ |
| 914 |
if (get_pathname(&cp, path1)) |
1020 |
if (argc - optidx < 1) { |
| 915 |
return(-1); |
|
|
| 916 |
if (*path1 == NULL) { |
| 917 |
error("You must specify at least one path after a " |
1021 |
error("You must specify at least one path after a " |
| 918 |
"%s command.", cmd); |
1022 |
"%s command.", cmd); |
| 919 |
return(-1); |
1023 |
return -1; |
|
|
1024 |
} |
| 1025 |
*path1 = xstrdup(argv[optidx]); |
| 1026 |
/* Get second pathname (optional) */ |
| 1027 |
if (argc - optidx > 1) { |
| 1028 |
*path2 = xstrdup(argv[optidx + 1]); |
| 1029 |
/* Destination is not globbed */ |
| 1030 |
undo_glob_escape(*path2); |
| 920 |
} |
1031 |
} |
| 921 |
/* Try to get second pathname (optional) */ |
|
|
| 922 |
if (get_pathname(&cp, path2)) |
| 923 |
return(-1); |
| 924 |
break; |
1032 |
break; |
| 925 |
case I_RENAME: |
1033 |
case I_RENAME: |
| 926 |
case I_SYMLINK: |
1034 |
case I_SYMLINK: |
| 927 |
if (get_pathname(&cp, path1)) |
1035 |
if (argc - optidx < 2) { |
| 928 |
return(-1); |
|
|
| 929 |
if (get_pathname(&cp, path2)) |
| 930 |
return(-1); |
| 931 |
if (!*path1 || !*path2) { |
| 932 |
error("You must specify two paths after a %s " |
1036 |
error("You must specify two paths after a %s " |
| 933 |
"command.", cmd); |
1037 |
"command.", cmd); |
| 934 |
return(-1); |
1038 |
return -1; |
| 935 |
} |
1039 |
} |
|
|
1040 |
*path1 = xstrdup(argv[optidx]); |
| 1041 |
*path2 = xstrdup(argv[optidx + 1]); |
| 1042 |
/* Paths are not globbed */ |
| 1043 |
undo_glob_escape(*path1); |
| 1044 |
undo_glob_escape(*path2); |
| 936 |
break; |
1045 |
break; |
| 937 |
case I_RM: |
1046 |
case I_RM: |
| 938 |
case I_MKDIR: |
1047 |
case I_MKDIR: |
|
Lines 941-999
parse_args(const char **cpp, int *pflag,
Link Here
|
| 941 |
case I_LCHDIR: |
1050 |
case I_LCHDIR: |
| 942 |
case I_LMKDIR: |
1051 |
case I_LMKDIR: |
| 943 |
/* Get pathname (mandatory) */ |
1052 |
/* Get pathname (mandatory) */ |
| 944 |
if (get_pathname(&cp, path1)) |
1053 |
if (argc - optidx < 1) { |
| 945 |
return(-1); |
|
|
| 946 |
if (*path1 == NULL) { |
| 947 |
error("You must specify a path after a %s command.", |
1054 |
error("You must specify a path after a %s command.", |
| 948 |
cmd); |
1055 |
cmd); |
| 949 |
return(-1); |
1056 |
return -1; |
| 950 |
} |
1057 |
} |
|
|
1058 |
*path1 = xstrdup(argv[optidx]); |
| 1059 |
/* Only "rm" globs */ |
| 1060 |
if (cmdnum != I_RM) |
| 1061 |
undo_glob_escape(*path1); |
| 951 |
break; |
1062 |
break; |
| 952 |
case I_LS: |
1063 |
case I_LS: |
| 953 |
if (parse_ls_flags(&cp, lflag)) |
1064 |
if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1) |
| 954 |
return(-1); |
1065 |
return(-1); |
| 955 |
/* Path is optional */ |
1066 |
/* Path is optional */ |
| 956 |
if (get_pathname(&cp, path1)) |
1067 |
if (argc - optidx > 0) |
| 957 |
return(-1); |
1068 |
*path1 = xstrdup(argv[optidx]); |
| 958 |
break; |
1069 |
break; |
| 959 |
case I_LLS: |
1070 |
case I_LLS: |
| 960 |
case I_SHELL: |
1071 |
case I_SHELL: |
| 961 |
/* Uses the rest of the line */ |
1072 |
/* Uses the rest of the line */ |
| 962 |
break; |
1073 |
break; |
| 963 |
case I_LUMASK: |
1074 |
case I_LUMASK: |
| 964 |
base = 8; |
|
|
| 965 |
case I_CHMOD: |
1075 |
case I_CHMOD: |
| 966 |
base = 8; |
1076 |
base = 8; |
| 967 |
case I_CHOWN: |
1077 |
case I_CHOWN: |
| 968 |
case I_CHGRP: |
1078 |
case I_CHGRP: |
| 969 |
/* Get numeric arg (mandatory) */ |
1079 |
/* Get numeric arg (mandatory) */ |
|
|
1080 |
if (argc - optidx < 1) |
| 1081 |
goto need_num_arg; |
| 970 |
errno = 0; |
1082 |
errno = 0; |
| 971 |
l = strtol(cp, &cp2, base); |
1083 |
l = strtol(argv[optidx], &cp2, base); |
| 972 |
if (cp2 == cp || ((l == LONG_MIN || l == LONG_MAX) && |
1084 |
if (cp2 == argv[optidx] || *cp2 != '\0' || |
| 973 |
errno == ERANGE) || l < 0) { |
1085 |
((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) || |
|
|
1086 |
l < 0) { |
| 1087 |
need_num_arg: |
| 974 |
error("You must supply a numeric argument " |
1088 |
error("You must supply a numeric argument " |
| 975 |
"to the %s command.", cmd); |
1089 |
"to the %s command.", cmd); |
| 976 |
return(-1); |
1090 |
return -1; |
| 977 |
} |
1091 |
} |
| 978 |
cp = cp2; |
|
|
| 979 |
*n_arg = l; |
1092 |
*n_arg = l; |
| 980 |
if (cmdnum == I_LUMASK && strchr(WHITESPACE, *cp)) |
1093 |
if (cmdnum == I_LUMASK) |
| 981 |
break; |
1094 |
break; |
| 982 |
if (cmdnum == I_LUMASK || !strchr(WHITESPACE, *cp)) { |
|
|
| 983 |
error("You must supply a numeric argument " |
| 984 |
"to the %s command.", cmd); |
| 985 |
return(-1); |
| 986 |
} |
| 987 |
cp += strspn(cp, WHITESPACE); |
| 988 |
|
| 989 |
/* Get pathname (mandatory) */ |
1095 |
/* Get pathname (mandatory) */ |
| 990 |
if (get_pathname(&cp, path1)) |
1096 |
if (argc - optidx < 2) { |
| 991 |
return(-1); |
|
|
| 992 |
if (*path1 == NULL) { |
| 993 |
error("You must specify a path after a %s command.", |
1097 |
error("You must specify a path after a %s command.", |
| 994 |
cmd); |
1098 |
cmd); |
| 995 |
return(-1); |
1099 |
return -1; |
| 996 |
} |
1100 |
} |
|
|
1101 |
*path1 = xstrdup(argv[optidx + 1]); |
| 997 |
break; |
1102 |
break; |
| 998 |
case I_QUIT: |
1103 |
case I_QUIT: |
| 999 |
case I_PWD: |
1104 |
case I_PWD: |