/* * Read and parse an interactive command. * The first word on the line is assigned to "cmd". If * there are no arguments on the command line, then "curdir" * is returned as the argument. If there are arguments * on the line they are returned one at a time on each * successive call to getcmd. Each argument is first assigned * to "name". If it does not start with "/" the pathname in * "curdir" is prepended to it. Finally "canon" is called to * eliminate any embedded ".." components. */ static void getcmd(char *curdir, char *cmd, char *name, size_t size, struct arglist *ap) { char *cp; static char input[BUFSIZ]; char output[BUFSIZ]; # define rawname input /* save space by reusing input buffer */ /* * Check to see if still processing arguments. */ if (ap->argcnt > 0) goto retnext; if (nextarg != NULL) goto getnext; /* * Read a command line and trim off trailing white space. */ do { fprintf(stderr, "restore > "); fflush(stderr); if (fgets(input, BUFSIZ, terminal) == NULL) { strcpy(cmd, "quit"); return; } } while (input[0] == '\n'); for (cp = &input[strlen(input) - 2]; *cp == ' ' || *cp == '\t'; cp--) /* trim off trailing white space and newline */; *++cp = '\0'; /* * Copy the command into "cmd". */ cp = copynext(input, cmd); ap->cmd = cmd; /* * If no argument, use curdir as the default. */ if (*cp == '\0') { strncpy(name, curdir, size); name[size - 1] = '\0'; return; } nextarg = cp; /* * Find the next argument. */ getnext: cp = copynext(nextarg, rawname); if (*cp == '\0') nextarg = NULL; else nextarg = cp; /* * If it is an absolute pathname, canonicalize it and return it. */ if (rawname[0] == '/') { canon(rawname, name, size); } else { /* * For relative pathnames, prepend the current directory to * it then canonicalize and return it. */ snprintf(output, sizeof(output), "%s/%s", curdir, rawname); canon(output, name, size); } if (glob(name, GLOB_ALTDIRFUNC, NULL, &ap->glob) < 0) fprintf(stderr, "%s: out of memory\n", ap->cmd); if (ap->glob.gl_pathc == 0) return; ap->freeglob = 1; ap->argcnt = ap->glob.gl_pathc; retnext: strncpy(name, ap->glob.gl_pathv[ap->glob.gl_pathc - ap->argcnt], size); name[size - 1] = '\0'; if (--ap->argcnt == 0) { ap->freeglob = 0; globfree(&ap->glob); } # undef rawname }
/* * Read and parse an interactive command. * The first word on the line is assigned to "cmd". If * there are no arguments on the command line, then "curdir" * is returned as the argument. If there are arguments * on the line they are returned one at a time on each * successive call to getcmd. Each argument is first assigned * to "name". If it does not start with "/" the pathname in * "curdir" is prepended to it. Finally "canon" is called to * eliminate any embedded ".." components. */ static void getcmd(char *curdir, char *cmd, size_t cmdlen, char *name, size_t namelen, struct arglist *ap) { char *cp; static char input[BUFSIZ]; char output[BUFSIZ]; # define rawname input /* save space by reusing input buffer */ int globretval; /* * Check to see if still processing arguments. */ if (ap->argcnt > 0) goto retnext; if (nextarg != NULL) goto getnext; /* * Read a command line and trim off trailing white space. */ do { (void)fprintf(stderr, "%s > ", __progname); (void)fflush(stderr); if (fgets(input, sizeof input, terminal) == NULL) { (void)strlcpy(cmd, "quit", cmdlen); return; } } while (input[0] == '\n' || input[0] == '\0'); for (cp = &input[strlen(input) - 1]; cp >= input && (*cp == ' ' || *cp == '\t' || *cp == '\n'); cp--) /* trim off trailing white space and newline */; *++cp = '\0'; /* * Copy the command into "cmd". */ cp = copynext(input, cmd); ap->cmd = cmd; /* * If no argument, use curdir as the default. */ if (*cp == '\0') { (void)strlcpy(name, curdir, MAXPATHLEN); return; } nextarg = cp; /* * Find the next argument. */ getnext: cp = copynext(nextarg, rawname); if (*cp == '\0') nextarg = NULL; else nextarg = cp; /* * If it is an absolute pathname, canonicalize it and return it. */ if (rawname[0] == '/') { canon(rawname, name, namelen); } else { /* * For relative pathnames, prepend the current directory to * it then canonicalize and return it. */ snprintf(output, sizeof(output), "%s/%s", curdir, rawname); canon(output, name, namelen); } if ((globretval = glob(name, GLOB_ALTDIRFUNC | GLOB_NOESCAPE, NULL, &ap->glob)) < 0) { fprintf(stderr, "%s: %s: ", ap->cmd, name); switch (globretval) { case GLOB_NOSPACE: fprintf(stderr, "out of memory\n"); break; case GLOB_NOMATCH: fprintf(stderr, "no filename match.\n"); break; case GLOB_ABORTED: fprintf(stderr, "glob() aborted.\n"); break; default: fprintf(stderr, "unknown error!\n"); break; } } if (ap->glob.gl_pathc == 0) return; ap->freeglob = 1; ap->argcnt = ap->glob.gl_pathc; retnext: strlcpy(name, ap->glob.gl_pathv[ap->glob.gl_pathc - ap->argcnt], MAXPATHLEN); if (--ap->argcnt == 0) { ap->freeglob = 0; globfree(&ap->glob); } # undef rawname }