int cmd_rmmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { int ret; /* Usage: rmmod <modulename> */ /* Remove the module */ ret = rmmod(argv[1]); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "rmmod", NSH_ERRNO); return ERROR; } return OK; }
int cmd_rmdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { char *fullpath = nsh_getfullpath(vtbl, argv[1]); int ret = ERROR; if (fullpath) { ret = rmdir(fullpath); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "rmdir", NSH_ERRNO); } nsh_freefullpath(fullpath); } return ret; }
int cmd_insmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { int ret; /* Usage: insmod <filepath> <modulename> */ /* Install the module */ ret = insmod(argv[1], argv[2]); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "insmod", NSH_ERRNO); return ERROR; } return OK; }
int cmd_mkfatfs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { struct fat_format_s fmt = FAT_FORMAT_INITIALIZER; char *fullpath = nsh_getfullpath(vtbl, argv[1]); int ret = ERROR; if (fullpath) { ret = mkfatfs(fullpath, &fmt); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mkfatfs", NSH_ERRNO); } nsh_freefullpath(fullpath); } return ret; }
int cmd_umount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { char *fullpath = nsh_getfullpath(vtbl, argv[1]); int ret = ERROR; if (fullpath) { /* Perform the umount */ ret = umount(fullpath); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "umount", NSH_ERRNO); } nsh_freefullpath(fullpath); } return ret; }
static inline int nsh_nice(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, FAR char **saveptr) { FAR char *cmd = *ppcmd; vtbl->np.np_nice = 0; if (cmd) { /* Check if the command is preceded by "nice" */ if (strcmp(cmd, "nice") == 0) { /* Nicenesses range from -20 (most favorable scheduling) to 19 * (least favorable). Default is 10. */ vtbl->np.np_nice = 10; /* Get the cmd (or -d option of nice command) */ cmd = nsh_argument(vtbl, saveptr); if (cmd && strcmp(cmd, "-d") == 0) { FAR char *val = nsh_argument(vtbl, saveptr); if (val) { char *endptr; vtbl->np.np_nice = (int)strtol(val, &endptr, 0); if (vtbl->np.np_nice > 19 || vtbl->np.np_nice < -20 || endptr == val || *endptr != '\0') { nsh_output(vtbl, g_fmtarginvalid, "nice"); return ERROR; } cmd = nsh_argument(vtbl, saveptr); } } /* Return the real command name */ *ppcmd = cmd; } } return OK; }
static int dd_readblk(struct dd_s *dd) { ssize_t nbytes; off_t offset = dd->sector * dd->sectsize; nbytes = bchlib_read(DD_INHANDLE, (char*)dd->buffer, offset, dd->sectsize); if (nbytes < 0) { FAR struct nsh_vtbl_s *vtbl = dd->vtbl; nsh_output(vtbl, g_fmtcmdfailed, g_dd, "bshlib_read", NSH_ERRNO_OF(-nbytes)); return ERROR; } /* bchlib_read return 0 on attempts to write past the end of the device. */ dd->nbytes = nbytes; dd->eof = (nbytes == 0); return OK; }
static inline int dd_outfopen(const char *name, struct dd_s *dd) { int type; int ret = OK; /* Get the type of the output file */ type = dd_filetype(name); /* Open the block driver for input */ if (type == true) { ret = bchlib_setup(name, true, &DD_OUTHANDLE); if (ret < 0) { return ERROR; } dd->outfwrite = dd_writeblk; /* Block oriented write */ dd->outfclose = dd_outfcloseblk; } /* Otherwise, the file is character oriented or does not exist */ else { DD_OUTFD = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0644); if (DD_OUTFD < 0) { FAR struct nsh_vtbl_s *vtbl = dd->vtbl; nsh_output(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO); return ERROR; } dd->outfwrite = dd_writech; /* Character oriented write */ dd->outfclose = dd_outfclosech; } return OK; }
static int dd_readch(struct dd_s *dd) { uint8_t *buffer = dd->buffer; ssize_t nbytes; dd->nbytes = 0; do { nbytes = read(DD_INFD, buffer, dd->sectsize - dd->nbytes); if (nbytes < 0) { FAR struct nsh_vtbl_s *vtbl = dd->vtbl; nsh_output(vtbl, g_fmtcmdfailed, g_dd, "read", NSH_ERRNO_OF(-nbytes)); return ERROR; } dd->nbytes += nbytes; buffer += nbytes; } while (dd->nbytes < dd->sectsize && nbytes > 0); dd->eof |= (dd->nbytes == 0); return OK; }
int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { const char *relpath; unsigned int lsflags = 0; char *fullpath; bool badarg = false; int ret; /* Get the ls options */ int option; while ((option = getopt(argc, argv, "lRs")) != ERROR) { switch (option) { case 'l': lsflags |= (LSFLAGS_SIZE|LSFLAGS_LONG); break; case 'R': lsflags |= LSFLAGS_RECURSIVE; break; case 's': lsflags |= LSFLAGS_SIZE; break; case '?': default: nsh_output(vtbl, g_fmtarginvalid, argv[0]); badarg = true; break; } } /* If a bad argument was encountered, then return without processing the command */ if (badarg) { return ERROR; } /* There may be one argument after the options */ if (optind + 1 < argc) { nsh_output(vtbl, g_fmttoomanyargs, argv[0]); return ERROR; } else if (optind >= argc) { #ifndef CONFIG_DISABLE_ENVIRON relpath = nsh_getcwd(); #else nsh_output(vtbl, g_fmtargrequired, argv[0]); return ERROR; #endif } else { relpath = argv[optind]; } /* Get the fullpath to the directory */ fullpath = nsh_getfullpath(vtbl, relpath); if (!fullpath) { return ERROR; } /* List the directory contents */ nsh_output(vtbl, "%s:\n", fullpath); ret = foreach_direntry(vtbl, "ls", fullpath, ls_handler, (void*)lsflags); if (ret == OK && (lsflags & LSFLAGS_RECURSIVE) != 0) { /* Then recurse to list each directory within the directory */ ret = foreach_direntry(vtbl, "ls", fullpath, ls_recursive, (void*)lsflags); } nsh_freefullpath(fullpath); return ret; }
int cmd_nfsmount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { struct nfs_args data; FAR char *address; FAR char *lpath; FAR char *rpath; bool badarg = false; #ifdef CONFIG_NET_IPv6 FAR struct sockaddr_in6 *sin; struct in6_addr inaddr; #else FAR struct sockaddr_in *sin; struct in_addr inaddr; #endif int ret; /* If a bad argument was encountered, then return without processing the * command. */ if (badarg) { return ERROR; } /* The fist argument on the command line should be the NFS server IP address * in standard IPv4 (or IPv6) dot format. */ address = argv[1]; if (!address) { return ERROR; } /* The local mount point path (lpath) might be relative to the current working * directory. */ lpath = nsh_getfullpath(vtbl, argv[2]); if (!lpath) { return ERROR; } /* Get the remote mount point path */ rpath = argv[3]; /* Convert the IP address string into its binary form */ #ifdef CONFIG_NET_IPv6 ret = inet_pton(AF_INET6, address, &inaddr); #else ret = inet_pton(AF_INET, address, &inaddr); #endif if (ret != 1) { nsh_freefullpath(lpath); return ERROR; } /* Place all of the NFS arguements into the nfs_args structure */ memset(&data, 0, sizeof(data)); #ifdef CONFIG_NET_IPv6 sin = (FAR struct sockaddr_in6 *)&data.addr; sin->sin_family = AF_INET6; sin->sin_port = htons(NFS_PMAPPORT); memcpy(&sin->sin6_addr, &inaddr, sizeof(struct in6_addr)); data.addrlen = sizeof(struct sockaddr_in6); #else sin = (FAR struct sockaddr_in *)&data.addr; sin->sin_family = AF_INET; sin->sin_port = htons(NFS_PMAPPORT); sin->sin_addr = inaddr; data.addrlen = sizeof(struct sockaddr_in); #endif data.sotype = SOCK_DGRAM; data.path = rpath; data.flags = 0; /* 0=Use all defaults */ /* Perform the mount */ ret = mount(NULL, lpath, "nfs", 0, (FAR void *)&data); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO); } /* We no longer need the allocated mount point path */ nsh_freefullpath(lpath); return ret; }
int cmd_cp(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { struct stat buf; char *srcpath = NULL; char *destpath = NULL; char *allocpath = NULL; int oflags = O_WRONLY|O_CREAT|O_TRUNC; int rdfd; int wrfd; int ret = ERROR; /* Get the full path to the source file */ srcpath = nsh_getfullpath(vtbl, argv[1]); if (!srcpath) { goto errout; } /* Open the source file for reading */ rdfd = open(srcpath, O_RDONLY); if (rdfd < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO); goto errout_with_srcpath; } /* Get the full path to the destination file or directory */ destpath = nsh_getfullpath(vtbl, argv[2]); if (!destpath) { goto errout_with_rdfd; } /* Check if the destination is a directory */ ret = stat(destpath, &buf); if (ret == 0) { /* Something exists here... is it a directory? */ if (S_ISDIR(buf.st_mode)) { /* Yes, it is a directory. Remove any trailing '/' characters from the path */ trim_dir(argv[2]); /* Construct the full path to the new file */ allocpath = nsh_getdirpath(argv[2], basename(argv[1]) ); if (!allocpath) { nsh_output(vtbl, g_fmtcmdoutofmemory, argv[0]); goto errout_with_destpath; } /* Open then dest for writing */ nsh_freefullpath(destpath); destpath = allocpath; } else if (!S_ISREG(buf.st_mode)) { /* Maybe it is a driver? */ oflags = O_WRONLY; } } /* Now open the destination */ wrfd = open(destpath, oflags, 0666); if (wrfd < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO); goto errout_with_allocpath; } /* Now copy the file */ for (;;) { int nbytesread; int nbyteswritten; do { nbytesread = read(rdfd, g_iobuffer, IOBUFFERSIZE); if (nbytesread == 0) { /* End of file */ ret = OK; goto errout_with_wrfd; } else if (nbytesread < 0) { /* EINTR is not an error (but will still stop the copy) */ #ifndef CONFIG_DISABLE_SIGNALS if (errno == EINTR) { nsh_output(vtbl, g_fmtsignalrecvd, argv[0]); } else #endif { /* Read error */ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO); } goto errout_with_wrfd; } } while (nbytesread <= 0); do { nbyteswritten = write(wrfd, g_iobuffer, nbytesread); if (nbyteswritten >= 0) { nbytesread -= nbyteswritten; } else { /* EINTR is not an error (but will still stop the copy) */ #ifndef CONFIG_DISABLE_SIGNALS if (errno == EINTR) { nsh_output(vtbl, g_fmtsignalrecvd, argv[0]); } else #endif { /* Read error */ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "write", NSH_ERRNO); } goto errout_with_wrfd; } } while (nbytesread > 0); } errout_with_wrfd: close(wrfd); errout_with_allocpath: if (allocpath) { free(allocpath); } errout_with_destpath: if (destpath && !allocpath) { nsh_freefullpath(destpath); } errout_with_rdfd: close(rdfd); errout_with_srcpath: if (srcpath) { nsh_freefullpath(srcpath); } errout: return ret; }
int cmd_losetup(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { char *loopdev = NULL; char *filepath = NULL; bool teardown = false; bool readonly = false; off_t offset = 0; bool badarg = false; int ret = ERROR; int option; /* Get the losetup options: Two forms are supported: * * losetup -d <loop-device> * losetup [-o <offset>] [-r] <loop-device> <filename> * * NOTE that the -o and -r options are accepted with the -d option, but * will be ignored. */ while ((option = getopt(argc, argv, "d:o:r")) != ERROR) { switch (option) { case 'd': loopdev = nsh_getfullpath(vtbl, optarg); teardown = true; break; case 'o': offset = atoi(optarg); break; case 'r': readonly = true; break; case '?': default: nsh_output(vtbl, g_fmtarginvalid, argv[0]); badarg = true; break; } } /* If a bad argument was encountered, then return without processing the command */ if (badarg) { goto errout_with_paths; } /* If this is not a tear down operation, then additional command line * parameters are required. */ if (!teardown) { /* There must be two arguments on the command line after the options */ if (optind + 1 < argc) { loopdev = nsh_getfullpath(vtbl, argv[optind]); optind++; filepath = nsh_getfullpath(vtbl, argv[optind]); optind++; } else { nsh_output(vtbl, g_fmtargrequired, argv[0]); goto errout_with_paths; } } /* There should be nothing else on the command line */ if (optind < argc) { nsh_output(vtbl, g_fmttoomanyargs, argv[0]); goto errout_with_paths; } /* Perform the teardown operation */ if (teardown) { /* Tear down the loop device. */ ret = loteardown(loopdev); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "loteardown", NSH_ERRNO_OF(-ret)); goto errout_with_paths; } } else { /* Set up the loop device */ ret = losetup(loopdev, filepath, 512, offset, readonly); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "losetup", NSH_ERRNO_OF(-ret)); goto errout_with_paths; } } /* Free memory */ errout_with_paths: if (loopdev) { free(loopdev); } if (filepath) { free(filepath); } return ret; }
static int ls_handler(FAR struct nsh_vtbl_s *vtbl, const char *dirpath, struct dirent *entryp, void *pvarg) { unsigned int lsflags = (unsigned int)pvarg; int ret; /* Check if any options will require that we stat the file */ if ((lsflags & (LSFLAGS_SIZE|LSFLAGS_LONG)) != 0) { struct stat buf; char *fullpath = nsh_getdirpath(dirpath, entryp->d_name); /* Yes, stat the file */ ret = stat(fullpath, &buf); free(fullpath); if (ret != 0) { nsh_output(vtbl, g_fmtcmdfailed, "ls", "stat", NSH_ERRNO); return ERROR; } if ((lsflags & LSFLAGS_LONG) != 0) { char details[] = "----------"; if (S_ISDIR(buf.st_mode)) { details[0]='d'; } else if (S_ISCHR(buf.st_mode)) { details[0]='c'; } else if (S_ISBLK(buf.st_mode)) { details[0]='b'; } if ((buf.st_mode & S_IRUSR) != 0) { details[1]='r'; } if ((buf.st_mode & S_IWUSR) != 0) { details[2]='w'; } if ((buf.st_mode & S_IXUSR) != 0) { details[3]='x'; } if ((buf.st_mode & S_IRGRP) != 0) { details[4]='r'; } if ((buf.st_mode & S_IWGRP) != 0) { details[5]='w'; } if ((buf.st_mode & S_IXGRP) != 0) { details[6]='x'; } if ((buf.st_mode & S_IROTH) != 0) { details[7]='r'; } if ((buf.st_mode & S_IWOTH) != 0) { details[8]='w'; } if ((buf.st_mode & S_IXOTH) != 0) { details[9]='x'; } nsh_output(vtbl, " %s", details); } if ((lsflags & LSFLAGS_SIZE) != 0) { nsh_output(vtbl, "%8d", buf.st_size); } } /* then provide the filename that is common to normal and verbose output */ #ifdef CONFIG_NSH_FULLPATH nsh_output(vtbl, " %s/%s", arg, entryp->d_name); #else nsh_output(vtbl, " %s", entryp->d_name); #endif if (DIRENT_ISDIRECTORY(entryp->d_type) && !ls_specialdir(entryp->d_name)) { nsh_output(vtbl, "/\n"); } else { nsh_output(vtbl, "\n"); } return OK; }
static int cat_common(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, FAR const char *filename) { char buffer[IOBUFFERSIZE]; int fd; int ret = OK; /* Open the file for reading */ fd = open(filename, O_RDONLY); if (fd < 0) { nsh_output(vtbl, g_fmtcmdfailed, cmd, "open", NSH_ERRNO); return ERROR; } /* And just dump it byte for byte into stdout */ for (;;) { int nbytesread = read(fd, buffer, IOBUFFERSIZE); /* Check for read errors */ if (nbytesread < 0) { int errval = errno; /* EINTR is not an error (but will stop stop the cat) */ #ifndef CONFIG_DISABLE_SIGNALS if (errval == EINTR) { nsh_output(vtbl, g_fmtsignalrecvd, cmd); } else #endif { nsh_output(vtbl, g_fmtcmdfailed, cmd, "read", NSH_ERRNO_OF(errval)); } ret = ERROR; break; } /* Check for data successfully read */ else if (nbytesread > 0) { int nbyteswritten = 0; while (nbyteswritten < nbytesread) { ssize_t n = nsh_write(vtbl, buffer, nbytesread); if (n < 0) { int errval = errno; /* EINTR is not an error (but will stop stop the cat) */ #ifndef CONFIG_DISABLE_SIGNALS if (errval == EINTR) { nsh_output(vtbl, g_fmtsignalrecvd, cmd); } else #endif { nsh_output(vtbl, g_fmtcmdfailed, cmd, "write", NSH_ERRNO); } ret = ERROR; break; } else { nbyteswritten += n; } } } /* Otherwise, it is the end of file */ else { break; } } (void)close(fd); return ret; }
int cmd_cmp(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { char *path1 = NULL; char *path2 = NULL; int fd1 = -1, fd2 = -1; int ret = ERROR; unsigned total_read = 0; /* Get the full path to the two files */ path1 = nsh_getfullpath(vtbl, argv[1]); if (!path1) { goto errout; } path2 = nsh_getfullpath(vtbl, argv[2]); if (!path2) { goto errout; } /* Open the files for reading */ fd1 = open(path1, O_RDONLY); if (fd1 < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO); goto errout; } fd2 = open(path2, O_RDONLY); if (fd2 < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO); goto errout; } for (;;) { char buf1[128]; char buf2[128]; int nbytesread1 = read(fd1, buf1, sizeof(buf1)); int nbytesread2 = read(fd2, buf2, sizeof(buf2)); if (nbytesread1 < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO); goto errout; } if (nbytesread2 < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO); goto errout; } total_read += nbytesread1>nbytesread2?nbytesread2:nbytesread1; if (nbytesread1 != nbytesread2 || memcmp(buf1, buf2, nbytesread1) != 0) { nsh_output(vtbl, "files differ: byte %u\n", total_read); goto errout; } if (nbytesread1 < sizeof(buf1)) break; } ret = OK; errout: if (fd1 != -1) close(fd1); if (fd2 != -1) close(fd2); return ret; }
static inline int date_settime(FAR struct nsh_vtbl_s *vtbl, FAR const char *name, FAR char *newtime) { struct timespec ts; struct tm tm; FAR char *token; FAR char *saveptr; long result; int ret; /* Only this date format is supported: MMM DD HH:MM:SS YYYY */ /* Get the month abbreviation */ token = strtok_r(newtime, " \t",&saveptr); if (token == NULL) { goto errout_bad_parm; } tm.tm_mon = date_month(token); if (tm.tm_mon < 0) { goto errout_bad_parm; } /* Get the day of the month. NOTE: Accepts day-of-month up to 31 for all months */ token = strtok_r(NULL, " \t",&saveptr); if (token == NULL) { goto errout_bad_parm; } result = strtol(token, NULL, 10); if (result < 1 || result > 31) { goto errout_bad_parm; } tm.tm_mday = (int)result; /* Get the hours */ token = strtok_r(NULL, " \t:", &saveptr); if (token == NULL) { goto errout_bad_parm; } result = strtol(token, NULL, 10); if (result < 0 || result > 23) { goto errout_bad_parm; } tm.tm_hour = (int)result; /* Get the minutes */ token = strtok_r(NULL, " \t:", &saveptr); if (token == NULL) { goto errout_bad_parm; } result = strtol(token, NULL, 10); if (result < 0 || result > 59) { goto errout_bad_parm; } tm.tm_min = (int)result; /* Get the seconds */ token = strtok_r(NULL, " \t:", &saveptr); if (token == NULL) { goto errout_bad_parm; } result = strtol(token, NULL, 10); if (result < 0 || result > 61) { goto errout_bad_parm; } tm.tm_sec = (int)result; /* And finally the year */ token = strtok_r(NULL, " \t", &saveptr); if (token == NULL) { goto errout_bad_parm; } result = strtol(token, NULL, 10); if (result < 1900 || result > 2100) { goto errout_bad_parm; } tm.tm_year = (int)result - 1900; /* Convert this to the right form, then set the timer */ ts.tv_sec = mktime(&tm); ts.tv_nsec = 0; ret = clock_settime(CLOCK_REALTIME, &ts); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, name, "clock_settime", NSH_ERRNO); return ERROR; } return OK; errout_bad_parm: nsh_output(vtbl, g_fmtarginvalid, name); return ERROR; }
static int cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { nsh_output(vtbl, g_fmtcmdnotfound, argv[0]); return ERROR; }
static inline int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, FAR char **saveptr) { struct nsh_parser_s *np = &vtbl->np; FAR char *cmd = *ppcmd; bool disabled; if (cmd) { /* Check if the command is preceeded by "if" */ if (strcmp(cmd, "if") == 0) { /* Get the cmd following the if */ *ppcmd = nsh_argument(vtbl, saveptr); if (!*ppcmd) { nsh_output(vtbl, g_fmtarginvalid, "if"); goto errout; } /* Verify that "if" is valid in this context */ if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_NORMAL && np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN && np->np_st[np->np_ndx].ns_state != NSH_PARSER_ELSE) { nsh_output(vtbl, g_fmtcontext, "if"); goto errout; } /* Check if we have exceeded the maximum depth of nesting */ if (np->np_ndx >= CONFIG_NSH_NESTDEPTH-1) { nsh_output(vtbl, g_fmtdeepnesting, "if"); goto errout; } /* "Push" the old state and set the new state */ disabled = !nsh_cmdenabled(vtbl); np->np_ndx++; np->np_st[np->np_ndx].ns_state = NSH_PARSER_IF; np->np_st[np->np_ndx].ns_disabled = disabled; np->np_st[np->np_ndx].ns_ifcond = false; } else if (strcmp(cmd, "then") == 0) { /* Get the cmd following the then -- there shouldn't be one */ *ppcmd = nsh_argument(vtbl, saveptr); if (*ppcmd) { nsh_output(vtbl, g_fmtarginvalid, "then"); goto errout; } /* Verify that "then" is valid in this context */ if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_IF) { nsh_output(vtbl, g_fmtcontext, "then"); goto errout; } np->np_st[np->np_ndx].ns_state = NSH_PARSER_THEN; } else if (strcmp(cmd, "else") == 0) { /* Get the cmd following the else -- there shouldn't be one */ *ppcmd = nsh_argument(vtbl, saveptr); if (*ppcmd) { nsh_output(vtbl, g_fmtarginvalid, "else"); goto errout; } /* Verify that "then" is valid in this context */ if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN) { nsh_output(vtbl, g_fmtcontext, "else"); goto errout; } np->np_st[np->np_ndx].ns_state = NSH_PARSER_ELSE; } else if (strcmp(cmd, "fi") == 0) { /* Get the cmd following the fi -- there should be one */ *ppcmd = nsh_argument(vtbl, saveptr); if (*ppcmd) { nsh_output(vtbl, g_fmtarginvalid, "fi"); goto errout; } /* Verify that "fi" is valid in this context */ if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN && np->np_st[np->np_ndx].ns_state != NSH_PARSER_ELSE) { nsh_output(vtbl, g_fmtcontext, "fi"); goto errout; } if (np->np_ndx < 1) /* Shouldn't happen */ { nsh_output(vtbl, g_fmtinternalerror, "if"); goto errout; } /* "Pop" the previous state */ np->np_ndx--; } else if (np->np_st[np->np_ndx].ns_state == NSH_PARSER_IF) { nsh_output(vtbl, g_fmtcontext, cmd); goto errout; } } return OK; errout: np->np_ndx = 0; np->np_st[0].ns_state = NSH_PARSER_NORMAL; np->np_st[0].ns_disabled = false; np->np_st[0].ns_ifcond = false; return ERROR; }
int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) { FAR char *argv[MAX_ARGV_ENTRIES]; FAR char *saveptr; FAR char *cmd; FAR char *redirfile = NULL; int fd = -1; int oflags = 0; int argc; int ret; /* Initialize parser state */ memset(argv, 0, MAX_ARGV_ENTRIES*sizeof(FAR char *)); #ifndef CONFIG_NSH_DISABLEBG vtbl->np.np_bg = false; #endif vtbl->np.np_redirect = false; /* Parse out the command at the beginning of the line */ saveptr = cmdline; cmd = nsh_argument(vtbl, &saveptr); /* Handler if-then-else-fi */ #ifndef CONFIG_NSH_DISABLESCRIPT if (nsh_ifthenelse(vtbl, &cmd, &saveptr) != 0) { goto errout; } #endif /* Handle nice */ #ifndef CONFIG_NSH_DISABLEBG if (nsh_nice(vtbl, &cmd, &saveptr) != 0) { goto errout; } #endif /* Check if any command was provided -OR- if command processing is * currently disabled. */ #ifndef CONFIG_NSH_DISABLESCRIPT if (!cmd || !nsh_cmdenabled(vtbl)) #else if (!cmd) #endif { /* An empty line is not an error and an unprocessed command cannot * generate an error, but neither should they change the last * command status. */ return OK; } /* Parse all of the arguments following the command name. The form * of argv is: * * argv[0]: The command name. * argv[1]: The beginning of argument (up to NSH_MAX_ARGUMENTS) * argv[argc-3]: Possibly '>' or '>>' * argv[argc-2]: Possibly <file> * argv[argc-1]: Possibly '&' * argv[argc]: NULL terminating pointer * * Maximum size is NSH_MAX_ARGUMENTS+5 */ argv[0] = cmd; for (argc = 1; argc < MAX_ARGV_ENTRIES-1; argc++) { argv[argc] = nsh_argument(vtbl, &saveptr); if (!argv[argc]) { break; } } argv[argc] = NULL; /* Check if the command should run in background */ #ifndef CONFIG_NSH_DISABLEBG if (argc > 1 && strcmp(argv[argc-1], "&") == 0) { vtbl->np.np_bg = true; argv[argc-1] = NULL; argc--; } #endif /* Check if the output was re-directed using > or >> */ if (argc > 2) { /* Check for redirection to a new file */ if (strcmp(argv[argc-2], g_redirect1) == 0) { vtbl->np.np_redirect = true; oflags = O_WRONLY|O_CREAT|O_TRUNC; redirfile = nsh_getfullpath(vtbl, argv[argc-1]); argc -= 2; } /* Check for redirection by appending to an existing file */ else if (strcmp(argv[argc-2], g_redirect2) == 0) { vtbl->np.np_redirect = true; oflags = O_WRONLY|O_CREAT|O_APPEND; redirfile = nsh_getfullpath(vtbl, argv[argc-1]); argc -= 2; } } /* Redirected output? */ if (vtbl->np.np_redirect) { /* Open the redirection file. This file will eventually * be closed by a call to either nsh_release (if the command * is executed in the background) or by nsh_undirect if the * command is executed in the foreground. */ fd = open(redirfile, oflags, 0666); nsh_freefullpath(redirfile); redirfile = NULL; if (fd < 0) { nsh_output(vtbl, g_fmtcmdfailed, cmd, "open", NSH_ERRNO); goto errout; } } /* Check if the maximum number of arguments was exceeded */ if (argc > NSH_MAX_ARGUMENTS) { nsh_output(vtbl, g_fmttoomanyargs, cmd); } /* Handle the case where the command is executed in background. * However is app is to be started as namedapp new process will * be created anyway, so skip this step. */ #ifndef CONFIG_NSH_DISABLEBG if (vtbl->np.np_bg #ifdef CONFIG_NSH_BUILTIN_APPS && namedapp_isavail(argv[0]) < 0 #endif ) { struct sched_param param; struct nsh_vtbl_s *bkgvtbl; struct cmdarg_s *args; pthread_attr_t attr; pthread_t thread; /* Get a cloned copy of the vtbl with reference count=1. * after the command has been processed, the nsh_release() call * at the end of nsh_child() will destroy the clone. */ bkgvtbl = nsh_clone(vtbl); if (!bkgvtbl) { goto errout_with_redirect; } /* Create a container for the command arguments */ args = nsh_cloneargs(bkgvtbl, fd, argc, argv); if (!args) { nsh_release(bkgvtbl); goto errout_with_redirect; } /* Handle redirection of output via a file descriptor */ if (vtbl->np.np_redirect) { (void)nsh_redirect(bkgvtbl, fd, NULL); } /* Get the execution priority of this task */ ret = sched_getparam(0, ¶m); if (ret != 0) { nsh_output(vtbl, g_fmtcmdfailed, cmd, "sched_getparm", NSH_ERRNO); nsh_releaseargs(args); nsh_release(bkgvtbl); goto errout; } /* Determine the priority to execute the command */ if (vtbl->np.np_nice != 0) { int priority = param.sched_priority - vtbl->np.np_nice; if (vtbl->np.np_nice < 0) { int max_priority = sched_get_priority_max(SCHED_NSH); if (priority > max_priority) { priority = max_priority; } } else { int min_priority = sched_get_priority_min(SCHED_NSH); if (priority < min_priority) { priority = min_priority; } } param.sched_priority = priority; } /* Set up the thread attributes */ (void)pthread_attr_init(&attr); (void)pthread_attr_setschedpolicy(&attr, SCHED_NSH); (void)pthread_attr_setschedparam(&attr, ¶m); /* Execute the command as a separate thread at the appropriate priority */ ret = pthread_create(&thread, &attr, nsh_child, (pthread_addr_t)args); if (ret != 0) { nsh_output(vtbl, g_fmtcmdfailed, cmd, "pthread_create", NSH_ERRNO_OF(ret)); nsh_releaseargs(args); nsh_release(bkgvtbl); goto errout; } nsh_output(vtbl, "%s [%d:%d]\n", cmd, thread, param.sched_priority); } else #endif { uint8_t save[SAVE_SIZE]; /* Handle redirection of output via a file descriptor */ if (vtbl->np.np_redirect) { nsh_redirect(vtbl, fd, save); } /* Then execute the command in "foreground" -- i.e., while the user waits * for the next prompt. nsh_execute will return: * * -1 (ERRROR) if the command was unsuccessful * 0 (OK) if the command was successful * 1 if an application task was spawned successfully, but * returned failure exit status. */ ret = nsh_execute(vtbl, argc, argv); /* Restore the original output. Undirect will close the redirection * file descriptor. */ if (vtbl->np.np_redirect) { nsh_undirect(vtbl, save); } /* Treat both errors and non-zero return codes as "errors" so that * it is possible to test for non-zero returns in nsh scripts. */ if (ret != OK) { goto errout; } } /* Return success if the command succeeded (or at least, starting of the * command task succeeded). */ return nsh_saveresult(vtbl, false); #ifndef CONFIG_NSH_DISABLEBG errout_with_redirect: if (vtbl->np.np_redirect) { close(fd); } #endif errout: return nsh_saveresult(vtbl, true); }
static int cmd_codecs_proc(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv, uint8_t mode, codec_callback_t func) { #if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5) static const unsigned char hex_chars[] = "0123456789abcdef"; MD5_CTX ctx; unsigned char mac[16]; char *pSrc; char *pDest; #endif char *localfile = NULL; char *src_buffer = NULL; char *buffer = NULL; char *fullpath = NULL; const char *fmt; char *s_data; bool badarg = false; bool is_file = false; bool is_websafe=false; int option; int fd = -1; int buff_len = 0; int src_buff_len = 0; int i = 0; int ret = OK; /* Get the command options */ while ((option = getopt(argc, argv, ":fw")) != ERROR) { switch (option) { case 'f': is_file = true; break; #ifdef CONFIG_CODECS_BASE64 case 'w': is_websafe = true; if (!(mode == CODEC_MODE_BASE64ENC || mode == CODEC_MODE_BASE64DEC)) { badarg = true; } break; #endif case ':': nsh_output(vtbl, g_fmtargrequired, argv[0]); badarg = true; break; case '?': default: nsh_output(vtbl, g_fmtarginvalid, argv[0]); badarg = true; break; } } /* If a bad argument was encountered, then return without processing the command */ if (badarg) { return ERROR; } /* There should be exactly on parameter left on the command-line */ if (optind == argc-1) { s_data = argv[optind]; } else if (optind >= argc) { fmt = g_fmttoomanyargs; goto errout; } else { fmt = g_fmtargrequired; goto errout; } #if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5) if (mode == CODEC_MODE_HASH_MD5) { MD5Init(&ctx); } #endif if (is_file) { /* Get the local file name */ localfile = s_data; /* Get the full path to the local file */ fullpath = nsh_getfullpath(vtbl, localfile); /* Open the local file for writing */ fd = open(fullpath, O_RDONLY|O_TRUNC, 0644); if (fd < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO); ret = ERROR; goto exit; } src_buffer = malloc(CONFIG_NSH_CODECS_BUFSIZE+2); #if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64ENC) if (mode == CODEC_MODE_BASE64ENC) { src_buff_len = CONFIG_NSH_CODECS_BUFSIZE / 3 * 3; } else #endif { src_buff_len = CONFIG_NSH_CODECS_BUFSIZE; } buff_len = calc_codec_buffsize(src_buff_len+2, mode); buffer = malloc(buff_len); while(true) { memset(src_buffer, 0, src_buff_len+2); ret=read(fd, src_buffer, src_buff_len); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO); ret = ERROR; goto exit; } else if(ret==0) { break; } #if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLDECODE) if (mode == CODEC_MODE_URLDECODE) { if (src_buffer[src_buff_len-1]=='%') { ret += read(fd,&src_buffer[src_buff_len],2); } else if (src_buffer[src_buff_len-2]=='%') { ret += read(fd,&src_buffer[src_buff_len],1); } } #endif memset(buffer, 0, buff_len); if (func) { #if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5) if (mode == CODEC_MODE_HASH_MD5) { func(src_buffer, ret, (char *)&ctx, &buff_len,0); } else #endif { func(src_buffer, ret, buffer, &buff_len,(is_websafe)?1:0); nsh_output(vtbl, "%s", buffer); } } buff_len = calc_codec_buffsize(src_buff_len+2, mode); } #if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5) if (mode == CODEC_MODE_HASH_MD5) { MD5Final(mac, &ctx); pSrc = (char *)&mac; pDest = buffer; for(i=0;i<16;i++,pSrc++) { *pDest++ = hex_chars[(*pSrc) >> 4]; *pDest++ = hex_chars[(*pSrc) & 0x0f]; } *pDest='\0'; nsh_output(vtbl, "%s\n", buffer); } #endif ret = OK; goto exit; }
static int expression(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { int value; int i = 0; /* Check for unary operations on expressions */ if (strcmp(argv[0], "!") == 0) { if (argc < 2) { goto errout_syntax; } return expression(vtbl, argc-1, &argv[1]) == TEST_TRUE ? TEST_FALSE : TEST_TRUE; } /* Check for unary operations on simple, typed arguments */ else if (argv[0][0] == '-') { if (argc < 2) { goto errout_syntax; } i += 2; value = unaryexpression(vtbl, argv); } /* Check for binary operations on simple, typed arguments */ else { if (argc < 3) { goto errout_syntax; } i += 3; value = binaryexpression(vtbl, argv); } /* Test if there any failure */ if (value == TEST_ERROR) { goto errout_syntax; } /* Is there anything after the simple expression? */ if (i < argc) { /* EXPRESSION -a EXPRESSION */ if (strcmp(argv[i], "-a") == 0) { if (value != TEST_TRUE) { return TEST_FALSE; } else { i++; return expression(vtbl, argc-i, &argv[i]); } } /* EXPRESSION -o EXPRESSION */ else if (strcmp(argv[i], "-o") == 0) { if (value == TEST_TRUE) { return TEST_TRUE; } else { i++; return expression(vtbl, argc-i, &argv[i]); } } else { goto errout_syntax; } } return value; errout_syntax: nsh_output(vtbl, g_nshsyntax, "test"); return TEST_FALSE; }
int cmd_date(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { FAR char *newtime = NULL; FAR const char *errfmt; bool badarg = false; int option; int ret; /* Get the date options: date [-s time] [+FORMAT] */ while ((option = getopt(argc, argv, "s:")) != ERROR) { if (option == 's') { /* We will be setting the time */ newtime = optarg; } else /* option = '?' */ { /* We need to parse to the end anyway so that getopt stays healthy */ badarg = true; } } /* If a bad argument was encountered then exit with an error */ if (badarg) { errfmt = g_fmtarginvalid; goto errout; } /* optind < argc-1 means that there are additional, unexpected arguments on * th command-line */ if (optind < argc) { errfmt = g_fmttoomanyargs; goto errout; } /* Display or set the time */ if (newtime) { ret = date_settime(vtbl, argv[0], newtime); } else { ret = date_showtime(vtbl, argv[0]); } return ret; errout: nsh_output(vtbl, errfmt, argv[0]); return ERROR; }
int cmd_time(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { struct timespec start; #ifndef CONFIG_NSH_DISABLEBG bool bgsave; #endif #if CONFIG_NFILE_STREAMS > 0 bool redirsave; #endif int ret; /* Get the current time */ ret = clock_gettime(TIME_CLOCK, &start); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "clock_gettime", NSH_ERRNO); return ERROR; } /* Save state */ #ifndef CONFIG_NSH_DISABLEBG bgsave = vtbl->np.np_bg; #endif #if CONFIG_NFILE_STREAMS > 0 redirsave = vtbl->np.np_redirect; #endif /* Execute the command */ ret = nsh_parse(vtbl, argv[1]); if (ret >= 0) { struct timespec end; struct timespec diff; /* Get and print the elapsed time */ ret = clock_gettime(TIME_CLOCK, &end); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "clock_gettime", NSH_ERRNO); ret = ERROR; } else { diff.tv_sec = end.tv_sec - start.tv_sec; if (start.tv_nsec > end.tv_nsec) { diff.tv_sec--; end.tv_nsec += 1000000000; } diff.tv_nsec = end.tv_nsec - start.tv_nsec; nsh_output(vtbl, "\n%lu.%04lu sec\n", (unsigned long)diff.tv_sec, (unsigned long)diff.tv_nsec / 100000); } } /* Restore state */ #ifndef CONFIG_NSH_DISABLEBG vtbl->np.np_bg = bgsave; #endif #if CONFIG_NFILE_STREAMS > 0 vtbl->np.np_redirect = redirsave; #endif return ret; }
static inline void help_usage(FAR struct nsh_vtbl_s *vtbl) { nsh_output(vtbl, "NSH command forms:\n"); #ifndef CONFIG_NSH_DISABLEBG nsh_output(vtbl, " [nice [-d <niceness>>]] <cmd> [> <file>|>> <file>] [&]\n\n"); #else nsh_output(vtbl, " <cmd> [> <file>|>> <file>]\n\n"); #endif #ifndef CONFIG_NSH_DISABLESCRIPT #ifndef CONFIG_NSH_DISABLE_ITEF nsh_output(vtbl, "OR\n"); nsh_output(vtbl, " if <cmd>\n"); nsh_output(vtbl, " then\n"); nsh_output(vtbl, " [sequence of <cmd>]\n"); nsh_output(vtbl, " else\n"); nsh_output(vtbl, " [sequence of <cmd>]\n"); nsh_output(vtbl, " fi\n\n"); #endif #ifndef CONFIG_NSH_DISABLE_LOOPS nsh_output(vtbl, "OR\n"); nsh_output(vtbl, " while <cmd>\n"); nsh_output(vtbl, " do\n"); nsh_output(vtbl, " [sequence of <cmd>]\n"); nsh_output(vtbl, " done\n\n"); nsh_output(vtbl, "OR\n"); nsh_output(vtbl, " until <cmd>\n"); nsh_output(vtbl, " do\n"); nsh_output(vtbl, " [sequence of <cmd>]\n"); nsh_output(vtbl, " done\n\n"); #endif #endif }
int cmd_kill(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { char *ptr; char *endptr; long signal; long pid; /* Check incoming parameters. The first parameter should be "-<signal>" */ ptr = argv[1]; if (*ptr != '-' || ptr[1] < '0' || ptr[1] > '9') { goto invalid_arg; } /* Extract the signal number */ signal = strtol(&ptr[1], &endptr, 0); /* The second parameter should be <pid> */ ptr = argv[2]; if (*ptr < '0' || *ptr > '9') { goto invalid_arg; } /* Extract athe pid */ pid = strtol(ptr, &endptr, 0); /* Send the signal. Kill return values: * * EINVAL An invalid signal was specified. * EPERM The process does not have permission to send the signal to any * of the target processes. * ESRCH The pid or process group does not exist. * ENOSYS Do not support sending signals to process groups. */ if (kill((pid_t)pid, (int)signal) == 0) { return OK; } switch (errno) { case EINVAL: goto invalid_arg; case ESRCH: nsh_output(vtbl, g_fmtnosuch, argv[0], "task", argv[2]); return ERROR; case EPERM: case ENOSYS: default: nsh_output(vtbl, g_fmtcmdfailed, argv[0], "kill", NSH_ERRNO); return ERROR; } invalid_arg: nsh_output(vtbl, g_fmtarginvalid, argv[0]); return ERROR; }
static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { FAR const char *cmd = NULL; #ifndef CONFIG_NSH_HELP_TERSE bool verbose = false; int i; #endif /* The command may be followed by a verbose option */ #ifndef CONFIG_NSH_HELP_TERSE i = 1; if (argc > i) { if (strcmp(argv[i], "-v") == 0) { verbose = true; i++; } } /* The command line may end with a command name */ if (argc > i) { cmd = argv[i]; } /* Show the generic usage if verbose is requested */ if (verbose) { help_usage(vtbl); } #else if (argc > 1) { cmd = argv[1]; } #endif /* Are we showing help on a single command? */ if (cmd) { /* Yes.. show the single command */ help_cmd(vtbl, cmd); } else { /* In verbose mode, show detailed help for all commands */ #ifndef CONFIG_NSH_HELP_TERSE if (verbose) { nsh_output(vtbl, "Where <cmd> is one of:\n"); help_allcmds(vtbl); } /* Otherwise, just show the list of command names */ else #endif { help_cmd(vtbl, "help"); nsh_output(vtbl, "\n"); help_cmdlist(vtbl); } /* And show the list of built-in applications */ help_builtins(vtbl); } return OK; }
int cmd_mkrd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { const char *fmt; uint8_t *buffer; uint32_t nsectors; bool badarg = false; int sectsize = 512; int minor = 0; int ret; /* Get the mount options */ int option; while ((option = getopt(argc, argv, ":m:s:")) != ERROR) { switch (option) { case 'm': minor = atoi(optarg); if (minor < 0 || minor > 255) { nsh_output(vtbl, g_fmtargrange, argv[0]); badarg = true; } break; case 's': sectsize = atoi(optarg); if (minor < 0 || minor > 16384) { nsh_output(vtbl, g_fmtargrange, argv[0]); badarg = true; } break; case ':': nsh_output(vtbl, g_fmtargrequired, argv[0]); badarg = true; break; case '?': default: nsh_output(vtbl, g_fmtarginvalid, argv[0]); badarg = true; break; } } /* If a bad argument was encountered, then return without processing the command */ if (badarg) { return ERROR; } /* There should be exactly on parameter left on the command-line */ if (optind == argc-1) { nsectors = (uint32_t)atoi(argv[optind]); } else if (optind >= argc) { fmt = g_fmttoomanyargs; goto errout_with_fmt; } else { fmt = g_fmtargrequired; goto errout_with_fmt; } /* Allocate the memory backing up the ramdisk */ buffer = (uint8_t*)malloc(sectsize * nsectors); if (!buffer) { fmt = g_fmtcmdoutofmemory; goto errout_with_fmt; } #ifdef CONFIG_DEBUG_VERBOSE memset(buffer, 0, sectsize * nsectors); #endif dbg("RAMDISK at %p\n", buffer); /* Then register the ramdisk */ ret = ramdisk_register(minor, buffer, nsectors, sectsize, true); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "ramdisk_register", NSH_ERRNO_OF(-ret)); free(buffer); return ERROR; } return ret; errout_with_fmt: nsh_output(vtbl, fmt, argv[0]); return ERROR; }
static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, int argc, char *argv[]) { const struct cmdmap_s *cmdmap; const char *cmd; cmd_t handler = cmd_unrecognized; int ret; /* The form of argv is: * * argv[0]: The command name. This is argv[0] when the arguments * are, finally, received by the command vtblr * argv[1]: The beginning of argument (up to NSH_MAX_ARGUMENTS) * argv[argc]: NULL terminating pointer */ cmd = argv[0]; /* Try to find a command in the application library. */ #ifdef CONFIG_NSH_BUILTIN_APPS ret = nsh_execapp(vtbl, cmd, argv); /* If the built-in application was successfully started, return OK * or 1 (if the application returned a non-zero exit status). */ if (ret >= 0) { return ret; } #endif /* See if the command is one that we understand */ for (cmdmap = g_cmdmap; cmdmap->cmd; cmdmap++) { if (strcmp(cmdmap->cmd, cmd) == 0) { /* Check if a valid number of arguments was provided. We * do this simple, imperfect checking here so that it does * not have to be performed in each command. */ if (argc < cmdmap->minargs) { /* Fewer than the minimum number were provided */ nsh_output(vtbl, g_fmtargrequired, cmd); return ERROR; } else if (argc > cmdmap->maxargs) { /* More than the maximum number were provided */ nsh_output(vtbl, g_fmttoomanyargs, cmd); return ERROR; } else { /* A valid number of arguments were provided (this does * not mean they are right). */ handler = cmdmap->handler; break; } } } ret = handler(vtbl, argc, argv); return ret; }
int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { char *source; char *target; char *filesystem = 0; bool badarg = false; int ret; /* Get the mount options */ int option; while ((option = getopt(argc, argv, ":t:")) != ERROR) { switch (option) { case 't': filesystem = optarg; break; case ':': nsh_output(vtbl, g_fmtargrequired, argv[0]); badarg = true; break; case '?': default: nsh_output(vtbl, g_fmtarginvalid, argv[0]); badarg = true; break; } } /* If a bad argument was encountered, then return without processing the command */ if (badarg) { return ERROR; } /* There are two required arguments after the options */ if (optind + 2 < argc) { nsh_output(vtbl, g_fmttoomanyargs, argv[0]); return ERROR; } else if (optind + 2 > argc) { nsh_output(vtbl, g_fmtargrequired, argv[0]); return ERROR; } /* The source and target paths might be relative to the current * working directory. */ source = nsh_getfullpath(vtbl, argv[optind]); if (!source) { return ERROR; } target = nsh_getfullpath(vtbl, argv[optind+1]); if (!target) { nsh_freefullpath(source); return ERROR; } /* Perform the mount */ ret = mount(source, target, filesystem, 0, NULL); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO); } nsh_freefullpath(source); nsh_freefullpath(target); return ret; }