├── .all-contributorsrc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── add_integration_test.md │ ├── add_new_command.md │ └── bug_report.md ├── dependabot.yml └── workflows │ ├── build.yml │ ├── integration_test.yml │ ├── release.yml │ ├── reviewdog.yml │ └── unit_test.yml ├── .gitignore ├── .goreleaser.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Contributors.md ├── Dockerfile ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── cmd └── mimixbox │ └── main.go ├── docs ├── examples │ ├── fakemovie │ │ ├── en │ │ │ └── fakemovie.md │ │ └── ja │ │ │ └── fakemovie.md │ ├── ghrdc │ │ ├── en │ │ │ └── ghrdc.md │ │ └── ja │ │ │ └── ghrdc.md │ ├── path │ │ ├── en │ │ │ └── path.md │ │ └── ja │ │ │ └── path.md │ ├── sddf │ │ ├── en │ │ │ └── sddf.md │ │ └── ja │ │ │ └── sddf.md │ └── serial │ │ ├── en │ │ └── serial.md │ │ └── ja │ │ └── serial.md ├── images │ ├── debug_logging.jpg │ ├── drawio │ │ └── debug_logging.drawio │ ├── lena.png │ ├── lena_phub_fake.png │ ├── lena_twitter_fake.png │ ├── logo.jpg │ └── serial.jpg ├── introduction │ ├── en │ │ ├── CommandAppletList.md │ │ └── DebugAndTest.md │ └── ja │ │ ├── DebugAndTest.md │ │ └── README.md └── man │ ├── fakemovie │ ├── en │ │ └── fakemovie.1.md │ └── ja │ │ └── fakemovie.1.md │ ├── ghrdc │ ├── en │ │ └── ghrdc.1.md │ └── ja │ │ └── ghrdc.1.md │ ├── mimixbox │ ├── en │ │ └── mimixbox.1.md │ └── ja │ │ └── mimixbox.1.md │ ├── path │ ├── en │ │ └── path.1.md │ └── ja │ │ └── path.1.md │ ├── sddf │ ├── en │ │ └── sddf.1.md │ └── ja │ │ └── sddf.1.md │ └── serial │ ├── en │ └── serial.1.md │ └── ja │ └── serial.1.md ├── go.mod ├── go.sum ├── internal ├── applets │ ├── applet.go │ ├── archival │ │ └── gzip │ │ │ └── gzip.go │ ├── console-tools │ │ ├── clear │ │ │ └── clear.go │ │ └── reset │ │ │ └── reset.go │ ├── debianutils │ │ ├── add-shell │ │ │ └── add-shell.go │ │ ├── ischroot │ │ │ └── ischroot.go │ │ ├── remove-shell │ │ │ └── remove-shell.go │ │ ├── valid-shell │ │ │ └── valid-shell.go │ │ └── which │ │ │ └── which.go │ ├── editors │ │ └── .gitkeep │ ├── fileutils │ │ ├── chgrp │ │ │ └── chgrp.go │ │ ├── chown │ │ │ └── chown.go │ │ ├── cp │ │ │ └── cp.go │ │ ├── ln │ │ │ └── ln.go │ │ ├── mkdir │ │ │ └── mkdir.go │ │ ├── mkfifo │ │ │ └── mkfifo.go │ │ ├── mv │ │ │ └── mv.go │ │ ├── rm │ │ │ └── rm.go │ │ ├── rmdir │ │ │ └── rmdir.go │ │ └── touch │ │ │ └── touch.go │ ├── findutils │ │ └── .gitkeep │ ├── games │ │ └── lifegame │ │ │ └── lifegame.go │ ├── jokeutils │ │ ├── cowsay │ │ │ └── cowsay.go │ │ ├── fakemovie │ │ │ └── fakemovie.go │ │ └── sl │ │ │ └── sl.go │ ├── loginutils │ │ └── chsh │ │ │ └── chsh.go │ ├── pmutils │ │ └── halt │ │ │ └── halt.go │ ├── shellutils │ │ ├── base64 │ │ │ └── base64.go │ │ ├── basename │ │ │ └── basename.go │ │ ├── chroot │ │ │ └── chroot.go │ │ ├── dirname │ │ │ └── dirname.go │ │ ├── echo │ │ │ └── echo.go │ │ ├── false │ │ │ └── false.go │ │ ├── ghrdc │ │ │ └── ghrdc.go │ │ ├── groups │ │ │ └── groups.go │ │ ├── hostid │ │ │ └── hostid.go │ │ ├── id │ │ │ └── id.go │ │ ├── kill │ │ │ └── kill.go │ │ ├── mbsh │ │ │ ├── builtin │ │ │ │ ├── builtInCmds.go │ │ │ │ └── cd.go │ │ │ └── mbsh.go │ │ ├── path │ │ │ └── path.go │ │ ├── printenv │ │ │ └── printenv.go │ │ ├── printf │ │ │ └── printf.go │ │ ├── pwd │ │ │ └── pwd.go │ │ ├── sddf │ │ │ └── sddf.go │ │ ├── seq │ │ │ └── seq.go │ │ ├── serial │ │ │ └── serial.go │ │ ├── sleep │ │ │ └── sleep.go │ │ ├── sync │ │ │ └── sync.go │ │ ├── true │ │ │ └── true.go │ │ ├── uuidgen │ │ │ └── uuidgen.go │ │ ├── wget │ │ │ └── wget.go │ │ └── whoami │ │ │ └── whoami.go │ └── textutils │ │ ├── cat │ │ └── cat.go │ │ ├── dos2unix │ │ └── dos2unix.go │ │ ├── expand │ │ └── expand.go │ │ ├── head │ │ └── head.go │ │ ├── md5sum │ │ └── md5sum.go │ │ ├── nl │ │ └── nl.go │ │ ├── sha1sum │ │ └── sha1sum.go │ │ ├── sha256sum │ │ └── sha256sum.go │ │ ├── sha512sum │ │ └── sha512sum.go │ │ ├── tac │ │ └── tac.go │ │ ├── tail │ │ └── tail.go │ │ ├── tr │ │ └── tr.go │ │ ├── unexpand │ │ └── unexpand.go │ │ ├── unix2dos │ │ └── unix2dos.go │ │ └── wc │ │ └── wc.go └── lib │ ├── common.go │ ├── crypto.go │ ├── file.go │ ├── file_test.go │ ├── gnu.go │ ├── id.go │ ├── net.go │ ├── option.go │ ├── path.go │ ├── shadow.go │ ├── shell.go │ ├── signal.go │ ├── string.go │ └── type.go ├── scripts ├── installer.sh ├── libshell.sh ├── mkJailForDebianFamily.sh ├── mkManpages.sh └── release.sh └── test ├── it ├── .shellspec ├── fileutils │ ├── cp_test.sh │ ├── mkdir_test.sh │ ├── mkfifo_test.sh │ ├── mv_test.sh │ ├── rm_test.sh │ └── touch_test.sh ├── games │ └── .gitkeep ├── jokeutils │ └── .gitkeep ├── shellutils │ ├── basename_test.sh │ ├── dirname_test.sh │ ├── echo_test.sh │ ├── false_test.sh │ ├── true_test.sh │ └── which_test.sh ├── spec │ ├── basename_spec.sh │ ├── cat_spec.sh │ ├── cp_spec.sh │ ├── dirname_spec.sh │ ├── dos2unix_spec.sh │ ├── echo_spec.sh │ ├── false_spec.sh │ ├── md5sum_spec.sh │ ├── mkdir_spec.sh │ ├── mkfifo_spec.sh │ ├── mv_spec.sh │ ├── nl_spec.sh │ ├── rm_spec.sh │ ├── sha1sum_spec.sh │ ├── sha256sum_spec.sh │ ├── sha512sum_spec.sh │ ├── spec_helper.sh │ ├── touch_spec.sh │ ├── true_spec.sh │ ├── unix2dos_spec.sh │ ├── wc_spec.sh │ └── which_spec.sh └── textutils │ ├── cat_test.sh │ ├── dos2unix_test.sh │ ├── md5sum_test.sh │ ├── nl_test.sh │ ├── sha1sum_test.sh │ ├── sha256sum_test.sh │ ├── sha512sum_test.sh │ ├── unix2dos_test.sh │ └── wc_test.sh └── ut └── prepareUnitTest.sh /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "mimixbox", 3 | "projectOwner": "nao1215", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": [ 7 | "README.md" 8 | ], 9 | "imageSize": 75, 10 | "commit": true, 11 | "commitConvention": "angular", 12 | "contributors": [ 13 | { 14 | "login": "nao1215", 15 | "name": "CHIKAMATSU Naohiro", 16 | "avatar_url": "https://avatars.githubusercontent.com/u/22737008?v=4", 17 | "profile": "https://debimate.jp/", 18 | "contributions": [ 19 | "code" 20 | ] 21 | }, 22 | { 23 | "login": "polynomialspace", 24 | "name": "polynomialspace", 25 | "avatar_url": "https://avatars.githubusercontent.com/u/45617594?v=4", 26 | "profile": "https://github.com/polynomialspace", 27 | "contributions": [ 28 | "code" 29 | ] 30 | }, 31 | { 32 | "login": "k-avy", 33 | "name": "Kavya Shukla", 34 | "avatar_url": "https://avatars.githubusercontent.com/u/81437739?v=4", 35 | "profile": "https://github.com/k-avy", 36 | "contributions": [ 37 | "code" 38 | ] 39 | } 40 | ], 41 | "contributorsPerLine": 7, 42 | "linkToUsage": true 43 | } 44 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: nao1215 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/add_integration_test.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Add Integration Test 3 | about: ToDo List for adding integration tests. 4 | title: "[Add] XXX command integration tests" 5 | labels: test 6 | assignees: '' 7 | 8 | --- 9 | 10 | **You don't have to write anything.** 11 | This issue is made as a TODO list. 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/add_new_command.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Add new command 3 | about: ToDo List for adding command. 4 | title: "[Add] XXX/YYY command " 5 | labels: "good first issue" 6 | assignees: '' 7 | 8 | --- 9 | 10 | **If you want to develop the command described in this Issue title, please comment on this issue** 11 | 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG] XXX" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "20:00" 8 | open-pull-requests-limit: 10 9 | # Maintain dependencies for GitHub Actions 10 | - package-ecosystem: "github-actions" 11 | directory: "/" 12 | schedule: 13 | interval: "daily" 14 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Set up Go 16 | uses: actions/setup-go@v5 17 | with: 18 | go-version: "1" 19 | check-latest: true 20 | 21 | - name: Build 22 | run: make build 23 | -------------------------------------------------------------------------------- /.github/workflows/integration_test.yml: -------------------------------------------------------------------------------- 1 | name: IntegrationTest 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | workflow_dispatch: 9 | 10 | jobs: 11 | integration_test: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Set up Go 17 | uses: actions/setup-go@v5 18 | with: 19 | go-version: "1" 20 | check-latest: true 21 | 22 | - name: SetupShellScript 23 | run: curl -fsSL https://git.io/shellspec | sh -s -- --yes 24 | 25 | - name: Build 26 | run: make build 27 | 28 | - name: InstallMimixBox 29 | run: sudo install -v -m 0755 -D mimixbox /usr/local/bin/. 30 | 31 | - name: CreateSymbolicLink 32 | run: mimixbox --full-install /usr/local/bin/ 33 | 34 | - name: IntegrationTest 35 | run: make it 36 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*" 7 | 8 | jobs: 9 | release: 10 | name: Release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | - name: Setup Go 18 | uses: actions/setup-go@v5 19 | with: 20 | go-version: "1" 21 | check-latest: true 22 | - name: Run GoReleaser 23 | uses: goreleaser/goreleaser-action@v6 24 | with: 25 | version: latest 26 | args: release --clean 27 | env: 28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 29 | TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} 30 | -------------------------------------------------------------------------------- /.github/workflows/reviewdog.yml: -------------------------------------------------------------------------------- 1 | name: reviewdog 2 | on: [pull_request] 3 | 4 | jobs: 5 | golangci-lint: 6 | name: golangci-lint 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Check out code into the Go module directory 10 | uses: actions/checkout@v4 11 | with: 12 | persist-credentials: false 13 | - name: golangci-lint 14 | uses: reviewdog/action-golangci-lint@v2 15 | with: 16 | reporter: github-pr-review 17 | level: warning 18 | 19 | misspell: 20 | name: misspell 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Check out code into the Go module directory 24 | uses: actions/checkout@v4 25 | with: 26 | persist-credentials: false 27 | - name: misspell 28 | uses: reviewdog/action-misspell@v1 29 | with: 30 | reporter: github-pr-review 31 | level: warning 32 | locale: "US" 33 | 34 | actionlint: 35 | runs-on: ubuntu-latest 36 | steps: 37 | - uses: actions/checkout@v4 38 | - uses: reviewdog/action-actionlint@v1 39 | with: 40 | reporter: github-pr-review 41 | level: warning 42 | -------------------------------------------------------------------------------- /.github/workflows/unit_test.yml: -------------------------------------------------------------------------------- 1 | name: UnitTest 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | unit-test: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - uses: actions/setup-go@v5 16 | with: 17 | go-version: "1" 18 | check-latest: true 19 | 20 | - name: UnitTest 21 | run: make ut 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | mimixbox 8 | 9 | # Test binary, built with `go test -c`. And test directory 10 | *.test 11 | *.sddf 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Dependency directories (remove the comment below to include it) 17 | vendor/* 18 | 19 | # release directory 20 | release/* 21 | 22 | # Coverage file 23 | cover.out 24 | cover.html 25 | 26 | # Man-pages 27 | *.1.gz 28 | 29 | # Directory that manages licenses for dependent libraries 30 | licenses -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | project_name: mimixbox 2 | env: 3 | - GO111MODULE=on 4 | before: 5 | hooks: 6 | - go mod tidy 7 | - go generate ./... 8 | builds: 9 | - main: ./cmd/mimixbox 10 | ldflags: 11 | - -s -w 12 | env: 13 | - CGO_ENABLED=0 14 | goos: 15 | - linux 16 | goarch: 17 | - amd64 18 | - arm64 19 | archives: 20 | - name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" 21 | checksum: 22 | name_template: "checksums.txt" 23 | snapshot: 24 | name_template: "{{ incpatch .Version }}-next" 25 | changelog: 26 | sort: asc 27 | filters: 28 | exclude: 29 | - "^docs:" 30 | - "^test:" 31 | nfpms: 32 | - maintainer: Naohiro CHIKAMATSU 33 | description: MimixBox - mimic BusyBox on Linux 34 | homepage: https://github.com/nao1215/mimixbox 35 | license: Apache-2.0 license 36 | formats: 37 | - deb 38 | - rpm 39 | - apk 40 | brews: 41 | - name: mimixbox 42 | description: MimixBox - mimic BusyBox on Linux 43 | license: Apache-2.0 license 44 | repository: 45 | owner: nao1215 46 | name: homebrew-tap 47 | token: "{{ .Env.TAP_GITHUB_TOKEN }}" 48 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to MimixBox 2 | First of all, thank you for taking the time to contribute. 3 | The following provides you with some guidance on how to contribute to this project. 4 | 5 | # Pull Requests 6 | MimixBox will make about 100 commands by the time it reaches Version 1.0.0. 7 | If you find a command that doesn't exist in MimixBox despite the general Unix command, feel free to make a Pull Request. 8 | It doesn't matter if there are few options. The test is also minimal. I'll fix some bugs later. 9 | First, increase the number of commands. The quality will be improved to Version 1.0.0 or later. 10 | 11 | I also accept original joke commands and games. 12 | However, please be careful about the license. Only licenses compatible with Apache License version 2.0 will be merged. 13 | For example, GPLv2 or latter is not merged. Tetris can't be merged either (sorry). 14 | 15 | If you really want to add a command, declare it in your [GitHub Issue](https://github.com/nao1215/mimixbox/issues). 16 | Other developers look at the Issue and try not to develop the same command. 17 | 18 | # Code tree 19 | ``` 20 | project root dir 21 | ├── cmd 22 | │ └── mimixbox 23 | │ └── main.go ※ If you add command, increment the minor version 24 | ├── docs 25 | │ └── introduction 26 | │ └──en 27 | │ └── CommandAppletList.md ※ If you add command, add a command description 28 | └── internal 29 | └── applets 30 | ├── applet.go ※ See init(). 31 | ├── fileutils 32 | ├── games 33 | ├── jokeutils 34 | ├── shellutils 35 | └── textutils 36 | ``` 37 | 38 | For example, fileutils directory structure is below. 39 | One command is managed in one directory. You can increase the number of files in a certain command directory. 40 | ``` 41 | internal/applets/fileutils/ 42 | ├── cp 43 | │ └── cp.go 44 | ├── ln 45 | │ └── ln.go 46 | ├── mkdir 47 | │ └── mkdir.go 48 | ├── mkfifo 49 | │ └── mkfifo.go 50 | ├── mv 51 | │ └── mv.go 52 | ├── rm 53 | │ └── rm.go 54 | ├── rmdir 55 | │ └── rmdir.go 56 | └── touch 57 | └── touch.go 58 | ``` 59 | 60 | If you want to implement a generic method, implement it in the internal library. 61 | Treat these libraries as mb libraries. 62 | ``` 63 | project root directory 64 | └── internal 65 | ├── applets 66 | └── lib 67 | ``` 68 | -------------------------------------------------------------------------------- /Contributors.md: -------------------------------------------------------------------------------- 1 | | NAME | EMAIL | +(APPEND) | -(DELETE) | 2 | |-----------------|---------------------------------------------------|-----------|-----------| 3 | | Nao1215 | n.chika156@gmail.com | 20781 | 3306 | 4 | | polynomialspace | github@polynomial.space | 310 | 293 | 5 | | Kavya Shukla | kavyuushukla59@gmail.com | 72 | 0 | 6 | | nao1215 | nao1215@users.noreply.github.com | 5 | 0 | 7 | | dependabot[bot] | 49699333+dependabot[bot]@users.noreply.github.com | 0 | 0 | 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang as builder 2 | ENV ROOT=/go/app 3 | ENV IT_SHELL=/home/mimixbox/do_integration_test.sh 4 | WORKDIR ${ROOT} 5 | 6 | # 1) Setting root user password 7 | # 2) Add mimixbox user 8 | # 3) Setting mimixbox user password 9 | RUN echo 'root:password' | chpasswd 10 | RUN useradd mimixbox -m -s /bin/bash &&\ 11 | echo 'mimixbox:password' |chpasswd 12 | RUN apt-get update && apt-get upgrade && apt-get -y install sudo file 13 | 14 | # Copy ShellSpec installer 15 | COPY ./test/it /home/mimixbox/integration_tests 16 | RUN git clone https://github.com/shellspec/shellspec.git && \ 17 | cd shellspec && make install 18 | 19 | RUN echo "#!/bin/bash" > ${IT_SHELL} && \ 20 | echo "cd /home/mimixbox/integration_tests && shellspec\n" >> ${IT_SHELL} && \ 21 | chmod a+x ${IT_SHELL} && \ 22 | chown -R mimixbox:mimixbox /home/mimixbox/. 23 | 24 | RUN git clone https://github.com/nao1215/mimixbox.git && cd mimixbox && \ 25 | make build 26 | RUN cd ${ROOT}/mimixbox && sudo make full-install 27 | 28 | # If you want to administrator privileges, you become the root user. 29 | # RUN echo "mimixbox ALL=(ALL) ALL" >> /etc/sudoers 30 | CMD ["su", "-", "mimixbox"] -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | APP := mimixbox 2 | PREPARE_UT := test/ut/prepareUnitTest.sh 3 | INSTALLER := scripts/installer.sh 4 | MK_JAIL := scripts/mkJailForDebianFamily.sh 5 | MK_MAN := scripts/mkManpages.sh 6 | RELEASE := scripts/release.sh 7 | 8 | build: ## Build mimixbox and make man-pages 9 | go build "-ldflags=-s -w" -trimpath -o $(APP) cmd/mimixbox/main.go 10 | $(MAKE) doc 11 | $(MAKE) licenses 12 | 13 | clean: ## Clean project 14 | -rm mimixbox 15 | -rm -rf vendor 16 | -rm cover.* 17 | -rm -rf /tmp/mimixbox/ut/* 18 | -rm -rf release 19 | -rm -rf licenses 20 | -find . -name "*.1.gz" | xargs rm -f 21 | 22 | doc: ## Make man-pages 23 | $(MK_MAN) 24 | 25 | docker: ## Run container for testing mimixbox 26 | docker image build -t mimixbox/test:latest . 27 | docker container run --rm -it mimixbox/test:latest 28 | 29 | install: ## Install mimixbox (with symbolic link) and man-pages on your system 30 | $(INSTALLER) 31 | 32 | full-install: ## Full Install mimixbox (with symbolic link) and man-pages on your system 33 | -$(INSTALLER) 34 | mimixbox --full-install /usr/local/bin 35 | 36 | remove: ## Remove mimixbox-symbolic link 37 | mimixbox --remove /usr/local/bin 38 | 39 | it: ## Execute integration test 40 | cd test/it && shellspec --shell /bin/bash 41 | 42 | jail: ## Make jail environment for testing chroot/ischroot 43 | $(MK_JAIL) 44 | 45 | release: ## Make release files. 46 | $(RELEASE) 47 | 48 | licenses: ## Get licenses for dependent libraries 49 | -@go-licenses save ./cmd/mimixbox --force --save_path "licenses/" 50 | 51 | pre_ut: 52 | @echo "Clean test directory." 53 | -@rm -rf /tmp/mimixbox/ut/* 54 | @echo "Make files for test at test directory." 55 | @$(PREPARE_UT) 56 | 57 | ut: pre_ut ## Execute unit test 58 | -@go test -cover ./... -v -coverpkg=./... -coverprofile=cover.out 59 | -@go tool cover -html=cover.out -o cover.html 60 | @echo "--------------------------------------------------------------------" 61 | -@rm -rf /tmp/mimixbox/ut/* 62 | @echo "The tool saved the coverage information in an HTML. See cover.html" 63 | 64 | 65 | .DEFAULT_GOAL := help 66 | .PHONY: build clean doc docker install jail release deps it ut pre_ut 67 | 68 | help: 69 | @grep -E '^[0-9a-zA-Z_-]+[[:blank:]]*:.*?## .*$$' $(MAKEFILE_LIST) | sort \ 70 | | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[1;32m%-15s\033[0m %s\n", $$1, $$2}' -------------------------------------------------------------------------------- /docs/examples/fakemovie/en/fakemovie.md: -------------------------------------------------------------------------------- 1 | # fakemovie: Add movie start button at image 2 | fakemovie add movie start button at image. [Original version made by Mr. mattn](https://github.com/mattn/fakemovie). MimixBox version has some functions added. 3 | 4 | ## How to Use 5 | ``` Usage 6 | fakemovie [OPTIONS] IMAGE_FILE_NAME 7 | ``` 8 | 9 | | short option | long option | description | 10 | |:------|:-----|:------| 11 | |-o| --output| Output file name
(default: Added suffix "_fake" to original name) | 12 | |-p|--phub| Put p-hub button
(default: Color similar to twitter button)| 13 | |-r|--radius| Radius of button
(default: Auto caluculate)| 14 | | -h | --help | Show help messages  | 15 | | -v | --version | Show version| 16 | 17 | 18 | ## Examples 19 | ### Put like Twitter button 20 | ``` 21 | $ fakemovie lena.png 22 | ``` 23 | 24 | ![Original](../../../images/lena.png "Original") 25 | ![Twitter](../../../images/lena_twitter_fake.png "Twitter") 26 | 27 | ### Put like P-hub button 28 | ``` 29 | $ fakemovie -p lena.png -o lena_phub_fake.png 30 | ``` 31 | ![Original](../../../images/lena.png "Original") 32 | ![Phub](../../../images/lena_phub_fake.png "Phub") -------------------------------------------------------------------------------- /docs/examples/fakemovie/ja/fakemovie.md: -------------------------------------------------------------------------------- 1 | # fakemovie: 画像に動画開始ボタンを付与 2 | fakemovieは、画像に動画開始ボタンを付与する。オリジナル版は、[mattn氏が作成したコマンド](https://github.com/mattn/fakemovie)であり、MimixBox版はそこから一部改変を加えている。 3 | 4 | ## 使い方 5 | ``` Usage 6 | fakemovie [OPTIONS] IMAGE_FILE_NAME 7 | ``` 8 | 9 | | short option | long option | description | 10 | |:------|:-----|:------| 11 | |-o| --output| 出力先ファイル名を指定する
(デフォルト:オリジナル名にサフィックス"_fake"を付与する) | 12 | |-p|--phub| ボタンをp-hub風とする
(デフォルトはTwitter風)| 13 | |-r|--radius| ボタンの半径を設定する
(デフォルトは自動計算)| 14 | | -h | --help | ヘルプメッセージを表示する  | 15 | | -v | --version | バージョンを表示する| 16 | 17 | 18 | ## 実行例 19 | ### Twitter風ボタン 20 | ``` 21 | $ fakemovie lena.png 22 | ``` 23 | 24 | ![オリジナル](../../../images/lena.png "オリジナル") 25 | ![Twitter風](../../../images/lena_twitter_fake.png "Twitter風") 26 | 27 | ### P-hub風ボタン 28 | ``` 29 | $ fakemovie -p lena.png -o lena_phub_fake.png 30 | ``` 31 | ![オリジナル](../../../images/lena.png "オリジナル") 32 | ![Phub風](../../../images/lena_phub_fake.png "Phub風") -------------------------------------------------------------------------------- /docs/examples/ghrdc/en/ghrdc.md: -------------------------------------------------------------------------------- 1 | # ghrdc - GitHub Release Downloads Counter 2 | ghrdc shows the number of Release file downloads in the repository using GitHub API. By default, it shows the number of downloads for the latest release. Because ghrdc does not authenticate with the GitHub API, it has the following restrictions. 3 | - It can only be run 60 times per hour. 4 | - Unable to get information in Organization repository. 5 | - Unable to get information in private repository 6 | 7 | ## How to Use 8 | ``` Usage 9 | $ ghrdc [OPTIONS] USER_NAME/RPOSITORY_NAME 10 | ``` 11 | 12 | | short option | long option | description | 13 | |:------|:-----|:------| 14 | | -a | --all | Show total number of downloads per release. | 15 | | -t | --total | Show total number of downloads for all releases. | 16 | | -h | --help | Show help message.  | 17 | | -v | --version | Show version.| 18 | 19 | ## Examples 20 | ### Get the number of downloads for the latest release 21 | ``` 22 | $ ghrdc nao1215/mimixbox 23 | [Name(Version)] :Version 0.12.1 24 | [Release Date] :2021-11-20 04:00:23 +0000 UTC 25 | [Binary Download Count] :0 26 | [Source Code Download Count]:0 27 | ``` 28 | 29 | ### Get the total number of downloads for all releases. 30 | ``` 31 | $ ghrdc -t nao1215/mimixbox 32 | [Name(Version)] :All release 33 | [Release Date] :- 34 | [Binary Download Count(total)] :0 35 | [Source Code Download Count(total)]:0 36 | ``` 37 | 38 | ### Get the total number of downloads per release. 39 | ``` 40 | $ ghrdc -a nao1215/mimixbox 41 | [Name(Version)] :Version 0.12.1 42 | [Release Date] :2021-11-20 04:00:23 +0000 UTC 43 | [Binary Download Count] :0 44 | [Source Code Download Count]:0 45 | 46 | [Name(Version)] :Version 0.9.1 47 | [Release Date] :2021-11-19 07:27:19 +0000 UTC 48 | [Binary Download Count] :0 49 | [Source Code Download Count]:0 50 | 51 | [Name(Version)] :Version 0.6.0 52 | [Release Date] :2021-11-18 13:54:57 +0000 UTC 53 | [Binary Download Count] :0 54 | [Source Code Download Count]:0 55 | 56 | [Name(Version)] :Version 0.3.0 57 | [Release Date] :2021-11-16 17:17:09 +0000 UTC 58 | [Binary Download Count] :0 59 | [Source Code Download Count]:0 60 | 61 | [Name(Version)] :Version 0.1.1 62 | [Release Date] :2021-11-15 16:06:40 +0000 UTC 63 | [Binary Download Count] :0 64 | [Source Code Download Count]:0 65 | 66 | [Name(Version)] :MimixBox Version 0.0.1 (Buggy) 67 | [Release Date] :2021-11-14 13:02:27 +0000 UTC 68 | [Binary Download Count] :0 69 | [Source Code Download Count]:0 70 | ``` -------------------------------------------------------------------------------- /docs/examples/ghrdc/ja/ghrdc.md: -------------------------------------------------------------------------------- 1 | # ghrdc - GitHub Release Downloads Counter 2 | ghrdcコマンドは、GitHub APIを用いてリリースファイルのダウンロード数を表示する。デフォルトでは、最新リリースのダウンロード数を表示する。ghrdcコマンドはGitHub API認証しないため、制約がある。 3 | - 一時間あたりに60回しか使用できない 4 | - Organization repositoryの情報を取得できない 5 | - Private repositoryの情報を取得できない 6 | 7 | ## 使い方 8 | ``` Usage 9 | $ ghrdc [OPTIONS] USER_NAME/RPOSITORY_NAME 10 | ``` 11 | 12 | | short option | long option | description | 13 | |:------|:-----|:------| 14 | | -a | --all | リリース毎のダウンロード数を表示する | 15 | | -t | --total | 全リリースのダウンロード数を表示する| 16 | | -h | --help | ヘルプメッセージを表示する | 17 | | -v | --version | バージョンを表示する| 18 | 19 | ## 実行例 20 | ### 最新リリースのダウンロード数を表示 21 | ``` 22 | $ ghrdc nao1215/mimixbox 23 | [Name(Version)] :Version 0.12.1 24 | [Release Date] :2021-11-20 04:00:23 +0000 UTC 25 | [Binary Download Count] :0 26 | [Source Code Download Count]:0 27 | ``` 28 | 29 | ### 全リリースのダウンロード数を表示 30 | ``` 31 | $ ghrdc -t nao1215/mimixbox 32 | [Name(Version)] :All release 33 | [Release Date] :- 34 | [Binary Download Count(total)] :0 35 | [Source Code Download Count(total)]:0 36 | ``` 37 | 38 | ### リリース毎のダウンロード数を表示 39 | ``` 40 | $ ghrdc -a nao1215/mimixbox 41 | [Name(Version)] :Version 0.12.1 42 | [Release Date] :2021-11-20 04:00:23 +0000 UTC 43 | [Binary Download Count] :0 44 | [Source Code Download Count]:0 45 | 46 | [Name(Version)] :Version 0.9.1 47 | [Release Date] :2021-11-19 07:27:19 +0000 UTC 48 | [Binary Download Count] :0 49 | [Source Code Download Count]:0 50 | 51 | [Name(Version)] :Version 0.6.0 52 | [Release Date] :2021-11-18 13:54:57 +0000 UTC 53 | [Binary Download Count] :0 54 | [Source Code Download Count]:0 55 | 56 | [Name(Version)] :Version 0.3.0 57 | [Release Date] :2021-11-16 17:17:09 +0000 UTC 58 | [Binary Download Count] :0 59 | [Source Code Download Count]:0 60 | 61 | [Name(Version)] :Version 0.1.1 62 | [Release Date] :2021-11-15 16:06:40 +0000 UTC 63 | [Binary Download Count] :0 64 | [Source Code Download Count]:0 65 | 66 | [Name(Version)] :MimixBox Version 0.0.1 (Buggy) 67 | [Release Date] :2021-11-14 13:02:27 +0000 UTC 68 | [Binary Download Count] :0 69 | [Source Code Download Count]:0 70 | ``` -------------------------------------------------------------------------------- /docs/examples/path/en/path.md: -------------------------------------------------------------------------------- 1 | # path: manipulating filename path 2 | path extracts the directory name, file name, and extension from the path. It also create canonical path and absolute path. 3 | 4 | ## How to Use 5 | ``` Usage 6 | $ path [OPTIONS] PATH 7 | ``` 8 | 9 | | short option | long option | description | 10 | |:------|:-----|:------| 11 | | -a | --absolute | Print absolute path. | 12 | | -b | --basename | Print basename (filename). | 13 | | -c | --canonical | Print canonical path (default). | 14 | | -d | --dirname | Print path without filename. | 15 | | -e | --extension | Print file extention. | 16 | | -h | --help | Show help message.  | 17 | | -v | --version | Show version.| 18 | 19 | ## Examples 20 | ### Get absolute path 21 | ``` 22 | $ path -a path 23 | /home/nao/.go/src/otter/path 24 | ``` 25 | 26 | ### Get basename 27 | ``` 28 | $ path -b /etc/systemd/pstore.conf 29 | pstore.conf 30 | ``` 31 | 32 | ### Get canonical path 33 | ``` 34 | $ path -c cmd/../scripts/installer.sh 35 | scripts/installer.sh 36 | ``` 37 | 38 | ### Get dirctory name 39 | ``` 40 | $ path -d /etc/ssh/ssh_config 41 | /etc/ssh 42 | ``` 43 | 44 | ### Get file extension 45 | ``` 46 | $ path -e go.mod 47 | .mod 48 | ``` 49 | -------------------------------------------------------------------------------- /docs/examples/path/ja/path.md: -------------------------------------------------------------------------------- 1 | # path: ファイルパス操作 2 | pathコマンドは、ディレクトリ名、ファイル名、拡張子をPATHから抽出する。Canonical PATHや絶対PATHも生成できる。 3 | 4 | ## 使い方 5 | ``` Usage 6 | $ path [OPTIONS] PATH 7 | ``` 8 | 9 | | short option | long option | description | 10 | |:------|:-----|:------| 11 | | -a | --absolute | 絶対PATHを表示する| 12 | | -b | --basename | ベースネームを表示する(デフォルト) | 13 | | -c | --canonical | Canonical PATHを表示する(デフォルト)| 14 | | -d | --dirname | ファイル名を取り除いたPATHを表示する | 15 | | -e | --extension | ファイル拡張子を表示する | 16 | | -h | --help | ヘルプメッセージを表示する  | 17 | | -v | --version | バージョンを表示する | 18 | 19 | ## 実行例 20 | ### 絶対PATHの取得 21 | ``` 22 | $ path -a path 23 | /home/nao/.go/src/otter/path 24 | ``` 25 | 26 | ### ベースネームの取得 27 | ``` 28 | $ path -b /etc/systemd/pstore.conf 29 | pstore.conf 30 | ``` 31 | 32 | ### Canonical PATHの取得 33 | ``` 34 | $ path -c cmd/../scripts/installer.sh 35 | scripts/installer.sh 36 | ``` 37 | 38 | ### ディレクトリ名の取得 39 | ``` 40 | $ path -d /etc/ssh/ssh_config 41 | /etc/ssh 42 | ``` 43 | 44 | ### ファイル拡張子の取得 45 | ``` 46 | $ path -e go.mod 47 | .mod 48 | ``` 49 | -------------------------------------------------------------------------------- /docs/examples/sddf/en/sddf.md: -------------------------------------------------------------------------------- 1 | # sddf: Search & Delete Duplicated File 2 | sddf command looks for files with the same data content and removes duplicate files. After deletion, only the latest file remains among the duplicate files. The identity of the files is confirmed by the md5 checksum in consideration of speed. 3 | 4 | ## How to use 5 | ```Usage 6 | $ sddf [OPTIONS] PATH 7 | ``` 8 | 9 | | short option | long option | description | 10 | |:------|:-----|:------| 11 | | -o | --output | Change output file-name without extension (default: duplicated-file.sddf)| 12 | | -h | --help | Show help message | 13 | | -v | --version | Show version| 14 | 15 | ## Examples 16 | ### Search duplicated file 17 | ``` 18 | (comment) directory structure 19 | $ tree . 20 | . 21 | ├── abc 22 | │   └── ev095b.bmp 23 | ├── def 24 | │   ├── ev088a.bmp 25 | │   ├── ev092g.bmp 26 | │   └── ghi 27 | │   └── ev088a.bmp 28 | └── ev088a.bmp 29 | 30 | 31 | $ sddf . 32 | Get all file path at . 33 | . 34 | Find the same file on a file content basis 35 | 5 / 5 [----------------------------------------------------------------] 100.00% 36 | Write down duplicated file list to duplicated-file.sddf 37 | 1 / 1 [----------------------------------------------------------------] 100.00% 38 | See duplicated file list: duplicated-file.sddf 39 | If you delete files, execute the following command. 40 | $ sddf duplicated-file.sddf 41 | 42 | (comment) check duplicated file list. 43 | $ cat duplicated-file.sddf 44 | [6121d44e98dc80f4f39937f13827547b] 45 | def/ev088a.bmp 46 | def/ghi/ev088a.bmp 47 | ev088a.bmp 48 | ``` 49 | 50 | ### Delete duplicated file 51 | ``` 52 | $ sddf duplicated-file.sddf 53 | Restore data from duplicated-file.sddf 54 | 5 / 5 [----------------------------------------------------------------] 100.00% 55 | Decide delete target files 56 | Start deleting files 57 | Delete(Success): ev088a.bmp: 3145782Byte 58 | Delete(Success): def/ghi/ev088a.bmp: 3145782Byte 59 | End deleting files. Size=6291564Byte 60 | 61 | $ tree 62 | . 63 | ├── abc 64 | │   └── ev095b.bmp 65 | ├── def 66 | │   ├── ev088a.bmp 67 | │   ├── ev092g.bmp 68 | │   └── ghi 69 | └── duplicated-file.sddf 70 | ``` 71 | -------------------------------------------------------------------------------- /docs/examples/sddf/ja/sddf.md: -------------------------------------------------------------------------------- 1 | # sddf: Search & Delete Duplicated File 2 | sddfコマンドは、データ内容が同じファイルを探し、重複ファイルを削除する。削除後は、重複ファイルのうち、最新ファイルのみが残る。なお、ファイルの同一性は、速度面を考慮してmd5チェックサムで確認している。 3 | 4 | ## 使い方 5 | ```Usage 6 | $ sddf [OPTIONS] PATH 7 | ``` 8 | 9 | | short option | long option | description | 10 | |:------|:-----|:------| 11 | | -o | --output | 重複ファイル一覧の出力先ファイル名を拡張子無しで指定(デフォルト:duplicated-file.sddf)| 12 | | -h | --help | ヘルプメッセージを表示する | 13 | | -v | --version | バージョンを表示する| 14 | 15 | ## 実行例 16 | ### 重複ファイルを探す 17 | ``` 18 | (注釈) ディレクトリ構成 19 | $ tree . 20 | . 21 | ├── abc 22 | │   └── ev095b.bmp 23 | ├── def 24 | │   ├── ev088a.bmp 25 | │   ├── ev092g.bmp 26 | │   └── ghi 27 | │   └── ev088a.bmp 28 | └── ev088a.bmp 29 | 30 | 31 | $ sddf . 32 | Get all file path at . 33 | . 34 | Find the same file on a file content basis 35 | 5 / 5 [----------------------------------------------------------------] 100.00% 36 | Write down duplicated file list to duplicated-file.sddf 37 | 1 / 1 [----------------------------------------------------------------] 100.00% 38 | See duplicated file list: duplicated-file.sddf 39 | If you delete files, execute the following command. 40 | $ sddf duplicated-file.sddf 41 | 42 | (注釈)重複ファイル一覧の確認 43 | $ cat duplicated-file.sddf 44 | [6121d44e98dc80f4f39937f13827547b] 45 | def/ev088a.bmp 46 | def/ghi/ev088a.bmp 47 | ev088a.bmp 48 | ``` 49 | 50 | ### 重複ファイルの削除 51 | ``` 52 | $ sddf duplicated-file.sddf 53 | Restore data from duplicated-file.sddf 54 | 5 / 5 [----------------------------------------------------------------] 100.00% 55 | Decide delete target files 56 | Start deleting files 57 | Delete(Success): ev088a.bmp: 3145782Byte 58 | Delete(Success): def/ghi/ev088a.bmp: 3145782Byte 59 | End deleting files. Size=6291564Byte 60 | 61 | $ tree 62 | . 63 | ├── abc 64 | │   └── ev095b.bmp 65 | ├── def 66 | │   ├── ev088a.bmp 67 | │   ├── ev092g.bmp 68 | │   └── ghi 69 | └── duplicated-file.sddf 70 | ``` 71 | -------------------------------------------------------------------------------- /docs/examples/serial/en/serial.md: -------------------------------------------------------------------------------- 1 | ![Serial logo](../../../images/serial.jpg "Serial logo") 2 | # serial: Add serial number to file name 3 | serial is a CLI command that renames files under any directory to the format "specified file name + serial number". 4 | The original version was released as a standalone command, but now it is one of the MimixBox commands. 5 | 6 | ## How to use 7 | ```Usage 8 | $ serial [OPTIONS] DIRECTORY_PATH 9 | ``` 10 | 11 | | short option | long option | description | 12 | |:------|:-----|:------| 13 | | -d | --dry-run | Output the file renaming result to standard output (do not update the file)  | 14 | | -f | --force | Forcibly overwrite and save even if a file with the same name exists  | 15 | | -h | --help | Show help message  | 16 | | -k | --keep | Keep the file before renaming  | 17 | | -n | --name | Base file name with/without directory path (assign a serial number to this file name) | 18 | | -p | --prefix | Add a serial number to the beginning of the file name | 19 | | -s | --suffix | Add a serial number to the end of the file name(default) | 20 | | -v | --version | Show serial command version | 21 | 22 | ## Examples 23 | ### Default (Add serial number at prefix) 24 | ``` 25 | $ ls 26 | a.txt b.txt c.txt d.txt e.txt 27 | 28 | $ serial . 29 | Rename a.txt to 0_a.txt 30 | Rename b.txt to 1_b.txt 31 | Rename c.txt to 2_c.txt 32 | Rename d.txt to 3_d.txt 33 | Rename e.txt to 4_e.txt 34 | 35 | $ ls 36 | 0_a.txt 1_b.txt 2_c.txt 3_d.txt 4_e.txt 37 | ``` 38 | 39 | ### Rename filename and add serial number at suffix 40 | ``` 41 | $ ls 42 | a.txt b.txt c.txt d.txt e.txt 43 | 44 | $ serial --suffix --name=demo . 45 | Rename a.txt to demo_0.txt 46 | Rename b.txt to demo_1.txt 47 | Rename c.txt to demo_2.txt 48 | Rename d.txt to demo_3.txt 49 | Rename e.txt to demo_4.txt 50 | 51 | $ ls 52 | demo_0.txt demo_1.txt demo_2.txt demo_3.txt demo_4.txt 53 | ``` 54 | 55 | ### Keep original files 56 | ``` 57 | $ ls 58 | a.txt b.txt c.txt d.txt e.txt 59 | 60 | $ serial --keep . 61 | Copy a.txt to 0_a.txt 62 | Copy b.txt to 1_b.txt 63 | Copy c.txt to 2_c.txt 64 | Copy d.txt to 3_d.txt 65 | Copy e.txt to 4_e.txt 66 | 67 | $ ls 68 | 0_a.txt 1_b.txt 2_c.txt 3_d.txt 4_e.txt a.txt b.txt c.txt d.txt e.txt 69 | ``` 70 | 71 | 72 | ## Credits 73 | The serial command project logo was created by the [DesignEvo (online logo maker)](https://www.designevo.com/). -------------------------------------------------------------------------------- /docs/examples/serial/ja/serial.md: -------------------------------------------------------------------------------- 1 | ![Serial logo](../../../images/serial.jpg "Serial logo") 2 | # serial: シリアル番号をファイル名に付与 3 | serialは、指定されたディレクト以下にあるファイルに対してシリアル番号を付与するCLIコマンドである。オリジナル版は、単独のコマンドとしてリリースしましたが、現在はMimixBoxのコマンドの一部としている。 4 | 5 | ## 使い方 6 | ```Usage 7 | $ serial [OPTIONS] DIRECTORY_PATH 8 | ``` 9 | 10 | | short option | long option | description | 11 | |:------|:-----|:------| 12 | | -d | --dry-run | ファイルを更新せずに、更新後のファイル名を出力する | 13 | | -f | --force | 同名ファイルが存在した場合、強制的に上書きする  | 14 | | -h | --help | ヘルプメッセージを表示する  | 15 | | -k | --keep | リネーム前ファイルをバックアップとして残す | 16 | | -n | --name | リネーム後ファイル名のベースネーム(拡張子は含まない) | 17 | | -p | --prefix | シリアル番号をファイル名の先頭に付与する | 18 | | -s | --suffix | シリアル番号をファイル名の末尾(拡張子の前)に付与する(デフォルトの動作) | 19 | | -v | --version | バージョンを表示する| 20 | 21 | ## 実行例 22 | ### デフォルト (プレフィックスにシリアル番号をつける場合) 23 | ``` 24 | $ ls 25 | a.txt b.txt c.txt d.txt e.txt 26 | 27 | $ serial . 28 | Rename a.txt to 0_a.txt 29 | Rename b.txt to 1_b.txt 30 | Rename c.txt to 2_c.txt 31 | Rename d.txt to 3_d.txt 32 | Rename e.txt to 4_e.txt 33 | 34 | $ ls 35 | 0_a.txt 1_b.txt 2_c.txt 3_d.txt 4_e.txt 36 | ``` 37 | 38 | ### サフィックスにシリアル番号を付与する場合 39 | ``` 40 | $ ls 41 | a.txt b.txt c.txt d.txt e.txt 42 | 43 | $ serial --suffix --name=demo . 44 | Rename a.txt to demo_0.txt 45 | Rename b.txt to demo_1.txt 46 | Rename c.txt to demo_2.txt 47 | Rename d.txt to demo_3.txt 48 | Rename e.txt to demo_4.txt 49 | 50 | $ ls 51 | demo_0.txt demo_1.txt demo_2.txt demo_3.txt demo_4.txt 52 | ``` 53 | 54 | ### オリジナルファイルを残す場合 55 | ``` 56 | $ ls 57 | a.txt b.txt c.txt d.txt e.txt 58 | 59 | $ serial --keep . 60 | Copy a.txt to 0_a.txt 61 | Copy b.txt to 1_b.txt 62 | Copy c.txt to 2_c.txt 63 | Copy d.txt to 3_d.txt 64 | Copy e.txt to 4_e.txt 65 | 66 | $ ls 67 | 0_a.txt 1_b.txt 2_c.txt 3_d.txt 4_e.txt a.txt b.txt c.txt d.txt e.txt 68 | ``` 69 | 70 | ## クレジット 71 | シリアルコマンドロゴは、[DesignEvo (online logo maker)](https://www.designevo.com/)によって作成されている。 72 | -------------------------------------------------------------------------------- /docs/images/debug_logging.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nao1215/mimixbox/063fffce9c5b7165e5d8315711dd3fc74f22158e/docs/images/debug_logging.jpg -------------------------------------------------------------------------------- /docs/images/drawio/debug_logging.drawio: -------------------------------------------------------------------------------- 1 | 7Vttc9o4EP41nrn7UMYv2IaPIZBLZ5Jrppm7Jp9uhK0aFdniZJFAf30lW34XgQYbkzbTmRStZCHtPs/uamU06zLc/EXBanFLfIg1U/c3mjXVTHNsOvyvEGxTwUgfp4KAIj8VGYXgHn2HUqhL6Rr5MK4MZIRghlZVoUeiCHqsIgOUkufqsK8EV791BQLYENx7ADelX5DPFnIXplvIryEKFtk3G47cXwiywXIn8QL45LkksmaadUkJYemncHMJsdBdppf0uasdvfnCKIzYIQ88TG6v7WuC8Df/39H19+WWfZ5+kIt9AngtNywXy7aZBihZRz4Uk+iaNXleIAbvV8ATvc/c5Fy2YCHmLYN//IowviSYUN6OSMQHTeQ3QMrgZufSjVwhHEiQhJDRLR+SPeBIHUoQmVn7uTCJqUvZomQO05VCIGEQ5HMXmuIfpLJ+QnGG1VAU9DlyZJNQtiABiQCeFdJJVZXFmBtCVlKB3yBjW0kDsGakql64QexBPD6wZeux1DPdyJmTxjZrRHy/D+XGYzGDaBaPJa3suZgByi4Ehbhgjom3zIRXCOcLivxsiDQ3l8h+PTe+0MzLpueKJGvqwZc0LtkPaADZC+NsNZQoxIChp+o6VLCQj94RxFeYQ9CtItAya8BKlyUfqmErX8URcBu+w+084eYcCbfjvJD9DovzhIXbKyzcd1icJyxGvcJCkew5mIm0jSSxrsCL8/+aZB0f4sTiF3wAV86m6OSfAvH/LQrRZkI22Wx8cemEafdxGWUL6WM9e9Sb2aNhKrJHq6vkMT8SnD8/eeMOUsT3DWmDswVNHyssVXO2RbpZB9Jt3CfdrP1nq5XIFyGdPXENxNIY+TlR6MwH8SK3ecmWMaNkCWsnLQzmEN+RGDFEIi72YJRYbSLYg/iZ9qY2YE4YI2FpwAVGgehgAlITIFv5POXTnWZati7+pUteiR2Fm0AUAQZh7AE44FtbR3CwjiH9L+DoXbVAZTPLeCSXjWGTy2MFlTs7B5q9JuZGicgFrfeF2iptjT20TVp1H1CJvxJ+5fCrV8Ovh0EcI68SgY12XYJ9oEswrT59gr0zBMcrEL0+BHMvIb48j7/pbGcSf/OAmwVgt/cA3Ou56Z211dPz2bPW6Yi14dJH9K2w1rJ6Z63KDqen8fmxyH0TLHI7YhEN3wyFxr1TqJ/K0K8dxEZvgn6jjujnAfZW+DdUnBZPyz+jKytosyttcqmNLzqxheJaV1mB6MJmvR8WDNUl+bvNXrCZ3X+FtYVat6Gy2f02nBPM44mcbU6zHoyi5aEVcK5qVrVWVmujqXIaFbkQ+X4ajCFfIpgnMwkUJCXERH32RLOnYioef9Nt7C4VtmB0u8ZTxTsZhuqdjGFnNjc7svk/MdTEG0ZhCCI/Pt7Gjbrs+Rq5cXdiKqzsKKxcfz+ivaq60dB0b3cnebXmFXcn5Tz4J+87zyLpNQ+9g7F0NcJOk/WaqluYNpzC3yDkgDL1u493sz+uPl59+vNQx5DdlnhbHjJ8SK39sXye4vdmnguAtwwSVH9aMz5N7gekS7DVCYCPKPTk5Q+3sGBwG15iWPMSlirPVnkJp7NYsDtnO87sXyg3lCL4k6Ap/K0ixbBe68hq7CUMqCDQWTpg9VLjPz9HneXY+x11r+WJbJmdv51SIW2AIk5cfQpgSKLXM/jkb7SM6g7XHDTpZowUfLPtrgy4O/0++JisdLmfIfBf9Lj7js2/hH91jP3+1T2pf20hs1IS9kYVS7lvhIeycQ//6m+rzAH3wAOfeOswsYUqcWoApgWLusPaCXp4WMR0OmNwC/ecr0yafgsKuzWvPdQ7S5F4s/hlUfojhOLnWdbsBw== -------------------------------------------------------------------------------- /docs/images/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nao1215/mimixbox/063fffce9c5b7165e5d8315711dd3fc74f22158e/docs/images/lena.png -------------------------------------------------------------------------------- /docs/images/lena_phub_fake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nao1215/mimixbox/063fffce9c5b7165e5d8315711dd3fc74f22158e/docs/images/lena_phub_fake.png -------------------------------------------------------------------------------- /docs/images/lena_twitter_fake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nao1215/mimixbox/063fffce9c5b7165e5d8315711dd3fc74f22158e/docs/images/lena_twitter_fake.png -------------------------------------------------------------------------------- /docs/images/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nao1215/mimixbox/063fffce9c5b7165e5d8315711dd3fc74f22158e/docs/images/logo.jpg -------------------------------------------------------------------------------- /docs/images/serial.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nao1215/mimixbox/063fffce9c5b7165e5d8315711dd3fc74f22158e/docs/images/serial.jpg -------------------------------------------------------------------------------- /docs/man/fakemovie/en/fakemovie.1.md: -------------------------------------------------------------------------------- 1 | % FAKEMOVIE(1) 2 | % Naohiro CHIKAMATSU 3 | % September 2021 4 | 5 | # NAME 6 | 7 | fakemovie – add fake-movie button to the image. 8 | 9 | # SYNOPSIS 10 | 11 | **fakemovie** [OPTIONS] IMAGE_FILE_NAME 12 | 13 | # DESCRIPTION 14 | **fakemovie** adds a video playback button to the image. 15 | The supported image formats are png or jpg. Otherwise, an error will occur at runtime. 16 | 17 | # EXAMPLES 18 | **When using the default output file name** 19 | $ fakemovie image.jpg 20 | $ ls 21 | image.jpg image_fake.jpg 22 | 23 | **When specifying the output file name, button color, and button size** 24 | $ fakemovie -p -o output.jpg -r 50 output.jpg 25 | $ ls 26 | image.jpg output.jpg 27 | 28 | 29 | # OPTIONS 30 | **-o**, **--output** 31 | : Specify output file name. By default, added suffix "_fake" to original file name. 32 | 33 | **-p**, **--phub** 34 | : Change button color to p-hub. By default, button color is similar to twitter button. 35 | 36 | **-r**, **--radius** 37 | : Specify radius value(integer) of button. The default is an automatically calculated value based on the image size. 38 | 39 | **-h**, **--help** 40 | : Show help message. 41 | 42 | **-v**, **--version** 43 | : Show fakemovie command version. 44 | 45 | # EXIT VALUES 46 | **0** 47 | : Success 48 | 49 | **1** 50 | : There is an error in the argument of the path command or image processing run-time error. 51 | 52 | # BUGS 53 | See GitHub Issues: https://github.com/nao1215/mimixbox/issues 54 | 55 | # LICENSE 56 | The MimixBox project is licensed under the terms of the MIT license and Apache License 2.0. -------------------------------------------------------------------------------- /docs/man/fakemovie/ja/fakemovie.1.md: -------------------------------------------------------------------------------- 1 | % FAKEMOVIE(1) 2 | % Naohiro CHIKAMATSU 3 | % 2021年9月 4 | 5 | # 名前 6 | 7 | fakemovie – 画像に動画再生ボタンを付与します。 8 | 9 | # 書式 10 | 11 | **fakemovie** [OPTIONS] IMAGE_FILE_NAME 12 | 13 | # 説明 14 | **fakemovie**は、画像に動画再生ボタンを付与します。 15 | 対応している画像フォーマットは、pngかjpgです。それ以外は実行時にエラーとなります。 16 | 17 | # 例 18 | **デフォルトの出力ファイル名を使用する場合** 19 | $ fakemovie image.jpg 20 | $ ls 21 | image.jpg image_fake.jpg 22 | 23 | **出力ファイル名、ボタン色、ボタンサイズを指定する場合** 24 | $ fakemovie -p -o output.jpg -r 50 output.jpg 25 | $ ls 26 | image.jpg output.jpg 27 | 28 | 29 | # オプション 30 | **-o**, **--output** 31 | : アウトプットファイル名を指定します。デフォルトは、オリジナル名に"_fake"を付与します。 32 | 33 | **-p**, **--phub** 34 | : ボタンの色をp-hubライクにします。デフォルトはTwitterに似た色です。 35 | 36 | **-r**, **--radius** 37 | : ボタンの半径(整数)を指定します。デフォルトは画像サイズを元にした自動計算値です。 38 | 39 | **-h**, **--help** 40 | : ヘルプメッセージを表示します。 41 | 42 | **-v**, **--version** 43 | : fakemovieコマンドのバージョンを表示します。 44 | 45 | # 終了ステータス 46 | **0** 47 | : 成功 48 | 49 | **1** 50 | : fakemovieコマンドの引数指定でエラー、もしくは画像処理の実行時エラー 51 | 52 | # バグ 53 | GitHub Issuesを参照してください。URL:https://github.com/nao1215/mimixbox/issues 54 | 55 | # ライセンス 56 | MimixBoxプロジェクトは、MIT License条文およびApache License 2.0条文の下でライセンスされています。 -------------------------------------------------------------------------------- /docs/man/ghrdc/en/ghrdc.1.md: -------------------------------------------------------------------------------- 1 | % GHRDC(1) 2 | % Naohiro CHIKAMATSU 3 | % September 2021 4 | 5 | # NAME 6 | 7 | ghrdc – shows the number of release file downloads in the repository using GitHub API. 8 | 9 | # SYNOPSIS 10 | 11 | **ghrdc** [OPTIONS] USER_NAME/RPOSITORY_NAME 12 | 13 | # DESCRIPTION 14 | **ghrdc** shows the number of Release file downloads in the repository. 15 | By default, it shows the number of downloads for the latest release. 16 | Because ghrdc does not authenticate with the GitHub API, it has the following restrictions. 17 | - It can only be run 60 times per hour. 18 | - Unable to get information in Organization repository. 19 | 20 | # EXAMPLES 21 | **Get the number of downloads for the latest release** 22 | $ ghrdc nao1215/serial 23 | [Name(Version)] :Version1.0.2: Release files with installer scripts. 24 | [Release Date] :2020-11-23 05:28:11 +0000 UTC 25 | [Binary Download Count] :177 26 | [Source Code Download Count]:0 27 | 28 | # OPTIONS 29 | **-a**, **--all** 30 | : Show total number of downloads per release. 31 | 32 | **-t**, **--total** 33 | : Show total number of downloads for all releases. 34 | 35 | **-h**, **--help** 36 | : Show help message. 37 | 38 | **-v**, **--version** 39 | : Show ghrdc command version. 40 | 41 | 42 | # EXIT VALUES 43 | **0** 44 | : Success 45 | 46 | **1** 47 | : There is an error in the argument of the path command or GitHub API runtime error. 48 | 49 | # BUGS 50 | See GitHub Issues: https://github.com/nao1215/mimixbox/issues 51 | 52 | # LICENSE 53 | The MimixBox project is licensed under the terms of the MIT license and Apache License 2.0. -------------------------------------------------------------------------------- /docs/man/ghrdc/ja/ghrdc.1.md: -------------------------------------------------------------------------------- 1 | % GHRDC(1) 2 | % Naohiro CHIKAMATSU 3 | % 2021年9月 4 | 5 | # 名前 6 | 7 | ghrdc – GitHub APIを利用して、レポジトリのReleaseファイルダウンロード数を表示します。 8 | 9 | # 書式 10 | 11 | **ghrdc** [OPTIONS] USER_NAME/RPOSITORY_NAME 12 | 13 | # 説明 14 | **ghrdc**は、レポジトリのReleaseファイルダウンロード数を表示します。 15 | デフォルトでは、最新リリースに対するダウンロード数を表示します。 16 | GitHub API認証を行わないため、以下の制約があります。 17 | - 1時間あたりに60回だけ実行できます。 18 | - Organizationレポジトリの情報を取得できません。 19 | 20 | # 例 21 | **最新リリースのダウンロード数を取得** 22 | $ ghrdc nao1215/serial 23 | [Name(Version)] :Version1.0.2: Release files with installer scripts. 24 | [Release Date] :2020-11-23 05:28:11 +0000 UTC 25 | [Binary Download Count] :177 26 | [Source Code Download Count]:0 27 | 28 | # オプション 29 | **-a**, **--all** 30 | : リリース毎のダウンロード数を表示します。 31 | 32 | **-t**, **--total** 33 | : 全リリースのダウンロード数(合計値)を表示します。 34 | 35 | **-h**, **--help** 36 | : ヘルプメッセージを表示します。 37 | 38 | **-v**, **--version** 39 | : ghrdcコマンドのバージョンを表示します。 40 | 41 | # 終了ステータス 42 | **0** 43 | : 成功 44 | 45 | **1** 46 | : ghrdcコマンドの引数指定でエラー、もしくはGitHub APIの実行時エラー 47 | 48 | # バグ 49 | GitHub Issuesを参照してください。URL:https://github.com/nao1215/mimixbox/issues 50 | 51 | # ライセンス 52 | MimixBoxプロジェクトは、MIT License条文およびApache License 2.0条文の下でライセンスされています。 -------------------------------------------------------------------------------- /docs/man/mimixbox/en/mimixbox.1.md: -------------------------------------------------------------------------------- 1 | % MIMIXBOX(1) 2 | % Naohiro CHIKAMATSU 3 | % November 2021 4 | 5 | # 名前 6 | 7 | MimixBox – mimic BusyBox which has many Unix commands (applet) in the single binary. 8 | 9 | # SYNOPSIS 10 | 11 | **mimixbox** [applet [arguments]...] [OPTIONS] 12 | 13 | # DESCRIPTION 14 | **mimixbox** has many Unix commands in the single binary like BusyBox. However, 15 | mimixbox aim for the different uses from BusyBox. Specifically, it is supposed 16 | to be used in the desktop environment, not the embedded environment. Also, the 17 | mimixbox project maintainer plan to have a wide range of built-in commands 18 | (applets) from basic command provided by Coreutils and others to experimental 19 | commands. 20 | 21 | # Command(applet)list 22 | base64 basename cat chroot echo fakemovie false ghrdc ischroot mbsh mkdir 23 | mkfifo mv path rm rmdir serial sh sleep tac touch true which 24 | 25 | # OPTIONS 26 | **-i**, **--install** 27 | : Create symbolic links for commands that don't exist on the system. 28 | 29 | **-f**, **--full-install** 30 | : Create symbolic links regardless of system state. 31 | 32 | **-h**, **--help** 33 | : Show this help message. 34 | 35 | **-l**, **--list** 36 | : Show command name provided by mimixbox. 37 | 38 | **-r**, **--remove** 39 | : Remove symbolic links for commands provided by mimixbox. 40 | 41 | **-v**, **--version** 42 | : Show mimixbox command version. 43 | 44 | # EXIT VALUES 45 | **0** 46 | : Success 47 | 48 | **1** 49 | : If you specify a non-existent applet name, or if the option is invalid, 50 | or if an error occurs in applet 51 | 52 | **2** 53 | : Errors that occur with some applets (eg ischroot, etc.) 54 | 55 | # BUGS 56 | See GitHub Issues: https://github.com/nao1215/mimixbox/issues 57 | 58 | # LICENSE 59 | The MimixBox project is licensed under the terms of the MIT license and Apache License 2.0. -------------------------------------------------------------------------------- /docs/man/mimixbox/ja/mimixbox.1.md: -------------------------------------------------------------------------------- 1 | % MIMIXBOX(1) 2 | % Naohiro CHIKAMATSU 3 | % 2021年11月 4 | 5 | # 名前 6 | 7 | MimixBox – BusyBoxの模造品。シングルバイナリ内に多数のUnixコマンド(applet)を持つ。 8 | 9 | # 書式 10 | 11 | **mimixbox** [applet [arguments]...] [OPTIONS] 12 | 13 | # 説明 14 | **mimixbox**は、BusyBoxのようにシングルバイナリ内に多数のUnixコマンドを持ちます。 15 | しかし、BusyBoxとは別の立ち位置を目指します。具体的には、組み込み環境ではなく、 16 | デスクトップ環境で使う事を想定しています。また、ビルトインするコマンド(applet)は、 17 | Coreutils等が提供する基本的な内容から実験的なコマンドまで、幅広く取り揃える予定です。 18 | 19 | # コマンド(applet)一覧 20 | **一般的なUnixコマンド(applet)** 21 | base64 basename cat chroot echo fakemovie false ghrdc ischroot mbsh mkdir 22 | mkfifo mv path rm rmdir serial sh sleep tac touch true which 23 | 24 | # オプション 25 | **-i**, **--install** 26 | : システム上に同名コマンドが存在しない場合、appletのシンボリックリンクを作成します。 27 | 28 | **-f**, **--full-install** 29 | : システム状態に関わらず、appletのシンボリックリンクを作成します。 30 | 31 | **-h**, **--help** 32 | : ヘルプメッセージを表示します。 33 | 34 | **-l**, **--list** 35 | : MimixBoxが提供するコマンド(applet)を表示します。 36 | 37 | **-r**, **--remove** 38 | : MimixBoxが提供するコマンド(applet)のシンボリックリンクを削除します。 39 | 40 | **-v**, **--version** 41 | : mimixboxコマンドのバージョンを表示します。 42 | 43 | # 終了ステータス 44 | **0** 45 | : 成功 46 | 47 | **1** 48 | : 存在しないapplet名を指定した場合、オプション不正の場合、appletでエラーが発生した場合 49 | 50 | **2** 51 | : 一部のappletで発生するエラー(例:ischrootなど) 52 | 53 | # バグ 54 | GitHub Issuesを参照してください。URL:https://github.com/nao1215/mimixbox/issues 55 | 56 | # ライセンス 57 | MimixBoxプロジェクトは、MIT License条文およびApache License 2.0条文の下でライセンスされています。 -------------------------------------------------------------------------------- /docs/man/path/en/path.1.md: -------------------------------------------------------------------------------- 1 | % PATH(1) 2 | % Naohiro CHIKAMATSU 3 | % September 2021 4 | 5 | # NAME 6 | 7 | path – command for manipulating filename path. 8 | 9 | # SYNOPSIS 10 | 11 | **path** [OPTIONS] DIRECTORY_PATH 12 | 13 | # DESCRIPTION 14 | **path** extracts the directory name, file name, and extension 15 | from the path. It also create canonical path and absolute path. 16 | 17 | # EXAMPLES 18 | **Get absolute path** 19 | $ path -a path 20 | /home/nao/.go/src/otter/path 21 | 22 | **Get basename** 23 | $ path -b /etc/systemd/pstore.conf 24 | pstore.conf 25 | 26 | **Get canonical path** 27 | $ path -c cmd/../scripts/installer.sh 28 | scripts/installer.sh 29 | 30 | **Get dirctory name** 31 | $ path -d /etc/ssh/ssh_config 32 | /etc/ssh 33 | 34 | **Get file extension** 35 | $ path -e go.mod 36 | .mod 37 | 38 | # OPTIONS 39 | **-a**, **--absolute** 40 | : Print absolute path. 41 | 42 | **-b**, **--basename** 43 | : Print basename (filename). 44 | 45 | **-c**, **--canonical** 46 | : Print canonical path (default). 47 | 48 | **-d**, **--dirname** 49 | : Print path without filename. 50 | 51 | **-e**, **--extension** 52 | : Print file extention. 53 | 54 | **-h**, **--help** 55 | : Show help message. 56 | 57 | **-v**, **--version** 58 | : Show path command version. 59 | 60 | # EXIT VALUES 61 | **0** 62 | : Success 63 | 64 | **1** 65 | : There is an error in the argument of the path command. 66 | 67 | # BUGS 68 | See GitHub Issues: https://github.com/nao1215/mimixbox/issues 69 | 70 | # LICENSE 71 | The MimixBox project is licensed under the terms of the MIT license and Apache License 2.0. -------------------------------------------------------------------------------- /docs/man/path/ja/path.1.md: -------------------------------------------------------------------------------- 1 | % PATH(1) 2 | % Naohiro CHIKAMATSU 3 | % 2021年9月 4 | 5 | # 名前 6 | 7 | path – ファイル名パスを操作するためのコマンド 8 | 9 | # 書式 10 | 11 | **path** [OPTIONS] DIRECTORY_PATH 12 | 13 | # 説明 14 | **path**は、パスからディレクトリ名、ファイル名、拡張子を抽出します。 15 | また、正規化されたパスや全体化されたパスを生成します。 16 | 17 | # 例 18 | **絶対パスの取得** 19 | $ path -a path 20 | /home/nao/.go/src/otter/path 21 | 22 | **ベースネームの取得** 23 | $ path -b /etc/systemd/pstore.conf 24 | pstore.conf 25 | 26 | **正規化されたパスの取得** 27 | $ path -c cmd/../scripts/installer.sh 28 | scripts/installer.sh 29 | 30 | **ディレクトリパスの取得** 31 | $ path -d /etc/ssh/ssh_config 32 | /etc/ssh 33 | 34 | **ファイルの拡張子の取得** 35 | $ path -e go.mod 36 | .mod 37 | 38 | # オプション 39 | **-a**, **--absolute** 40 | : 絶対パスを表示します。 41 | 42 | **-b**, **--basename** 43 | : ベースネーム(ファイル名)を表示します。 44 | 45 | **-c**, **--canonical** 46 | : 正規化されたパスを表示します(デフォルト)。 47 | 48 | **-d**, **--dirname** 49 | : ファイル名を除いたパスを表示します。 50 | 51 | **-e**, **--extension** 52 | : 拡張子を表示します。 53 | 54 | **-h**, **--help** 55 | : ヘルプメッセージを表示します。 56 | 57 | **-v**, **--version** 58 | : pathコマンドのバージョンを表示します。 59 | 60 | # 終了ステータス 61 | **0** 62 | : 成功 63 | 64 | **1** 65 | : pathコマンドの引数指定でエラー 66 | 67 | # バグ 68 | GitHub Issuesを参照してください。URL:https://github.com/nao1215/mimixbox/issues 69 | 70 | # ライセンス 71 | MimixBoxプロジェクトは、MIT License条文およびApache License 2.0条文の下でライセンスされています。 -------------------------------------------------------------------------------- /docs/man/sddf/en/sddf.1.md: -------------------------------------------------------------------------------- 1 | % SDDF(1) 2 | % Naohiro CHIKAMATSU 3 | % December 2021 4 | 5 | # NAME 6 | 7 | serial – Search & Delete Duplicatetd File 8 | 9 | # SYNOPSIS 10 | 11 | **sddf** [OPTIONS] PATH 12 | 13 | # DESCRIPTION 14 | **sddf** looks for duplicate files under the specified directory and 15 | creates a list of them (default: duplicated-file.sddf). 16 | If the list is executed with sddf arguments, sddf delete the file based 17 | on the contents of the list. 18 | 19 | # EXAMPLES 20 | **Search for duplicate files under the current directory** 21 | 22 | $ sddf . 23 | 24 | **Remove duplicate files** 25 | 26 | $ sddf duplicated-file.sddf 27 | 28 | # OPTIONS 29 | **-o, **--output** 30 | : Specify the file name of the duplicate file list. 31 | 32 | **-h**, **--help** 33 | : Show help message. 34 | 35 | **-v**, **--version** 36 | : Show sddf command version. 37 | 38 | # EXIT VALUES 39 | **0** 40 | : Success 41 | 42 | **1** 43 | : Error when specifying the argument of the sddf command, or error during file operation 44 | 45 | # BUGS 46 | See GitHub Issues: https://github.com/nao1215/mimixbox/issues 47 | 48 | # LICENSE 49 | The MimixBox project is licensed under the terms of the MIT license and Apache License 2.0. -------------------------------------------------------------------------------- /docs/man/sddf/ja/sddf.1.md: -------------------------------------------------------------------------------- 1 | % SDDF(1) 2 | % Naohiro CHIKAMATSU 3 | % 2021年12月 4 | 5 | # 名前 6 | 7 | serial – 重複するファイルを探し、削除する 8 | 9 | # 書式 10 | 11 | **sddf** [OPTIONS] PATH 12 | 13 | # 説明 14 | **sddf**は、任意のディレクトリ以下にある重複ファイルを探し出し、 15 | そのリスト(デフォルト:duplicated-file.sddf)を作成します。 16 | リストを指定して実行した場合は、リスト内容に基づいてファイルを削除します。 17 | 18 | # 例 19 | **カレントディレクトリ以下から重複ファイルを探索** 20 | 21 | $ sddf . 22 | 23 | **重複ファイルを削除** 24 | 25 | $ sddf duplicated-file.sddf 26 | 27 | # オプション 28 | **-o, **--output** 29 | : 重複ファイルリストのファイル名を指定します。 30 | 31 | **-h**, **--help** 32 | : ヘルプメッセージを表示します。 33 | 34 | **-v**, **--version** 35 | : sddfコマンドのバージョンを表示します。 36 | 37 | # 終了ステータス 38 | **0** 39 | : 成功 40 | 41 | **1** 42 | : sddfコマンドの引数指定でエラー、もしくはファイル操作中のエラー 43 | 44 | # バグ 45 | GitHub Issuesを参照してください。URL:https://github.com/nao1215/mimixbox/issues 46 | 47 | # ライセンス 48 | MimixBoxプロジェクトは、MIT License条文およびApache License 2.0条文の下でライセンスされています。 -------------------------------------------------------------------------------- /docs/man/serial/en/serial.1.md: -------------------------------------------------------------------------------- 1 | % SERIAL(1) 2 | % Naohiro CHIKAMATSU 3 | % September 2021 4 | 5 | # NAME 6 | 7 | serial – rename the file name to the name with a serial number. 8 | 9 | # SYNOPSIS 10 | 11 | **serial** [OPTIONS] DIRECTORY_PATH 12 | 13 | # DESCRIPTION 14 | **serial** is a CLI command that renames files under any directory to 15 | the format user specified file name with serial number. 16 | serial can specify the destination directory of the renamed file. Also, 17 | if you want to keep the original file, you can copy the file instead of 18 | renaming the file. 19 | 20 | # EXAMPLES 21 | **Rename the file name to the name with a serial number at current directory.** 22 | 23 | $ ls 24 | a.txt b.txt c.txt 25 | $ serial --name demo . 26 | Rename a.txt to 1_demo.txt 27 | Rename b.txt to 2_demo.txt 28 | Rename c.txt to 3_demo.txt 29 | 30 | **Copy & Rename the file at specified directory.** 31 | 32 | $ serial -s -k -n ../../dir/demo . 33 | Copy a.txt to ../../dir/demo_0.txt 34 | Copy b.txt to ../../dir/demo_1.txt 35 | Copy c.txt to ../../dir/demo_2.txt 36 | 37 | # OPTIONS 38 | **-d**, **--dry-run** 39 | : Output the file renaming result to standard output (do not update the file). 40 | 41 | **-f**, **--force** 42 | : Forcibly overwrite and save even if a file with the same name exists. 43 | 44 | **-h**, **--help** 45 | : Show help message. 46 | 47 | **-k**, **--keep** 48 | : Keep the file before renaming (not rename, do copy). 49 | 50 | **-n new_filename**, **--name=new_filename** 51 | : Base file name with/without directory path (assign a serial number to this file name). 52 | 53 | **-p**, **--prefix** 54 | : Add a serial number to the beginning of the file name(default). 55 | 56 | **-s**, **--suffix** 57 | : Add a serial number to the end of the file name. 58 | 59 | **-v**, **--version** 60 | : Show serial command version. 61 | 62 | # EXIT VALUES 63 | **0** 64 | : Success 65 | 66 | **1** 67 | : There is an error in the argument of the serial command. 68 | 69 | # BUGS 70 | See GitHub Issues: https://github.com/nao1215/mimixbox/issues 71 | 72 | # LICENSE 73 | The MimixBox project is licensed under the terms of the MIT license and Apache License 2.0. -------------------------------------------------------------------------------- /docs/man/serial/ja/serial.1.md: -------------------------------------------------------------------------------- 1 | % SERIAL(1) 2 | % Naohiro CHIKAMATSU 3 | % 2021年9月 4 | 5 | # 名前 6 | 7 | serial – シリアル番号付きのファイル名にリネームする。 8 | 9 | # 書式 10 | 11 | **serial** [OPTIONS] DIRECTORY_PATH 12 | 13 | # 説明 14 | **serial**は、任意のディレクトリ以下にあるファイルの名前を 15 | ユーザ指定の名前に連番を付与してリネームするCLIコマンドです。 16 | serialは、リネームしたファイルの格納先ディレクトリを指定でき 17 | ます。また、オリジナルファイルを保持したい場合、リネームでは 18 | なくファイルコピーができます。 19 | 20 | # 例 21 | **カレントディレクトリにあるファイルの名前をシリアル番号付きのファイル名にリネームする。** 22 | 23 | $ ls 24 | a.txt b.txt c.txt 25 | $ serial --name demo . 26 | Rename a.txt to 1_demo.txt 27 | Rename b.txt to 2_demo.txt 28 | Rename c.txt to 3_demo.txt 29 | 30 | **指定のディレクトリへファイルをコピー&リネーム** 31 | 32 | $ serial -s -k -n ../../dir/demo . 33 | Copy a.txt to ../../dir/demo_0.txt 34 | Copy b.txt to ../../dir/demo_1.txt 35 | Copy c.txt to ../../dir/demo_2.txt 36 | 37 | # オプション 38 | **-d**, **--dry-run** 39 | : 標準出力にファイル名のリネーム結果を表示します(ファイル更新はしません)。 40 | 41 | **-f**, **--force** 42 | : 同名のファイルが存在する場合であっても、強制的に上書き保存します。 43 | 44 | **-h**, **--help** 45 | : ヘルプメッセージを表示します。 46 | 47 | **-k**, **--keep** 48 | : リネーム前のファイルを保持します(リネームはせず、コピーします)。 49 | 50 | **-n new_filename**, **--name=new_filename** 51 | : 格納先のディレクトリ名を含んだ/含まないベースファイル名(このファイル名に連番を付与します)。 52 | 53 | **-p**, **--prefix** 54 | : 連番をファイル名の先頭に付与します(デフォルト)。 55 | 56 | **-s**, **--suffix** 57 | : 連番をファイル名の末尾に付与します。 58 | 59 | **-v**, **--version** 60 | : serialコマンドのバージョンを表示します。 61 | 62 | # 終了ステータス 63 | **0** 64 | : 成功 65 | 66 | **1** 67 | : serialコマンドの引数指定でエラー 68 | 69 | # バグ 70 | GitHub Issuesを参照してください。URL:https://github.com/nao1215/mimixbox/issues 71 | 72 | # ライセンス 73 | MimixBoxプロジェクトは、MIT License条文およびApache License 2.0条文の下でライセンスされています。 -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/nao1215/mimixbox 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/cheggaaa/pb/v3 v3.1.7 7 | github.com/fogleman/gg v1.3.0 8 | github.com/jessevdk/go-flags v1.6.1 9 | github.com/nsf/termbox-go v1.1.1 10 | github.com/stretchr/testify v1.10.0 11 | golang.org/x/term v0.29.0 12 | ) 13 | 14 | require ( 15 | github.com/VividCortex/ewma v1.2.0 // indirect 16 | github.com/davecgh/go-spew v1.1.1 // indirect 17 | github.com/fatih/color v1.18.0 // indirect 18 | github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect 19 | github.com/kr/pretty v0.1.0 // indirect 20 | github.com/mattn/go-colorable v0.1.14 // indirect 21 | github.com/mattn/go-isatty v0.0.20 // indirect 22 | github.com/mattn/go-runewidth v0.0.16 // indirect 23 | github.com/pmezard/go-difflib v1.0.0 // indirect 24 | github.com/rivo/uniseg v0.4.7 // indirect 25 | golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect 26 | golang.org/x/sys v0.30.0 // indirect 27 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect 28 | gopkg.in/yaml.v3 v3.0.1 // indirect 29 | ) 30 | -------------------------------------------------------------------------------- /internal/applets/console-tools/clear/clear.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/console-tools/clear/clear.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package clear 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | 23 | mb "github.com/nao1215/mimixbox/internal/lib" 24 | 25 | "github.com/jessevdk/go-flags" 26 | ) 27 | 28 | const cmdName string = "clear" 29 | 30 | const version = "1.0.0" 31 | 32 | var osExit = os.Exit 33 | 34 | type options struct { 35 | Version bool `short:"v" long:"version" description:"Show clear command version"` 36 | } 37 | 38 | func Run() (int, error) { 39 | var opts options 40 | var err error 41 | 42 | if _, err = parseArgs(&opts); err != nil { 43 | return mb.ExitFailure, nil 44 | } 45 | return clear() 46 | } 47 | 48 | func clear() (int, error) { 49 | fmt.Fprintf(os.Stdout, "\033[H\033[J") 50 | return mb.ExitSuccess, nil 51 | } 52 | 53 | func parseArgs(opts *options) ([]string, error) { 54 | p := initParser(opts) 55 | 56 | args, err := p.Parse() 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | if opts.Version { 62 | mb.ShowVersion(cmdName, version) 63 | osExit(mb.ExitSuccess) 64 | } 65 | 66 | return args, nil 67 | } 68 | 69 | func initParser(opts *options) *flags.Parser { 70 | parser := flags.NewParser(opts, flags.Default) 71 | parser.Name = cmdName 72 | parser.Usage = "[OPTIONS]" 73 | 74 | return parser 75 | } 76 | -------------------------------------------------------------------------------- /internal/applets/console-tools/reset/reset.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/console-tools/reset/reset.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package reset 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "syscall" 23 | 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | "golang.org/x/term" 26 | 27 | "github.com/jessevdk/go-flags" 28 | ) 29 | 30 | const cmdName string = "reset" 31 | 32 | const version = "1.0.0" 33 | 34 | var osExit = os.Exit 35 | 36 | type options struct { 37 | Version bool `short:"v" long:"version" description:"Show reset command version"` 38 | } 39 | 40 | func Run() (int, error) { 41 | var opts options 42 | var err error 43 | 44 | if _, err = parseArgs(&opts); err != nil { 45 | return mb.ExitFailure, nil 46 | } 47 | return reset() 48 | } 49 | 50 | func reset() (int, error) { 51 | // See 'man 4 console_codes' for details: 52 | // "ESC c" -- Reset 53 | // "ESC ( B" -- Select G0 Character Set (B = US) 54 | // "ESC [ m" -- Reset all display attributes 55 | // "ESC [ J" -- Erase to the end of screen 56 | // "ESC [ ? 25 h" -- Make cursor visible 57 | if term.IsTerminal(syscall.Stdin) { 58 | fmt.Fprintf(os.Stdout, "\033c\033(B\033[m\033[J\033[?25h") 59 | } 60 | return mb.ExitSuccess, nil 61 | } 62 | 63 | func parseArgs(opts *options) ([]string, error) { 64 | p := initParser(opts) 65 | 66 | args, err := p.Parse() 67 | if err != nil { 68 | return nil, err 69 | } 70 | 71 | if opts.Version { 72 | mb.ShowVersion(cmdName, version) 73 | osExit(mb.ExitSuccess) 74 | } 75 | 76 | return args, nil 77 | } 78 | 79 | func initParser(opts *options) *flags.Parser { 80 | parser := flags.NewParser(opts, flags.Default) 81 | parser.Name = cmdName 82 | parser.Usage = "[OPTIONS]" 83 | 84 | return parser 85 | } 86 | -------------------------------------------------------------------------------- /internal/applets/debianutils/add-shell/add-shell.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/debianutils/add-shell/add-shell.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package addShell 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | 23 | "github.com/jessevdk/go-flags" 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | ) 26 | 27 | const cmdName string = "add-shell" 28 | 29 | const version = "1.0.0" 30 | 31 | var osExit = os.Exit 32 | 33 | type options struct { 34 | Version bool `short:"v" long:"version" description:"Show add-shell command version"` 35 | } 36 | 37 | func Run() (int, error) { 38 | var opts options 39 | var args []string 40 | var err error 41 | 42 | if args, err = parseArgs(&opts); err != nil { 43 | return mb.ExitFailure, nil 44 | } 45 | 46 | return addShell(args) 47 | } 48 | 49 | func addShell(args []string) (int, error) { 50 | // The original add-shell command has poor error checking. 51 | // add-shell can also write the names of non-existent shells in /etc/shells. 52 | err := mb.Copy(mb.ShellsFilePath, mb.TmpShellsFile()) 53 | if err != nil { 54 | return mb.ExitFailure, err 55 | } 56 | f, err := os.OpenFile(mb.TmpShellsFile(), os.O_APPEND|os.O_WRONLY, 0644) 57 | if err != nil { 58 | return mb.ExitFailure, err 59 | } 60 | defer f.Close() 61 | 62 | for _, v := range args { 63 | fmt.Fprintln(f, v) 64 | } 65 | 66 | err = mb.Copy(mb.TmpShellsFile(), mb.ShellsFilePath) 67 | if err != nil { 68 | mb.RemoveFile(mb.TmpShellsFile(), false) // Original add-shell does not remove tmp file. 69 | return mb.ExitFailure, err 70 | } 71 | 72 | mb.RemoveFile(mb.TmpShellsFile(), false) 73 | return mb.ExitSuccess, nil 74 | } 75 | 76 | func parseArgs(opts *options) ([]string, error) { 77 | p := initParser(opts) 78 | 79 | args, err := p.Parse() 80 | if err != nil { 81 | return nil, err 82 | } 83 | 84 | if opts.Version { 85 | mb.ShowVersion(cmdName, version) 86 | osExit(mb.ExitSuccess) 87 | } 88 | 89 | if !isValidArgNr(args) { 90 | fmt.Fprintln(os.Stderr, cmdName+": shellname [shellname ...]") 91 | osExit(mb.ExitFailure) 92 | } 93 | return args, nil 94 | } 95 | 96 | func initParser(opts *options) *flags.Parser { 97 | parser := flags.NewParser(opts, flags.Default) 98 | parser.Name = cmdName 99 | parser.Usage = "[OPTIONS] SHELL_NAME" 100 | 101 | return parser 102 | } 103 | 104 | func isValidArgNr(args []string) bool { 105 | return len(args) >= 1 106 | } 107 | -------------------------------------------------------------------------------- /internal/applets/debianutils/remove-shell/remove-shell.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/debianutils/remove-shell/remove-shell.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package removeShell 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | 23 | "github.com/jessevdk/go-flags" 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | ) 26 | 27 | const cmdName string = "remove-shell" 28 | 29 | const version = "1.0.0" 30 | 31 | var osExit = os.Exit 32 | 33 | type options struct { 34 | Version bool `short:"v" long:"version" description:"Show remove-shell command version"` 35 | } 36 | 37 | func Run() (int, error) { 38 | var opts options 39 | var args []string 40 | var err error 41 | 42 | if args, err = parseArgs(&opts); err != nil { 43 | return mb.ExitFailure, nil 44 | } 45 | return removeShell(args) 46 | } 47 | 48 | func removeShell(args []string) (int, error) { 49 | f, err := os.OpenFile(mb.TmpShellsFile(), os.O_CREATE|os.O_WRONLY, 0644) 50 | if err != nil { 51 | return mb.ExitFailure, err 52 | } 53 | defer f.Close() 54 | 55 | lines, err := mb.ReadFileToStrList(mb.ShellsFilePath) 56 | if err != nil { 57 | return mb.ExitFailure, err 58 | } 59 | 60 | lines = mb.ChopAll(lines) 61 | for _, shell := range args { 62 | lines = mb.Remove(lines, shell) 63 | } 64 | for _, v := range lines { 65 | fmt.Fprintln(f, v) 66 | } 67 | 68 | err = mb.Copy(mb.TmpShellsFile(), mb.ShellsFilePath) 69 | if err != nil { 70 | mb.RemoveFile(mb.TmpShellsFile(), false) 71 | return mb.ExitFailure, err 72 | } 73 | 74 | mb.RemoveFile(mb.TmpShellsFile(), false) 75 | return mb.ExitSuccess, nil 76 | } 77 | 78 | func parseArgs(opts *options) ([]string, error) { 79 | p := initParser(opts) 80 | 81 | args, err := p.Parse() 82 | if err != nil { 83 | return nil, err 84 | } 85 | 86 | if opts.Version { 87 | mb.ShowVersion(cmdName, version) 88 | osExit(mb.ExitSuccess) 89 | } 90 | 91 | if !isValidArgNr(args) { 92 | fmt.Fprintln(os.Stderr, cmdName+": shellname [shellname ...]") 93 | osExit(mb.ExitFailure) 94 | } 95 | return args, nil 96 | } 97 | 98 | func initParser(opts *options) *flags.Parser { 99 | parser := flags.NewParser(opts, flags.Default) 100 | parser.Name = cmdName 101 | parser.Usage = "[OPTIONS] SHELL_NAME" 102 | 103 | return parser 104 | } 105 | 106 | func isValidArgNr(args []string) bool { 107 | return len(args) >= 1 108 | } 109 | -------------------------------------------------------------------------------- /internal/applets/debianutils/which/which.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/debianutils/which/which.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package which 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "os/exec" 23 | 24 | "github.com/jessevdk/go-flags" 25 | mb "github.com/nao1215/mimixbox/internal/lib" 26 | ) 27 | 28 | const cmdName string = "which" 29 | 30 | const version = "1.0.2" 31 | 32 | var osExit = os.Exit 33 | 34 | type options struct { 35 | Version bool `short:"v" long:"version" description:"Show which command version"` 36 | } 37 | 38 | func Run() (int, error) { 39 | var opts options 40 | var args []string 41 | var err error 42 | 43 | if args, err = parseArgs(&opts); err != nil { 44 | return mb.ExitFailure, nil 45 | } 46 | 47 | status := mb.ExitSuccess 48 | for _, path := range args { 49 | p, err := exec.LookPath(path) 50 | if err != nil { 51 | e, ok := err.(*exec.Error) 52 | if ok && e.Err == exec.ErrNotFound { 53 | status = mb.ExitFailure 54 | continue // Don't print error like coreutils. 55 | } 56 | fmt.Fprintln(os.Stderr, e) 57 | status = mb.ExitFailure 58 | } 59 | fmt.Fprintln(os.Stdout, p) 60 | } 61 | return status, nil 62 | } 63 | 64 | func parseArgs(opts *options) ([]string, error) { 65 | p := initParser(opts) 66 | 67 | args, err := p.Parse() 68 | if err != nil { 69 | return nil, err 70 | } 71 | 72 | if opts.Version { 73 | mb.ShowVersion(cmdName, version) 74 | osExit(mb.ExitSuccess) 75 | } 76 | 77 | if !isValidArgNr(args) { 78 | osExit(mb.ExitFailure) // Do not display help messages because it behaves the same as Coreutils 79 | } 80 | return args, nil 81 | } 82 | 83 | func initParser(opts *options) *flags.Parser { 84 | parser := flags.NewParser(opts, flags.Default) 85 | parser.Name = cmdName 86 | parser.Usage = "[OPTIONS] COMMAND_NAME" 87 | 88 | return parser 89 | } 90 | 91 | func isValidArgNr(args []string) bool { 92 | return len(args) >= 1 93 | } 94 | -------------------------------------------------------------------------------- /internal/applets/editors/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nao1215/mimixbox/063fffce9c5b7165e5d8315711dd3fc74f22158e/internal/applets/editors/.gitkeep -------------------------------------------------------------------------------- /internal/applets/fileutils/mkdir/mkdir.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/fileutils/mkdir/mkdir.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mkdir 18 | 19 | import ( 20 | "errors" 21 | "fmt" 22 | "os" 23 | 24 | "github.com/jessevdk/go-flags" 25 | mb "github.com/nao1215/mimixbox/internal/lib" 26 | ) 27 | 28 | const cmdName string = "mkdir" 29 | 30 | const version = "1.0.3" 31 | 32 | var osExit = os.Exit 33 | 34 | var ErrNoOperand = errors.New("no operand") 35 | 36 | type options struct { 37 | Parent bool `short:"p" long:"parents" description:"No error if existing, make parent directories as needed"` 38 | Version bool `short:"v" long:"version" description:"Show mkdir command version"` 39 | } 40 | 41 | func Run() (int, error) { 42 | var opts options 43 | var args []string 44 | var err error 45 | 46 | if args, err = parseArgs(&opts); err != nil { 47 | if err == ErrNoOperand { 48 | return mb.ExitFailure, err 49 | } 50 | return mb.ExitFailure, nil 51 | } 52 | 53 | status := mb.ExitSuccess 54 | for _, path := range args { 55 | target := os.ExpandEnv(path) 56 | if opts.Parent { 57 | err = os.MkdirAll(target, 0755) 58 | } else { 59 | err = os.Mkdir(target, 0755) 60 | } 61 | 62 | if err != nil { 63 | status = mb.ExitFailure 64 | fmt.Fprintln(os.Stderr, err.Error()) 65 | } 66 | } 67 | return status, nil 68 | } 69 | 70 | func parseArgs(opts *options) ([]string, error) { 71 | p := initParser(opts) 72 | 73 | args, err := p.Parse() 74 | if err != nil { 75 | return nil, err 76 | } 77 | 78 | if opts.Version { 79 | mb.ShowVersion(cmdName, version) 80 | osExit(mb.ExitSuccess) 81 | } 82 | 83 | if !isValidArgNr(args) { 84 | return nil, ErrNoOperand 85 | } 86 | return args, nil 87 | } 88 | 89 | func initParser(opts *options) *flags.Parser { 90 | parser := flags.NewParser(opts, flags.Default) 91 | parser.Name = cmdName 92 | parser.Usage = "[OPTIONS] PATH" 93 | 94 | return parser 95 | } 96 | 97 | func isValidArgNr(args []string) bool { 98 | return len(args) >= 1 99 | } 100 | -------------------------------------------------------------------------------- /internal/applets/fileutils/mkfifo/mkfifo.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/fileutils/mkfifo/mkfifo.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mkfifo 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "syscall" 23 | 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | 26 | "github.com/jessevdk/go-flags" 27 | ) 28 | 29 | const cmdName string = "mkfifo" 30 | 31 | const version = "1.0.2" 32 | 33 | var osExit = os.Exit 34 | 35 | type options struct { 36 | Version bool `short:"v" long:"version" description:"Show mkfifo command version"` 37 | } 38 | 39 | func Run() (int, error) { 40 | var opts options 41 | var args []string 42 | var err error 43 | status := mb.ExitSuccess 44 | 45 | if args, err = parseArgs(&opts); err != nil { 46 | return mb.ExitFailure, nil 47 | } 48 | 49 | for _, path := range args { 50 | p := os.ExpandEnv(path) 51 | if mb.Exists(p) { 52 | status = mb.ExitFailure 53 | fmt.Fprintln(os.Stderr, cmdName+": can't make "+p+": already exist") 54 | continue 55 | } 56 | if err := syscall.Mkfifo(p, 0644); err != nil { 57 | status = mb.ExitFailure 58 | fmt.Fprintln(os.Stderr, cmdName+": "+p+": "+err.Error()) 59 | continue 60 | } 61 | } 62 | return status, nil 63 | } 64 | 65 | func parseArgs(opts *options) ([]string, error) { 66 | p := initParser(opts) 67 | 68 | args, err := p.Parse() 69 | if err != nil { 70 | return nil, err 71 | } 72 | 73 | if opts.Version { 74 | mb.ShowVersion(cmdName, version) 75 | osExit(mb.ExitSuccess) 76 | } 77 | 78 | if !isValidArgNr(args) { 79 | showHelp(p) 80 | osExit(mb.ExitFailure) 81 | } 82 | return args, nil 83 | } 84 | 85 | func initParser(opts *options) *flags.Parser { 86 | parser := flags.NewParser(opts, flags.Default) 87 | parser.Name = cmdName 88 | parser.Usage = "[OPTIONS] FILE_PATH" 89 | 90 | return parser 91 | } 92 | 93 | func isValidArgNr(args []string) bool { 94 | return len(args) >= 1 95 | } 96 | 97 | func showHelp(p *flags.Parser) { 98 | p.WriteHelp(os.Stdout) 99 | } 100 | -------------------------------------------------------------------------------- /internal/applets/fileutils/touch/touch.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/fileutils/touch/touch.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package touch 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "time" 23 | 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | 26 | "github.com/jessevdk/go-flags" 27 | ) 28 | 29 | const cmdName string = "touch" 30 | 31 | const version = "1.0.2" 32 | 33 | var osExit = os.Exit 34 | 35 | type options struct { 36 | NoCreate bool `short:"c" long:"no-create" description:"Not create file"` 37 | Version bool `short:"v" long:"version" description:"Show touch command version"` 38 | } 39 | 40 | func Run() (int, error) { 41 | var opts options 42 | var args []string 43 | var err error 44 | 45 | if args, err = parseArgs(&opts); err != nil { 46 | return mb.ExitFailure, nil 47 | } 48 | 49 | status := mb.ExitSuccess 50 | for _, file := range args { 51 | if err = touch(file, opts); err != nil { 52 | fmt.Fprintln(os.Stderr, "touch: "+err.Error()) 53 | status = mb.ExitFailure 54 | continue 55 | } 56 | } 57 | return status, nil 58 | } 59 | 60 | // atime = access time 61 | // ctime = change time 62 | // mtime = modify time 63 | func touch(file string, opts options) error { 64 | path := os.ExpandEnv(file) 65 | if !mb.Exists(path) && !opts.NoCreate { 66 | f, err := os.Create(path) 67 | if err != nil { 68 | return err 69 | } 70 | defer f.Close() 71 | } else { 72 | currentTime := time.Now().Local() 73 | err := os.Chtimes(path, currentTime, currentTime) 74 | if err != nil { 75 | return err 76 | } 77 | } 78 | return nil 79 | } 80 | 81 | func parseArgs(opts *options) ([]string, error) { 82 | p := initParser(opts) 83 | 84 | args, err := p.Parse() 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | if opts.Version { 90 | mb.ShowVersion(cmdName, version) 91 | osExit(mb.ExitSuccess) 92 | } 93 | 94 | if !isValidArgNr(args) { 95 | showHelp(p) 96 | osExit(mb.ExitFailure) 97 | } 98 | return args, nil 99 | } 100 | 101 | func initParser(opts *options) *flags.Parser { 102 | parser := flags.NewParser(opts, flags.Default) 103 | parser.Name = cmdName 104 | parser.Usage = "[OPTIONS] FILE_PATH" 105 | 106 | return parser 107 | } 108 | 109 | func isValidArgNr(args []string) bool { 110 | return len(args) >= 1 111 | } 112 | 113 | func showHelp(p *flags.Parser) { 114 | p.WriteHelp(os.Stdout) 115 | } 116 | -------------------------------------------------------------------------------- /internal/applets/findutils/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nao1215/mimixbox/063fffce9c5b7165e5d8315711dd3fc74f22158e/internal/applets/findutils/.gitkeep -------------------------------------------------------------------------------- /internal/applets/jokeutils/cowsay/cowsay.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/jokeutils/cowsay/cowsay.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package cowsay 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "strings" 23 | 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | ) 26 | 27 | const cmdName string = "cowsay" 28 | 29 | const version = "0.9.3" 30 | 31 | var osExit = os.Exit 32 | 33 | const cow = ` \ 34 | \ ^__^ 35 | \ (oo)\_______ 36 | (__)\ )\/\ 37 | ||----w | 38 | || ||` 39 | 40 | func Run() (int, error) { 41 | var messages string 42 | args, err := parseArgs(os.Args) 43 | if err != nil { 44 | return mb.ExitFailure, nil 45 | } 46 | 47 | if mb.HasPipeData() { 48 | messages = strings.TrimSuffix(strings.Join(args, ""), "\n") 49 | } else if len(args) == 0 { 50 | messages = userInput() 51 | } else { 52 | messages = strings.Join(args, "") 53 | } 54 | cowsay(messages) 55 | 56 | return mb.ExitSuccess, nil 57 | } 58 | 59 | func cowsay(msg string) { 60 | fmt.Fprintln(os.Stdout, "------------------------------------------------------------") 61 | fmt.Fprintf(os.Stdout, "%s\n", mb.WrapString(msg, 60)) 62 | fmt.Fprintln(os.Stdout, "------------------------------------------------------------") 63 | fmt.Fprintln(os.Stdout, cow) 64 | } 65 | 66 | func userInput() string { 67 | var inputs string 68 | for { 69 | input, next := mb.Input() 70 | if !next { 71 | break 72 | } 73 | inputs += input 74 | } 75 | return inputs 76 | } 77 | 78 | func parseArgs(args []string) ([]string, error) { 79 | 80 | if mb.HasVersionOpt(args) { 81 | mb.ShowVersion(cmdName, version) 82 | osExit(mb.ExitSuccess) 83 | } 84 | 85 | if mb.HasHelpOpt(args) { 86 | showHelp() 87 | osExit(mb.ExitSuccess) 88 | } 89 | 90 | if mb.HasPipeData() { 91 | stdin, err := mb.FromPIPE() 92 | if err != nil { 93 | return nil, err 94 | } 95 | return []string{stdin}, nil 96 | } 97 | 98 | return args[1:], nil 99 | } 100 | 101 | func showHelp() { 102 | fmt.Fprintln(os.Stdout, "Usage:") 103 | fmt.Fprintln(os.Stdout, " cowsay [OPTIONS] message") 104 | fmt.Fprintln(os.Stdout, "") 105 | fmt.Fprintln(os.Stdout, "Application Options:") 106 | fmt.Fprintln(os.Stdout, " -v, --version Show cowsay command version") 107 | fmt.Fprintln(os.Stdout, "") 108 | fmt.Fprintln(os.Stdout, "Help Options:") 109 | fmt.Fprintln(os.Stdout, " -h, --help Show this help message") 110 | } 111 | -------------------------------------------------------------------------------- /internal/applets/loginutils/chsh/chsh.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/loginutils/chsh/chsh.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package chsh 18 | 19 | import ( 20 | "os" 21 | 22 | mb "github.com/nao1215/mimixbox/internal/lib" 23 | 24 | "github.com/jessevdk/go-flags" 25 | ) 26 | 27 | // TODO: This file stopped implementation prematurely. 28 | // PAM (pluggable authentication modules) can only be used in a Linux environment 29 | // MimixBox needs to be compatible with Linux environments without PAM, and will 30 | // be compatible with Mac in the future. 31 | // First of all, in order to verify Basic authentication, we stopped the implementation halfway. 32 | // In mb library, Basic authentication using PAM is commented out. 33 | 34 | const cmdName string = "chsh" 35 | 36 | const version = "1.0.0" 37 | 38 | var osExit = os.Exit 39 | 40 | type options struct { 41 | Version bool `short:"v" long:"version" description:"Show chsh command version"` 42 | } 43 | 44 | func Run() (int, error) { 45 | var opts options 46 | var err error 47 | var args []string 48 | 49 | if args, err = parseArgs(&opts); err != nil { 50 | return mb.ExitFailure, nil 51 | } 52 | return chsh(args, opts) 53 | } 54 | 55 | func chsh(args []string, opts options) (int, error) { 56 | status := mb.ExitSuccess 57 | 58 | if len(args) == 0 { 59 | interactiveChangeShell(opts) 60 | } 61 | //isRoot := mb.IsRootUser() 62 | return status, nil 63 | } 64 | 65 | func interactiveChangeShell(opts options) (int, error) { 66 | /* 67 | user, err := user.Current() 68 | if err != nil { 69 | return mb.ExitFailure, err 70 | } 71 | if err = mb.AuthByPasswordWithPam(user.Username); err != nil { 72 | return mb.ExitFailure, err 73 | } 74 | */ 75 | return mb.ExitSuccess, nil 76 | } 77 | 78 | func parseArgs(opts *options) ([]string, error) { 79 | p := initParser(opts) 80 | 81 | args, err := p.Parse() 82 | if err != nil { 83 | return nil, err 84 | } 85 | 86 | if opts.Version { 87 | mb.ShowVersion(cmdName, version) 88 | osExit(mb.ExitSuccess) 89 | } 90 | return args, nil 91 | } 92 | 93 | func initParser(opts *options) *flags.Parser { 94 | parser := flags.NewParser(opts, flags.Default) 95 | parser.Name = cmdName 96 | parser.Usage = "[OPTIONS] [LOGIN_USERNAME]" 97 | 98 | return parser 99 | } 100 | -------------------------------------------------------------------------------- /internal/applets/shellutils/basename/basename.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/basename/basename.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package basename 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "path/filepath" 23 | "strings" 24 | 25 | "github.com/jessevdk/go-flags" 26 | mb "github.com/nao1215/mimixbox/internal/lib" 27 | ) 28 | 29 | const cmdName string = "basename" 30 | 31 | const version = "1.0.2" 32 | 33 | var osExit = os.Exit 34 | 35 | type options struct { 36 | Multiple bool `short:"a" long:"multiple" description:"Process for multiple PATHs"` 37 | Suffix string `short:"s" long:"suffix" default:"" description:"Delete suffix"` 38 | Zero bool `short:"z" long:"zero" description:"Basename do not include line feed"` 39 | Version bool `short:"v" long:"version" description:"Show basename command version"` 40 | } 41 | 42 | func Run() (int, error) { 43 | var opts options 44 | var args []string 45 | var err error 46 | 47 | if args, err = parseArgs(&opts); err != nil { 48 | return mb.ExitFailure, nil 49 | } 50 | 51 | for _, path := range args { 52 | basename := filepath.Base(path) 53 | if opts.Suffix != "" && strings.HasSuffix(basename, opts.Suffix) { 54 | basename = strings.TrimSuffix(basename, opts.Suffix) 55 | } 56 | 57 | // The result when the user specifies ""(empty string) is different from Coreutils. 58 | // So change the result from "." to "" to match the result with Coreutils. 59 | if path == "" && basename == "." { 60 | basename = "" 61 | } 62 | 63 | if opts.Zero { 64 | fmt.Fprintf(os.Stdout, "%s", basename) 65 | } else { 66 | fmt.Fprintln(os.Stdout, basename) 67 | } 68 | 69 | if !opts.Multiple { 70 | break 71 | } 72 | } 73 | return mb.ExitSuccess, nil 74 | } 75 | 76 | func parseArgs(opts *options) ([]string, error) { 77 | p := initParser(opts) 78 | 79 | args, err := p.Parse() 80 | if err != nil { 81 | return nil, err 82 | } 83 | 84 | if opts.Version { 85 | mb.ShowVersion(cmdName, version) 86 | osExit(mb.ExitSuccess) 87 | } 88 | 89 | if !isValidArgNr(args) { 90 | fmt.Fprintln(os.Stderr, "basename: no operand") 91 | osExit(mb.ExitFailure) 92 | } 93 | return args, nil 94 | } 95 | 96 | func initParser(opts *options) *flags.Parser { 97 | parser := flags.NewParser(opts, flags.Default) 98 | parser.Name = cmdName 99 | parser.Usage = "[OPTIONS] PATH" 100 | 101 | return parser 102 | } 103 | 104 | func isValidArgNr(args []string) bool { 105 | return len(args) >= 1 106 | } 107 | -------------------------------------------------------------------------------- /internal/applets/shellutils/dirname/dirname.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/dirname/dirname.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package dirname 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "path/filepath" 23 | 24 | "github.com/jessevdk/go-flags" 25 | mb "github.com/nao1215/mimixbox/internal/lib" 26 | ) 27 | 28 | const cmdName string = "dirname" 29 | 30 | const version = "1.0.0" 31 | 32 | var osExit = os.Exit 33 | 34 | type options struct { 35 | Version bool `short:"v" long:"version" description:"Show dirname command version"` 36 | Zero bool `short:"z" long:"zero" description:"Print each output line without line feed"` 37 | } 38 | 39 | func Run() (int, error) { 40 | var opts options 41 | var args []string 42 | var err error 43 | 44 | if args, err = parseArgs(&opts); err != nil { 45 | return mb.ExitFailure, nil 46 | } 47 | 48 | return dirname(args, opts) 49 | } 50 | 51 | func dirname(args []string, opts options) (int, error) { 52 | status := mb.ExitSuccess 53 | for _, path := range args { 54 | dirname := filepath.Dir(os.ExpandEnv(path)) 55 | if opts.Zero { 56 | fmt.Fprintf(os.Stdout, "%s", dirname) 57 | } else { 58 | fmt.Fprintln(os.Stdout, dirname) 59 | } 60 | } 61 | return status, nil 62 | } 63 | 64 | func parseArgs(opts *options) ([]string, error) { 65 | p := initParser(opts) 66 | 67 | args, err := p.Parse() 68 | if err != nil { 69 | return nil, err 70 | } 71 | 72 | if opts.Version { 73 | mb.ShowVersion(cmdName, version) 74 | osExit(mb.ExitSuccess) 75 | } 76 | 77 | if !isValidArgNr(args) { 78 | fmt.Fprintln(os.Stderr, "dirname: no operand") 79 | osExit(mb.ExitFailure) 80 | } 81 | return args, nil 82 | } 83 | 84 | func initParser(opts *options) *flags.Parser { 85 | parser := flags.NewParser(opts, flags.Default) 86 | parser.Name = cmdName 87 | parser.Usage = "[OPTIONS] PATH" 88 | 89 | return parser 90 | } 91 | 92 | func isValidArgNr(args []string) bool { 93 | return len(args) >= 1 94 | } 95 | -------------------------------------------------------------------------------- /internal/applets/shellutils/echo/echo.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/echo/echo.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package echo 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "strings" 23 | 24 | "github.com/jessevdk/go-flags" 25 | mb "github.com/nao1215/mimixbox/internal/lib" 26 | ) 27 | 28 | const cmdName string = "echo" 29 | const version = "1.0.2" 30 | 31 | var osExit = os.Exit 32 | 33 | type options struct { 34 | Version bool `short:"v" long:"version" description:"Show echo command version"` 35 | } 36 | 37 | func Run() (int, error) { 38 | var output []string 39 | var opts options 40 | var args []string 41 | var err error 42 | 43 | if args, err = parseArgs(&opts); err != nil { 44 | return mb.ExitFailure, nil 45 | } 46 | 47 | if len(args) == 0 { 48 | output = make([]string, 0) 49 | } else { 50 | output = os.Args[1:] 51 | } 52 | 53 | fmt.Fprintln(os.Stdout, strings.Join(output, " ")) 54 | return mb.ExitSuccess, nil 55 | } 56 | 57 | func parseArgs(opts *options) ([]string, error) { 58 | p := initParser(opts) 59 | 60 | args, err := p.Parse() 61 | if err != nil { 62 | return nil, err 63 | } 64 | 65 | if opts.Version { 66 | mb.ShowVersion(cmdName, version) 67 | osExit(mb.ExitSuccess) 68 | } 69 | 70 | return args, nil 71 | } 72 | 73 | func initParser(opts *options) *flags.Parser { 74 | parser := flags.NewParser(opts, flags.Default) 75 | parser.Name = cmdName 76 | parser.Usage = "[OPTIONS] STRING" 77 | 78 | return parser 79 | } 80 | -------------------------------------------------------------------------------- /internal/applets/shellutils/false/false.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/false/false.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package false 18 | 19 | import ( 20 | "os" 21 | 22 | "github.com/jessevdk/go-flags" 23 | mb "github.com/nao1215/mimixbox/internal/lib" 24 | ) 25 | 26 | const cmdName string = "false" 27 | const version = "1.0.1" 28 | 29 | var osExit = os.Exit 30 | 31 | type options struct { 32 | Version bool `short:"v" long:"version" description:"Show false command version"` 33 | } 34 | 35 | func Run() (int, error) { 36 | var opts options 37 | var err error 38 | 39 | if _, err = parseArgs(&opts); err != nil { 40 | return mb.ExitFailure, nil 41 | } 42 | return mb.ExitFailure, nil 43 | } 44 | 45 | func parseArgs(opts *options) ([]string, error) { 46 | p := initParser(opts) 47 | 48 | args, err := p.Parse() 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | if opts.Version { 54 | mb.ShowVersion(cmdName, version) 55 | osExit(mb.ExitSuccess) 56 | } 57 | return args, nil 58 | } 59 | 60 | func initParser(opts *options) *flags.Parser { 61 | parser := flags.NewParser(opts, flags.Default) 62 | parser.Name = cmdName 63 | parser.Usage = "[OPTIONS]" 64 | 65 | return parser 66 | } 67 | -------------------------------------------------------------------------------- /internal/applets/shellutils/groups/groups.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/groups/groups.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package groups 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "os/user" 23 | 24 | "github.com/jessevdk/go-flags" 25 | mb "github.com/nao1215/mimixbox/internal/lib" 26 | ) 27 | 28 | const cmdName string = "groups" 29 | const version = "1.0.2" 30 | 31 | var osExit = os.Exit 32 | 33 | type options struct { 34 | Version bool `short:"v" long:"version" description:"Show groups command version"` 35 | } 36 | 37 | func Run() (int, error) { 38 | var opts options 39 | var err error 40 | var args []string 41 | 42 | if args, err = parseArgs(&opts); err != nil { 43 | return mb.ExitSuccess, nil 44 | } 45 | return groups(args) 46 | } 47 | 48 | func groups(args []string) (int, error) { 49 | 50 | if len(args) == 0 { 51 | return showCurrentUserGroups() 52 | } 53 | 54 | var status int = mb.ExitSuccess 55 | for _, uname := range args { 56 | groups, err := mb.Groups(uname) 57 | if err != nil { 58 | fmt.Fprintln(os.Stderr, "can't get "+uname+" groups information") 59 | status = mb.ExitFailure 60 | continue 61 | } 62 | fmt.Fprint(os.Stdout, uname+" : ") 63 | mb.DumpGroups(groups, true) 64 | } 65 | return status, nil 66 | } 67 | 68 | func showCurrentUserGroups() (int, error) { 69 | u, err := user.Current() 70 | if err != nil { 71 | return mb.ExitFailure, err 72 | } 73 | 74 | groups, err := mb.Groups(u.Username) 75 | if err != nil { 76 | return mb.ExitFailure, err 77 | } 78 | mb.DumpGroups(groups, true) 79 | return mb.ExitSuccess, nil 80 | } 81 | 82 | func parseArgs(opts *options) ([]string, error) { 83 | p := initParser(opts) 84 | 85 | args, err := p.Parse() 86 | if err != nil { 87 | return nil, err 88 | } 89 | 90 | if opts.Version { 91 | mb.ShowVersion(cmdName, version) 92 | osExit(mb.ExitSuccess) 93 | } 94 | 95 | return args, nil 96 | } 97 | 98 | func initParser(opts *options) *flags.Parser { 99 | parser := flags.NewParser(opts, flags.Default) 100 | parser.Name = cmdName 101 | parser.Usage = "[OPTIONS] [USERNAME]" 102 | 103 | return parser 104 | } 105 | -------------------------------------------------------------------------------- /internal/applets/shellutils/hostid/hostid.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/hostid/hostid.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package hostid 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "strconv" 23 | "strings" 24 | 25 | "github.com/jessevdk/go-flags" 26 | mb "github.com/nao1215/mimixbox/internal/lib" 27 | ) 28 | 29 | const cmdName string = "hostid" 30 | const version = "0.9.1" 31 | 32 | var osExit = os.Exit 33 | 34 | type options struct { 35 | Version bool `short:"v" long:"version" description:"Show hostid command version"` 36 | } 37 | 38 | func Run() (int, error) { 39 | var opts options 40 | var err error 41 | 42 | if _, err = parseArgs(&opts); err != nil { 43 | return mb.ExitSuccess, nil 44 | } 45 | return hostid() 46 | } 47 | 48 | func hostid() (int, error) { 49 | ip4, err := mb.Ip4() 50 | if err != nil { 51 | return mb.ExitFailure, err 52 | } 53 | 54 | //TODO: The output doesn't match the Coreutils version of hostid command. 55 | // First, the IP address should be calculated from the hostname. 56 | // Next, the process of converting the IP address to hexadecimal does not match. 57 | // I don't know the cause, so I'll deal with it later. 58 | for _, ip := range ip4 { 59 | ipList := strings.Split(ip, ".") 60 | fmt.Fprintf(os.Stdout, "%02x%02x%02x%02x\n", 61 | atoi(ipList[1]), atoi(ipList[0]), atoi(ipList[3]), atoi(ipList[2])) 62 | } 63 | 64 | return mb.ExitSuccess, nil 65 | } 66 | 67 | func atoi(decimal string) int { 68 | i, _ := strconv.Atoi(decimal) 69 | return i 70 | } 71 | 72 | func parseArgs(opts *options) ([]string, error) { 73 | p := initParser(opts) 74 | 75 | args, err := p.Parse() 76 | if err != nil { 77 | return nil, err 78 | } 79 | 80 | if opts.Version { 81 | mb.ShowVersion(cmdName, version) 82 | osExit(mb.ExitSuccess) 83 | } 84 | 85 | return args, nil 86 | } 87 | 88 | func initParser(opts *options) *flags.Parser { 89 | parser := flags.NewParser(opts, flags.Default) 90 | parser.Name = cmdName 91 | parser.Usage = "[OPTIONS]" 92 | 93 | return parser 94 | } 95 | -------------------------------------------------------------------------------- /internal/applets/shellutils/mbsh/builtin/builtInCmds.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/mbsh/builtin/buitInCmds.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package builtin 18 | 19 | import ( 20 | "errors" 21 | ) 22 | 23 | // ビルトインコマンドの書式 24 | type run func(args []string) error 25 | 26 | // ビルトインコマンドのマップ 27 | type builtin map[string]run 28 | 29 | var buitInCmds builtin 30 | 31 | func init() { 32 | buitInCmds = builtin{ 33 | "cd": cd, 34 | } 35 | } 36 | 37 | // 文字列がビルトインコマンドではない 38 | var ErrNotBuiltinCmd = errors.New("the command is not built-in") 39 | 40 | // 引数の文字列がビルトインコマンドかどうかを返す。 41 | // 文字列がビルトインコマンドに含まれればtrue、 42 | // 含まれないもしくはcommand == nilの場合はfalse 43 | func IsBuiltinCmd(command string) bool { 44 | _, ok := buitInCmds[command] 45 | return ok 46 | } 47 | 48 | func Run(key string, args []string) error { 49 | cmd, ok := buitInCmds[key] 50 | if !ok { 51 | return ErrNotBuiltinCmd 52 | } 53 | return cmd(args) 54 | } 55 | -------------------------------------------------------------------------------- /internal/applets/shellutils/mbsh/builtin/cd.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/mbsh/builtin/cd.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package builtin 18 | 19 | import ( 20 | "errors" 21 | "os" 22 | ) 23 | 24 | // ErrNoPath is returned when 'cd' was called without a second argument. 25 | var ErrNoPath = errors.New("path required") 26 | 27 | func cd(args []string) error { 28 | // 'cd' to home with empty path not yet supported. 29 | if len(args) < 2 { 30 | return ErrNoPath 31 | } 32 | // Change the directory and return the error. 33 | return os.Chdir(args[1]) 34 | } 35 | -------------------------------------------------------------------------------- /internal/applets/shellutils/mbsh/mbsh.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/mbsh/mbsh.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mbsh 18 | 19 | import ( 20 | "bufio" 21 | "errors" 22 | "fmt" 23 | "os" 24 | "os/exec" 25 | "strings" 26 | 27 | "github.com/jessevdk/go-flags" 28 | "github.com/nao1215/mimixbox/internal/applets/shellutils/mbsh/builtin" 29 | mb "github.com/nao1215/mimixbox/internal/lib" 30 | ) 31 | 32 | const cmdName string = "mbsh" 33 | 34 | var osExit = os.Exit 35 | 36 | // ErrNoPath is returned when 'cd' was called without a second argument. 37 | var ErrNoPath = errors.New("path required") 38 | 39 | const version = "0.0.2" 40 | 41 | type options struct { 42 | Version bool `short:"v" long:"version" description:"Show shell version"` 43 | } 44 | 45 | func Run() (int, error) { 46 | args, opts := parseArgs() 47 | 48 | fmt.Fprintf(os.Stdout, "Dummy(Not implement shell option): %s:%v\n", args, opts.Version) 49 | 50 | reader := bufio.NewReader(os.Stdin) 51 | for { 52 | fmt.Print("> ") 53 | // Read the keyboad input. 54 | input, err := reader.ReadString('\n') 55 | if err != nil { 56 | fmt.Fprintln(os.Stderr, err) 57 | } 58 | 59 | // Handle the execution of the input. 60 | if err := execInput(input); err != nil { 61 | fmt.Fprintln(os.Stderr, err) 62 | } 63 | } 64 | } 65 | 66 | func execInput(input string) error { 67 | input = strings.TrimSuffix(input, "\n") 68 | args := strings.Split(input, " ") 69 | 70 | // ユーザ入力がビルトインコマンドであれば、優先的に実行する。 71 | if builtin.IsBuiltinCmd(args[0]) { 72 | return builtin.Run(args[0], args[1:]) 73 | } 74 | 75 | // Prepare the command to execute. 76 | cmd := exec.Command(args[0], args[1:]...) 77 | 78 | // Set the correct output device. 79 | cmd.Stderr = os.Stderr 80 | cmd.Stdout = os.Stdout 81 | 82 | // Execute the command and return the error. 83 | return cmd.Run() 84 | } 85 | 86 | // オプション解析 87 | func parseArgs() ([]string, options) { 88 | var opts options 89 | p := initParser(&opts) 90 | 91 | args, err := p.Parse() 92 | if err != nil { 93 | osExit(mb.ExitFailure) 94 | } 95 | 96 | if opts.Version { 97 | mb.ShowVersion(cmdName, version) 98 | osExit(mb.ExitSuccess) 99 | } 100 | 101 | return args, opts 102 | } 103 | 104 | // オプション解析用のパーサを初期化する。 105 | func initParser(opts *options) *flags.Parser { 106 | parser := flags.NewParser(opts, flags.Default) 107 | parser.Name = cmdName 108 | parser.Usage = "[OPTIONS]" 109 | 110 | return parser 111 | } 112 | -------------------------------------------------------------------------------- /internal/applets/shellutils/printenv/printenv.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/printenv/printenv.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package printenv 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | 23 | mb "github.com/nao1215/mimixbox/internal/lib" 24 | 25 | "github.com/jessevdk/go-flags" 26 | ) 27 | 28 | const cmdName string = "printenv" 29 | 30 | const version = "1.0.0" 31 | 32 | var osExit = os.Exit 33 | 34 | type options struct { 35 | Null bool `short:"0" long:"null" description:"End each output line with NULL temination, not newline"` 36 | Version bool `short:"v" long:"version" description:"Show printenv command version"` 37 | } 38 | 39 | func Run() (int, error) { 40 | var opts options 41 | var err error 42 | var args []string 43 | 44 | if args, err = parseArgs(&opts); err != nil { 45 | return mb.ExitFailure, nil 46 | } 47 | return printenv(args, opts) 48 | } 49 | 50 | func printenv(args []string, opts options) (int, error) { 51 | if len(args) == 0 { 52 | return printAllEnvironmentVar(opts) 53 | } 54 | for _, v := range args { 55 | if opts.Null { 56 | fmt.Fprintf(os.Stdout, "%s", os.Getenv(v)) 57 | } else { 58 | fmt.Fprintln(os.Stdout, os.Getenv(v)) 59 | } 60 | } 61 | return mb.ExitSuccess, nil 62 | } 63 | 64 | func printAllEnvironmentVar(opts options) (int, error) { 65 | for _, e := range os.Environ() { 66 | if opts.Null { 67 | fmt.Fprintf(os.Stdout, "%s", e) 68 | } else { 69 | fmt.Fprintln(os.Stdout, e) 70 | } 71 | } 72 | return mb.ExitSuccess, nil 73 | } 74 | 75 | func parseArgs(opts *options) ([]string, error) { 76 | p := initParser(opts) 77 | 78 | args, err := p.Parse() 79 | if err != nil { 80 | return nil, err 81 | } 82 | 83 | if opts.Version { 84 | mb.ShowVersion(cmdName, version) 85 | osExit(mb.ExitSuccess) 86 | } 87 | return args, nil 88 | } 89 | 90 | func initParser(opts *options) *flags.Parser { 91 | parser := flags.NewParser(opts, flags.Default) 92 | parser.Name = cmdName 93 | parser.Usage = "[OPTIONS] ENV" 94 | 95 | return parser 96 | } 97 | -------------------------------------------------------------------------------- /internal/applets/shellutils/printf/printf.go: -------------------------------------------------------------------------------- 1 | package printf 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strconv" 7 | 8 | "github.com/jessevdk/go-flags" 9 | mb "github.com/nao1215/mimixbox/internal/lib" 10 | ) 11 | 12 | const cmdName string = "printf" 13 | const version = "1.0.0" 14 | 15 | var osExit = os.Exit 16 | 17 | type options struct { 18 | Version bool `short:"v" long:"version" description:"Show printf command version"` 19 | } 20 | 21 | func Run() (int, error) { 22 | var output []any 23 | var opts options 24 | var args []string 25 | var err error 26 | var outputstr string 27 | if args, err = parseArgs(&opts); err != nil { 28 | return mb.ExitFailure, nil 29 | } 30 | 31 | if len(args) == 0 { 32 | output = make([]any, 0) 33 | } else { 34 | for i := 1; i < len(args); i++ { 35 | num, err := strconv.Atoi(args[i]) 36 | if err == nil { 37 | output = append(output, num) 38 | } else { 39 | output = append(output, args[i]) 40 | } 41 | } 42 | } 43 | outputstr = fmt.Sprintf(args[0], output...) 44 | fmt.Fprintln(os.Stdout, outputstr) 45 | return mb.ExitSuccess, nil 46 | } 47 | 48 | func parseArgs(opts *options) ([]string, error) { 49 | p := initParser(opts) 50 | 51 | args, err := p.Parse() 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | if opts.Version { 57 | mb.ShowVersion(cmdName, version) 58 | osExit(mb.ExitSuccess) 59 | } 60 | 61 | return args, nil 62 | } 63 | 64 | func initParser(opts *options) *flags.Parser { 65 | parser := flags.NewParser(opts, flags.Default) 66 | parser.Name = cmdName 67 | parser.Usage = "[OPTIONS] STRING" 68 | 69 | return parser 70 | } 71 | -------------------------------------------------------------------------------- /internal/applets/shellutils/pwd/pwd.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/pwd/pwd.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package pwd 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "path/filepath" 23 | 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | 26 | "github.com/jessevdk/go-flags" 27 | ) 28 | 29 | const cmdName string = "pwd" 30 | 31 | const version = "1.0.0" 32 | 33 | var osExit = os.Exit 34 | 35 | type options struct { 36 | Logical bool `short:"L" description:"print the value of $PWD if it names the current working directory (default)"` 37 | Physical bool `short:"P" description:"print the physical directory, without any symbolic links"` 38 | Version bool `short:"v" long:"version" description:"Show pwd command version"` 39 | } 40 | 41 | func Run() (int, error) { 42 | var opts options 43 | var err error 44 | 45 | if _, err = parseArgs(&opts); err != nil { 46 | return mb.ExitFailure, nil 47 | } 48 | return pwd(opts) 49 | } 50 | 51 | func pwd(opts options) (int, error) { 52 | if !opts.Logical && !opts.Physical { 53 | fmt.Fprintln(os.Stdout, os.Getenv("PWD")) 54 | } else if opts.Logical && opts.Physical { 55 | fmt.Fprintln(os.Stdout, os.Getenv("PWD")) 56 | } else if opts.Logical { 57 | fmt.Fprintln(os.Stdout, os.Getenv("PWD")) 58 | } else if opts.Physical { 59 | path, err := filepath.EvalSymlinks(os.Getenv("PWD")) 60 | if err != nil { 61 | return mb.ExitFailure, err 62 | } 63 | fmt.Fprintln(os.Stdout, path) 64 | } 65 | return mb.ExitSuccess, nil 66 | } 67 | 68 | func parseArgs(opts *options) ([]string, error) { 69 | p := initParser(opts) 70 | 71 | args, err := p.Parse() 72 | if err != nil { 73 | return nil, err 74 | } 75 | 76 | if opts.Version { 77 | mb.ShowVersion(cmdName, version) 78 | osExit(mb.ExitSuccess) 79 | } 80 | 81 | return args, nil 82 | } 83 | 84 | func initParser(opts *options) *flags.Parser { 85 | parser := flags.NewParser(opts, flags.Default) 86 | parser.Name = cmdName 87 | parser.Usage = "[OPTIONS]" 88 | 89 | return parser 90 | } 91 | -------------------------------------------------------------------------------- /internal/applets/shellutils/sync/sync.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/sync/sync.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package sync 18 | 19 | import ( 20 | "os" 21 | "syscall" 22 | 23 | mb "github.com/nao1215/mimixbox/internal/lib" 24 | 25 | "github.com/jessevdk/go-flags" 26 | ) 27 | 28 | const cmdName string = "sync" 29 | 30 | const version = "1.0.0" 31 | 32 | var osExit = os.Exit 33 | 34 | type options struct { 35 | Version bool `short:"v" long:"version" description:"Show sync command version"` 36 | } 37 | 38 | func Run() (int, error) { 39 | var opts options 40 | var err error 41 | 42 | if _, err = parseArgs(&opts); err != nil { 43 | return mb.ExitFailure, nil 44 | } 45 | return sync() 46 | } 47 | 48 | func sync() (int, error) { 49 | syscall.Sync() 50 | return mb.ExitSuccess, nil 51 | } 52 | 53 | func parseArgs(opts *options) ([]string, error) { 54 | p := initParser(opts) 55 | 56 | args, err := p.Parse() 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | if opts.Version { 62 | mb.ShowVersion(cmdName, version) 63 | osExit(mb.ExitSuccess) 64 | } 65 | 66 | return args, nil 67 | } 68 | 69 | func initParser(opts *options) *flags.Parser { 70 | parser := flags.NewParser(opts, flags.Default) 71 | parser.Name = cmdName 72 | parser.Usage = "[OPTIONS]" 73 | 74 | return parser 75 | } 76 | -------------------------------------------------------------------------------- /internal/applets/shellutils/true/true.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/true/true.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package true 18 | 19 | import ( 20 | "os" 21 | 22 | "github.com/jessevdk/go-flags" 23 | mb "github.com/nao1215/mimixbox/internal/lib" 24 | ) 25 | 26 | const cmdName string = "true" 27 | const version = "1.0.1" 28 | 29 | var osExit = os.Exit 30 | 31 | type options struct { 32 | Version bool `short:"v" long:"version" description:"Show true command version"` 33 | } 34 | 35 | func Run() (int, error) { 36 | var opts options 37 | var err error 38 | 39 | if _, err = parseArgs(&opts); err != nil { 40 | return mb.ExitSuccess, nil // This is true command. Not retuen fail. 41 | } 42 | return mb.ExitSuccess, nil 43 | } 44 | 45 | func parseArgs(opts *options) ([]string, error) { 46 | p := initParser(opts) 47 | 48 | args, err := p.Parse() 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | if opts.Version { 54 | mb.ShowVersion(cmdName, version) 55 | osExit(mb.ExitSuccess) 56 | } 57 | 58 | return args, nil 59 | } 60 | 61 | func initParser(opts *options) *flags.Parser { 62 | parser := flags.NewParser(opts, flags.Default) 63 | parser.Name = cmdName 64 | parser.Usage = "[OPTIONS]" 65 | 66 | return parser 67 | } 68 | -------------------------------------------------------------------------------- /internal/applets/shellutils/uuidgen/uuidgen.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/uuidgen/uuidgen.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package uuidgen 18 | 19 | import ( 20 | "bufio" 21 | "fmt" 22 | "os" 23 | 24 | "github.com/jessevdk/go-flags" 25 | mb "github.com/nao1215/mimixbox/internal/lib" 26 | ) 27 | 28 | const cmdName string = "uuidgen" 29 | 30 | const version = "1.0.0" 31 | 32 | var osExit = os.Exit 33 | 34 | type options struct { 35 | Version bool `short:"v" long:"version" description:"Show uuidgen command version"` 36 | } 37 | 38 | func Run() (int, error) { 39 | var opts options 40 | var err error 41 | 42 | if _, err = parseArgs(&opts); err != nil { 43 | return mb.ExitFailure, nil 44 | } 45 | return uuidgen() 46 | } 47 | 48 | func parseArgs(opts *options) ([]string, error) { 49 | p := initParser(opts) 50 | 51 | args, err := p.Parse() 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | if opts.Version { 57 | mb.ShowVersion(cmdName, version) 58 | osExit(mb.ExitSuccess) 59 | } 60 | return args, nil 61 | } 62 | 63 | func initParser(opts *options) *flags.Parser { 64 | parser := flags.NewParser(opts, flags.Default) 65 | parser.Name = cmdName 66 | parser.Usage = "[OPTIONS] " 67 | 68 | return parser 69 | } 70 | 71 | // Generate UUID version.4 72 | // [e.g. ver 1.0] 73 | // xxxxxxxx-xxxx-1xxx-xxxx-xxxxxxxxxxxx 74 | // ^ 75 | // | 76 | // always "1" 77 | // [e.g. ver 4.0] 78 | // xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx 79 | // ^ 80 | // | 81 | // always "4" 82 | func uuidgen() (int, error) { 83 | fp, err := os.Open("/proc/sys/kernel/random/uuid") 84 | if err != nil { 85 | return mb.ExitFailure, err 86 | } 87 | defer fp.Close() 88 | 89 | reader := bufio.NewReaderSize(fp, 38) // UUID's format sample: 333f899e-5dbf-41ec-8c42-e3b3ddbe2e68 90 | line, _, err := reader.ReadLine() 91 | if err != nil { 92 | return mb.ExitFailure, err 93 | } 94 | 95 | fmt.Fprintln(os.Stdout, string(line)) 96 | return mb.ExitSuccess, nil 97 | } 98 | -------------------------------------------------------------------------------- /internal/applets/shellutils/whoami/whoami.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/shellutils/whoami/whoami.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package whoami 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "os/user" 23 | 24 | "github.com/jessevdk/go-flags" 25 | mb "github.com/nao1215/mimixbox/internal/lib" 26 | ) 27 | 28 | const cmdName string = "who" 29 | const version = "1.0.0" 30 | 31 | var osExit = os.Exit 32 | 33 | type options struct { 34 | Version bool `short:"v" long:"version" description:"Show whoami command version"` 35 | } 36 | 37 | func Run() (int, error) { 38 | var opts options 39 | var err error 40 | 41 | if _, err = parseArgs(&opts); err != nil { 42 | return mb.ExitSuccess, nil 43 | } 44 | return whoami() 45 | } 46 | 47 | func whoami() (int, error) { 48 | user, err := user.Current() 49 | if err != nil { 50 | return mb.ExitFailure, err 51 | } 52 | fmt.Fprintln(os.Stdout, user.Username) 53 | return mb.ExitSuccess, nil 54 | } 55 | 56 | func parseArgs(opts *options) ([]string, error) { 57 | p := initParser(opts) 58 | 59 | args, err := p.Parse() 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | if opts.Version { 65 | mb.ShowVersion(cmdName, version) 66 | osExit(mb.ExitSuccess) 67 | } 68 | 69 | return args, nil 70 | } 71 | 72 | func initParser(opts *options) *flags.Parser { 73 | parser := flags.NewParser(opts, flags.Default) 74 | parser.Name = cmdName 75 | parser.Usage = "[OPTIONS]" 76 | 77 | return parser 78 | } 79 | -------------------------------------------------------------------------------- /internal/applets/textutils/cat/cat.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/textutils/cat/cat.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package cat 18 | 19 | import ( 20 | "os" 21 | 22 | mb "github.com/nao1215/mimixbox/internal/lib" 23 | 24 | "github.com/jessevdk/go-flags" 25 | ) 26 | 27 | const cmdName string = "cat" 28 | 29 | const version = "1.0.10" 30 | 31 | var osExit = os.Exit 32 | 33 | type options struct { 34 | Number bool `short:"n" long:"number" description:"Print with line number"` 35 | Version bool `short:"v" long:"version" description:"Show cat command version"` 36 | } 37 | 38 | func Run() (int, error) { 39 | var opts options 40 | var args []string 41 | var err error 42 | 43 | if args, err = parseArgs(&opts); err != nil { 44 | return mb.ExitFailure, nil 45 | } 46 | 47 | if mb.HasPipeData() && mb.HasNoOperand(os.Args, cmdName) { 48 | mb.Dump(args, opts.Number) 49 | return mb.ExitSuccess, nil 50 | } 51 | 52 | if len(args) == 0 || mb.Contains(args, "-") { 53 | mb.Parrot(opts.Number) 54 | if len(args) == 0 { 55 | return mb.ExitSuccess, nil 56 | } 57 | // If this case, Heredocuments and files may be concatenated. 58 | args = mb.Remove(args, "-") 59 | } 60 | 61 | strLisr, err := mb.Concatenate(args) 62 | if err != nil { 63 | return mb.ExitFailure, err 64 | } 65 | 66 | mb.Dump(strLisr, opts.Number) 67 | 68 | return mb.ExitSuccess, nil 69 | } 70 | 71 | func parseArgs(opts *options) ([]string, error) { 72 | p := initParser(opts) 73 | 74 | args, err := p.Parse() 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | if mb.HasPipeData() && len(args) == 0 { 80 | stdin, err := mb.FromPIPE() 81 | if err != nil { 82 | return nil, err 83 | } 84 | return []string{stdin}, nil 85 | } 86 | 87 | if opts.Version { 88 | mb.ShowVersion(cmdName, version) 89 | osExit(mb.ExitSuccess) 90 | } 91 | 92 | return args, nil 93 | } 94 | 95 | func initParser(opts *options) *flags.Parser { 96 | parser := flags.NewParser(opts, flags.Default) 97 | parser.Name = cmdName 98 | parser.Usage = "[OPTIONS] FILE_PATH" 99 | 100 | return parser 101 | } 102 | -------------------------------------------------------------------------------- /internal/applets/textutils/expand/expand.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/textutils/expand/expand.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package expand 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "strings" 23 | 24 | "github.com/jessevdk/go-flags" 25 | mb "github.com/nao1215/mimixbox/internal/lib" 26 | ) 27 | 28 | const cmdName string = "expand" 29 | const version = "1.0.3" 30 | 31 | var osExit = os.Exit 32 | 33 | type options struct { 34 | Tab int `short:"t" long:"tab" default:"8" description:"Convert TAB to N space (default:N=8)"` 35 | Version bool `short:"v" long:"version" description:"Show expand command version"` 36 | } 37 | 38 | func Run() (int, error) { 39 | var opts options 40 | var err error 41 | var args []string 42 | 43 | if args, err = parseArgs(&opts); err != nil { 44 | return mb.ExitSuccess, nil 45 | } 46 | 47 | if mb.HasPipeData() { 48 | mb.Dump(mb.AddLineFeed(strings.Split(args[0], "\n")), false) 49 | return mb.ExitSuccess, nil 50 | } 51 | 52 | if len(args) == 0 || mb.Contains(args, "-") { 53 | mb.Parrot(false) 54 | return mb.ExitSuccess, nil 55 | } 56 | 57 | return expand(args, opts) 58 | } 59 | 60 | func expand(args []string, opts options) (int, error) { 61 | status := mb.ExitSuccess 62 | for _, file := range args { 63 | target := os.ExpandEnv(file) 64 | if !mb.IsFile(target) { 65 | fmt.Fprintln(os.Stderr, target+": No such file. Skip it") 66 | status = mb.ExitFailure 67 | continue 68 | } 69 | lines, err := mb.ReadFileToStrList(target) 70 | if err != nil { 71 | fmt.Fprintln(os.Stderr, err) 72 | status = mb.ExitFailure 73 | continue 74 | } 75 | 76 | mb.Dump(mb.ReplaceAll(lines, "\t", strings.Repeat(" ", opts.Tab)), false) 77 | } 78 | return status, nil 79 | } 80 | 81 | func parseArgs(opts *options) ([]string, error) { 82 | p := initParser(opts) 83 | 84 | args, err := p.Parse() 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | if mb.HasPipeData() { 90 | stdin, err := mb.FromPIPE() 91 | if err != nil { 92 | return nil, err 93 | } 94 | return []string{stdin}, nil 95 | } 96 | 97 | if opts.Version { 98 | mb.ShowVersion(cmdName, version) 99 | osExit(mb.ExitSuccess) 100 | } 101 | 102 | if opts.Tab <= 0 { 103 | opts.Tab = 8 104 | } 105 | 106 | return args, nil 107 | } 108 | 109 | func initParser(opts *options) *flags.Parser { 110 | parser := flags.NewParser(opts, flags.Default) 111 | parser.Name = cmdName 112 | parser.Usage = "[OPTIONS] FILE_NAME" 113 | 114 | return parser 115 | } 116 | -------------------------------------------------------------------------------- /internal/applets/textutils/md5sum/md5sum.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/textutils/md5sum/md5sum.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package md5sum 18 | 19 | import ( 20 | "crypto/md5" 21 | "os" 22 | "strings" 23 | 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | 26 | "github.com/jessevdk/go-flags" 27 | ) 28 | 29 | const cmdName string = "md5sum" 30 | 31 | const version = "1.0.1" 32 | 33 | var osExit = os.Exit 34 | 35 | type options struct { 36 | Check bool `short:"c" long:"check" description:"Check if the MD5 hash value matches the file"` 37 | Version bool `short:"v" long:"version" description:"Show md5sum command version"` 38 | } 39 | 40 | func Run() (int, error) { 41 | var opts options 42 | var args []string 43 | var err error = nil 44 | hash := md5.New() 45 | 46 | if args, err = parseArgs(&opts); err != nil { 47 | return mb.ExitFailure, nil 48 | } 49 | 50 | if mb.HasPipeData() && mb.HasNoOperand(os.Args, cmdName) { 51 | err = mb.ChecksumOutput(hash, strings.NewReader(args[0]), "-") 52 | if err != nil { 53 | return mb.ExitFailure, err 54 | } 55 | return mb.ExitSuccess, nil 56 | } 57 | 58 | if len(args) == 0 || mb.Contains(args, "-") { 59 | err = mb.ChecksumOutput(hash, os.Stdin, "-") 60 | if err != nil { 61 | return mb.ExitSuccess, nil 62 | } 63 | return mb.ExitSuccess, nil 64 | } 65 | 66 | if opts.Check { 67 | err = mb.CompareChecksum(hash, args) 68 | if err != nil { 69 | return mb.ExitFailure, err 70 | } 71 | return mb.ExitSuccess, nil 72 | } 73 | 74 | return mb.PrintChecksums(cmdName, hash, args) 75 | } 76 | 77 | func parseArgs(opts *options) ([]string, error) { 78 | p := initParser(opts) 79 | 80 | args, err := p.Parse() 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | if mb.HasPipeData() && len(args) == 0 { 86 | stdin, err := mb.FromPIPE() 87 | if err != nil { 88 | return nil, err 89 | } 90 | return []string{stdin}, nil 91 | } 92 | 93 | if opts.Version { 94 | mb.ShowVersion(cmdName, version) 95 | osExit(mb.ExitSuccess) 96 | } 97 | 98 | return args, nil 99 | } 100 | 101 | func initParser(opts *options) *flags.Parser { 102 | parser := flags.NewParser(opts, flags.Default) 103 | parser.Name = cmdName 104 | parser.Usage = "[OPTIONS] FILE_PATH" 105 | 106 | return parser 107 | } 108 | -------------------------------------------------------------------------------- /internal/applets/textutils/nl/nl.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/textutils/nl/nl.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package nl 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | 23 | mb "github.com/nao1215/mimixbox/internal/lib" 24 | 25 | "github.com/jessevdk/go-flags" 26 | ) 27 | 28 | const cmdName string = "nl" 29 | 30 | const version = "1.0.2" 31 | 32 | var osExit = os.Exit 33 | 34 | type options struct { 35 | Version bool `short:"v" long:"version" description:"Show nl command version"` 36 | } 37 | 38 | func Run() (int, error) { 39 | var opts options 40 | var args []string 41 | var err error 42 | 43 | if args, err = parseArgs(&opts); err != nil { 44 | return mb.ExitFailure, nil 45 | } 46 | 47 | if mb.HasPipeData() && mb.HasNoOperand(os.Args, cmdName) { 48 | mb.PrintStrListWithNumberLine(args, true) 49 | return mb.ExitSuccess, nil 50 | } 51 | 52 | var pipeData []string 53 | if len(args) == 0 || mb.Contains(args, "-") { 54 | var nr int = 1 55 | for { 56 | input, next := mb.Input() 57 | if !next { 58 | break 59 | } 60 | pipeData = append(pipeData, input+"\n") 61 | if input != "" && len(args) == 0 { 62 | mb.PrintStrWithNumberLine(nr, " %6d %s", input+"\n") 63 | nr++ 64 | } else if input == "" && len(args) == 0 { 65 | fmt.Fprintln(os.Stdout, "") 66 | } 67 | } 68 | if len(args) == 0 { 69 | return mb.ExitSuccess, nil 70 | } 71 | // If this case, Heredocuments and files may be concatenated. 72 | args = mb.Remove(args, "-") 73 | } 74 | 75 | lines, err := mb.Concatenate(args) 76 | if err != nil { 77 | return mb.ExitFailure, err 78 | } 79 | 80 | if len(pipeData) >= 1 { 81 | lines = append(pipeData, lines...) 82 | } 83 | mb.PrintStrListWithNumberLine(lines, false) 84 | 85 | return mb.ExitSuccess, nil 86 | } 87 | 88 | func parseArgs(opts *options) ([]string, error) { 89 | p := initParser(opts) 90 | 91 | args, err := p.Parse() 92 | if err != nil { 93 | return nil, err 94 | } 95 | 96 | if mb.HasPipeData() && len(args) == 0 { 97 | stdin, err := mb.FromPIPE() 98 | if err != nil { 99 | return nil, err 100 | } 101 | return []string{stdin}, nil 102 | } 103 | 104 | if opts.Version { 105 | mb.ShowVersion(cmdName, version) 106 | osExit(mb.ExitSuccess) 107 | } 108 | 109 | return args, nil 110 | } 111 | 112 | func initParser(opts *options) *flags.Parser { 113 | parser := flags.NewParser(opts, flags.Default) 114 | parser.Name = cmdName 115 | parser.Usage = "[OPTIONS] FILE_PATH" 116 | 117 | return parser 118 | } 119 | -------------------------------------------------------------------------------- /internal/applets/textutils/sha1sum/sha1sum.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/textutils/md5sum/md5sum.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package sha1sum 18 | 19 | import ( 20 | "crypto/sha1" 21 | "os" 22 | "strings" 23 | 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | 26 | "github.com/jessevdk/go-flags" 27 | ) 28 | 29 | const cmdName string = "sha1sum" 30 | 31 | const version = "1.0.1" 32 | 33 | var osExit = os.Exit 34 | 35 | type options struct { 36 | Check bool `short:"c" long:"check" description:"Check if the SHA1 value matches the file"` 37 | Version bool `short:"v" long:"version" description:"Show sha1sum command version"` 38 | } 39 | 40 | func Run() (int, error) { 41 | var opts options 42 | var args []string 43 | var err error = nil 44 | hash := sha1.New() 45 | 46 | if args, err = parseArgs(&opts); err != nil { 47 | return mb.ExitFailure, nil 48 | } 49 | 50 | if mb.HasPipeData() && mb.HasNoOperand(os.Args, cmdName) { 51 | err = mb.ChecksumOutput(hash, strings.NewReader(args[0]), "-") 52 | if err != nil { 53 | return mb.ExitFailure, err 54 | } 55 | return mb.ExitSuccess, nil 56 | } 57 | 58 | if len(args) == 0 || mb.Contains(args, "-") { 59 | err = mb.ChecksumOutput(hash, os.Stdin, "-") 60 | if err != nil { 61 | return mb.ExitSuccess, nil 62 | } 63 | return mb.ExitSuccess, nil 64 | } 65 | 66 | if opts.Check { 67 | err = mb.CompareChecksum(hash, args) 68 | if err != nil { 69 | return mb.ExitFailure, err 70 | } 71 | return mb.ExitSuccess, nil 72 | } 73 | 74 | return mb.PrintChecksums(cmdName, hash, args) 75 | } 76 | 77 | func parseArgs(opts *options) ([]string, error) { 78 | p := initParser(opts) 79 | 80 | args, err := p.Parse() 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | if mb.HasPipeData() && len(args) == 0 { 86 | stdin, err := mb.FromPIPE() 87 | if err != nil { 88 | return nil, err 89 | } 90 | return []string{stdin}, nil 91 | } 92 | 93 | if opts.Version { 94 | mb.ShowVersion(cmdName, version) 95 | osExit(mb.ExitSuccess) 96 | } 97 | 98 | return args, nil 99 | } 100 | 101 | func initParser(opts *options) *flags.Parser { 102 | parser := flags.NewParser(opts, flags.Default) 103 | parser.Name = cmdName 104 | parser.Usage = "[OPTIONS] FILE_PATH" 105 | 106 | return parser 107 | } 108 | -------------------------------------------------------------------------------- /internal/applets/textutils/sha256sum/sha256sum.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/textutils/sha256sum/sha256sum.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package sha256sum 18 | 19 | import ( 20 | "crypto/sha256" 21 | "os" 22 | "strings" 23 | 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | 26 | "github.com/jessevdk/go-flags" 27 | ) 28 | 29 | const cmdName string = "sha256sum" 30 | 31 | const version = "1.0.1" 32 | 33 | var osExit = os.Exit 34 | 35 | type options struct { 36 | Check bool `short:"c" long:"check" description:"Check if the SHA1 value matches the file"` 37 | Version bool `short:"v" long:"version" description:"Show sha256sum command version"` 38 | } 39 | 40 | func Run() (int, error) { 41 | var opts options 42 | var args []string 43 | var err error = nil 44 | hash := sha256.New() 45 | 46 | if args, err = parseArgs(&opts); err != nil { 47 | return mb.ExitFailure, nil 48 | } 49 | 50 | if mb.HasPipeData() && mb.HasNoOperand(os.Args, cmdName) { 51 | err = mb.ChecksumOutput(hash, strings.NewReader(args[0]), "-") 52 | if err != nil { 53 | return mb.ExitFailure, err 54 | } 55 | return mb.ExitSuccess, nil 56 | } 57 | 58 | if len(args) == 0 || mb.Contains(args, "-") { 59 | err = mb.ChecksumOutput(hash, os.Stdin, "-") 60 | if err != nil { 61 | return mb.ExitSuccess, nil 62 | } 63 | return mb.ExitSuccess, nil 64 | } 65 | 66 | if opts.Check { 67 | err = mb.CompareChecksum(hash, args) 68 | if err != nil { 69 | return mb.ExitFailure, err 70 | } 71 | return mb.ExitSuccess, nil 72 | } 73 | 74 | return mb.PrintChecksums(cmdName, hash, args) 75 | } 76 | 77 | func parseArgs(opts *options) ([]string, error) { 78 | p := initParser(opts) 79 | 80 | args, err := p.Parse() 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | if mb.HasPipeData() && len(args) == 0 { 86 | stdin, err := mb.FromPIPE() 87 | if err != nil { 88 | return nil, err 89 | } 90 | return []string{stdin}, nil 91 | } 92 | 93 | if opts.Version { 94 | mb.ShowVersion(cmdName, version) 95 | osExit(mb.ExitSuccess) 96 | } 97 | 98 | return args, nil 99 | } 100 | 101 | func initParser(opts *options) *flags.Parser { 102 | parser := flags.NewParser(opts, flags.Default) 103 | parser.Name = cmdName 104 | parser.Usage = "[OPTIONS] FILE_PATH" 105 | 106 | return parser 107 | } 108 | -------------------------------------------------------------------------------- /internal/applets/textutils/sha512sum/sha512sum.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/textutils/sha512sum/sha512sum.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package sha512sum 18 | 19 | import ( 20 | "crypto/sha512" 21 | "os" 22 | "strings" 23 | 24 | mb "github.com/nao1215/mimixbox/internal/lib" 25 | 26 | "github.com/jessevdk/go-flags" 27 | ) 28 | 29 | const cmdName string = "sha512sum" 30 | 31 | const version = "1.0.1" 32 | 33 | var osExit = os.Exit 34 | 35 | type options struct { 36 | Check bool `short:"c" long:"check" description:"Check if the SHA1 value matches the file"` 37 | Version bool `short:"v" long:"version" description:"Show sha512sum command version"` 38 | } 39 | 40 | func Run() (int, error) { 41 | var opts options 42 | var args []string 43 | var err error = nil 44 | hash := sha512.New() 45 | 46 | if args, err = parseArgs(&opts); err != nil { 47 | return mb.ExitFailure, nil 48 | } 49 | 50 | if mb.HasPipeData() && mb.HasNoOperand(os.Args, cmdName) { 51 | err = mb.ChecksumOutput(hash, strings.NewReader(args[0]), "-") 52 | if err != nil { 53 | return mb.ExitFailure, err 54 | } 55 | return mb.ExitSuccess, nil 56 | } 57 | 58 | if len(args) == 0 || mb.Contains(args, "-") { 59 | err = mb.ChecksumOutput(hash, os.Stdin, "-") 60 | if err != nil { 61 | return mb.ExitSuccess, nil 62 | } 63 | return mb.ExitSuccess, nil 64 | } 65 | 66 | if opts.Check { 67 | err = mb.CompareChecksum(hash, args) 68 | if err != nil { 69 | return mb.ExitFailure, err 70 | } 71 | return mb.ExitSuccess, nil 72 | } 73 | 74 | return mb.PrintChecksums(cmdName, hash, args) 75 | } 76 | 77 | func parseArgs(opts *options) ([]string, error) { 78 | p := initParser(opts) 79 | 80 | args, err := p.Parse() 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | if mb.HasPipeData() && len(args) == 0 { 86 | stdin, err := mb.FromPIPE() 87 | if err != nil { 88 | return nil, err 89 | } 90 | return []string{stdin}, nil 91 | } 92 | 93 | if opts.Version { 94 | mb.ShowVersion(cmdName, version) 95 | osExit(mb.ExitSuccess) 96 | } 97 | 98 | return args, nil 99 | } 100 | 101 | func initParser(opts *options) *flags.Parser { 102 | parser := flags.NewParser(opts, flags.Default) 103 | parser.Name = cmdName 104 | parser.Usage = "[OPTIONS] FILE_PATH" 105 | 106 | return parser 107 | } 108 | -------------------------------------------------------------------------------- /internal/applets/textutils/unexpand/unexpand.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/applets/textutils/expand/expand.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package unexpand 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "strings" 23 | 24 | "github.com/jessevdk/go-flags" 25 | mb "github.com/nao1215/mimixbox/internal/lib" 26 | ) 27 | 28 | const cmdName string = "unexpand" 29 | const version = "1.0.3" 30 | 31 | var osExit = os.Exit 32 | 33 | type options struct { 34 | Tab int `short:"t" long:"tab" default:"8" description:"Convert N space to TAB(default:N=8)"` 35 | Version bool `short:"v" long:"version" description:"Show unexpand command version"` 36 | } 37 | 38 | func Run() (int, error) { 39 | var opts options 40 | var err error 41 | var args []string 42 | 43 | if args, err = parseArgs(&opts); err != nil { 44 | return mb.ExitSuccess, nil 45 | } 46 | 47 | if mb.HasPipeData() { 48 | mb.Dump(mb.AddLineFeed(strings.Split(args[0], "\n")), false) 49 | return mb.ExitSuccess, nil 50 | } 51 | 52 | if len(args) == 0 || mb.Contains(args, "-") { 53 | mb.Parrot(false) 54 | return mb.ExitSuccess, nil 55 | } 56 | 57 | return unexpand(args, opts) 58 | } 59 | 60 | func unexpand(args []string, opts options) (int, error) { 61 | status := mb.ExitSuccess 62 | for _, file := range args { 63 | target := os.ExpandEnv(file) 64 | if !mb.IsFile(target) { 65 | fmt.Fprintln(os.Stderr, target+": No such file. Skip it") 66 | status = mb.ExitFailure 67 | continue 68 | } 69 | lines, err := mb.ReadFileToStrList(target) 70 | if err != nil { 71 | fmt.Fprintln(os.Stderr, err) 72 | status = mb.ExitFailure 73 | continue 74 | } 75 | 76 | mb.Dump(mb.ReplaceAll(lines, strings.Repeat(" ", opts.Tab), "\t"), false) 77 | } 78 | return status, nil 79 | } 80 | 81 | func parseArgs(opts *options) ([]string, error) { 82 | p := initParser(opts) 83 | 84 | args, err := p.Parse() 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | if mb.HasPipeData() { 90 | stdin, err := mb.FromPIPE() 91 | if err != nil { 92 | return nil, err 93 | } 94 | return []string{stdin}, nil 95 | } 96 | 97 | if opts.Version { 98 | mb.ShowVersion(cmdName, version) 99 | osExit(mb.ExitSuccess) 100 | } 101 | 102 | if opts.Tab <= 0 { 103 | opts.Tab = 8 104 | } 105 | 106 | return args, nil 107 | } 108 | 109 | func initParser(opts *options) *flags.Parser { 110 | parser := flags.NewParser(opts, flags.Default) 111 | parser.Name = cmdName 112 | parser.Usage = "[OPTIONS] FILE_NAME" 113 | 114 | return parser 115 | } 116 | -------------------------------------------------------------------------------- /internal/lib/common.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/lib/common.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mb 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | ) 23 | 24 | const ( 25 | ExitSuccess int = iota // 0 26 | ExitFailure 27 | ) 28 | 29 | func ShowVersion(cmdName string, version string) { 30 | description := cmdName + " version " + version + " (under Apache License version 2.0)" 31 | fmt.Fprintln(os.Stdout, description) 32 | } 33 | -------------------------------------------------------------------------------- /internal/lib/gnu.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/lib/gnu.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mb 18 | 19 | import "os" 20 | 21 | func SimpleBackupSuffix() string { 22 | suffix := os.Getenv("SIMPLE_BACKUP_SUFFIX") 23 | if suffix == "" { 24 | return "~" 25 | } 26 | return suffix 27 | } 28 | -------------------------------------------------------------------------------- /internal/lib/id.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/lib/id.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mb 18 | 19 | import ( 20 | "os/user" 21 | "strconv" 22 | ) 23 | 24 | func LookupGid(groupId string) (int, error) { 25 | group, err := user.LookupGroupId(groupId) 26 | if err != nil { 27 | group, err = user.LookupGroup(groupId) 28 | if err != nil { 29 | return 0, err 30 | } 31 | } 32 | 33 | gid, err := strconv.Atoi(group.Gid) 34 | if err != nil { 35 | return 0, err 36 | } 37 | return gid, nil 38 | } 39 | 40 | func LookupUid(userId string) (int, error) { 41 | u, err := user.LookupId(userId) 42 | if err != nil { 43 | u, err = user.Lookup(userId) 44 | if err != nil { 45 | return 0, err 46 | } 47 | } 48 | uid, err := strconv.Atoi(u.Uid) 49 | if err != nil { 50 | return 0, err 51 | } 52 | return uid, nil 53 | } 54 | -------------------------------------------------------------------------------- /internal/lib/net.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/lib/net.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mb 18 | 19 | import ( 20 | "net" 21 | ) 22 | 23 | func Ip4() ([]string, error) { 24 | var ip4 []string 25 | interfaces, err := net.Interfaces() 26 | if err != nil { 27 | return nil, err 28 | } 29 | for _, inter := range interfaces { 30 | addrs, err := inter.Addrs() 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | for _, a := range addrs { 36 | if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 37 | if ipnet.IP.To4() != nil { 38 | ip4 = append(ip4, ipnet.IP.String()) 39 | } 40 | } 41 | } 42 | } 43 | return ip4, nil 44 | } 45 | -------------------------------------------------------------------------------- /internal/lib/option.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/lib/option.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mb 18 | 19 | // For historical reasons, there are commands whose option system is 20 | // neither POSIX(short option) nor GNU(long option with POSIX one). 21 | // This file parses the arguments for such commands. 22 | 23 | func HasVersionOpt(args []string) bool { 24 | return Contains(args, "--version") || Contains(args, "-v") 25 | } 26 | 27 | func HasHelpOpt(args []string) bool { 28 | return Contains(args, "--help") || Contains(args, "-h") 29 | } 30 | -------------------------------------------------------------------------------- /internal/lib/path.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/lib/path.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mb 18 | 19 | import ( 20 | "os" 21 | "path/filepath" 22 | "strings" 23 | ) 24 | 25 | // IsSamePath return true if src and dest is same path, 26 | // false if src and dest is not same path or error occur 27 | func IsSamePath(src string, dest string) bool { 28 | s, err := filepath.Abs(src) 29 | if err != nil { 30 | return false 31 | } 32 | 33 | d, err := filepath.Abs(dest) 34 | if err != nil { 35 | return false 36 | } 37 | return s == d 38 | } 39 | 40 | // TopDirName return top directory name from path. 41 | func TopDirName(path string) string { 42 | index := strings.Index(path, string(os.PathSeparator)) 43 | if index == -1 { 44 | return path 45 | } 46 | 47 | byteList := []byte(path) 48 | return string(byteList[:index]) 49 | } 50 | -------------------------------------------------------------------------------- /internal/lib/shadow.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/lib/shadow.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mb 18 | 19 | import ( 20 | "os" 21 | ) 22 | 23 | const ShellsFilePath = "/etc/shells" 24 | 25 | func TmpShellsFile() string { 26 | return ShellsFilePath + ".tmp" 27 | } 28 | 29 | func IsRootUser() bool { 30 | return os.Geteuid() == 0 && os.Getuid() == 0 31 | } 32 | 33 | /* TODO: See chsh command. 34 | func HasPamModule() bool { 35 | return IsFile("/etc/pam.conf") 36 | } 37 | 38 | func AuthByPasswordWithPam(userName string) error { 39 | // Stopping logging is not security measures. 40 | // There is a problem that the log during authentication cannot be stopped, 41 | // and the log is temporarily disabled in the workaround. 42 | // log.SetOutput(ioutil.Discard) 43 | 44 | fmt.Fprintf(os.Stdout, "Enter password: ") 45 | passwd, err := terminal.ReadPassword(syscall.Stdin) 46 | if err != nil { 47 | return err 48 | } 49 | fmt.Fprintln(os.Stdout, "") 50 | 51 | reader := bytes.NewReader(passwd) 52 | key, err := crypto.NewKeyFromReader(reader) 53 | if err != nil { 54 | return err 55 | } 56 | defer key.Wipe() 57 | 58 | err = pam.IsUserLoginToken(userName, key, true) 59 | return err 60 | } 61 | */ 62 | -------------------------------------------------------------------------------- /internal/lib/string.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/lib/string.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mb 18 | 19 | import ( 20 | "strconv" 21 | "strings" 22 | ) 23 | 24 | func ReplaceAll(lines []string, target string, after string) []string { 25 | var replacedLines []string 26 | for _, line := range lines { 27 | l := strings.ReplaceAll(line, target, after) 28 | replacedLines = append(replacedLines, l) 29 | } 30 | return replacedLines 31 | } 32 | 33 | func Remove(strings []string, target string) []string { 34 | result := []string{} 35 | for _, v := range strings { 36 | if v != target { 37 | result = append(result, v) 38 | } 39 | } 40 | return result 41 | } 42 | 43 | func AddLineFeed(lines []string) []string { 44 | var newLines []string 45 | for _, v := range lines { 46 | newLines = append(newLines, v+"\n") 47 | } 48 | return newLines 49 | } 50 | 51 | func ListDigit(strList []string) string { 52 | return strconv.Itoa(len(strconv.Itoa(len(strList)))) 53 | } 54 | 55 | func WithSingleCoat(str string) string { 56 | return "'" + str + "'" 57 | } 58 | -------------------------------------------------------------------------------- /internal/lib/type.go: -------------------------------------------------------------------------------- 1 | // 2 | // mimixbox/internal/lib/type.go 3 | // 4 | // Copyright 2021 Naohiro CHIKAMATSU 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | package mb 18 | 19 | import "reflect" 20 | 21 | func Contains(list interface{}, elem interface{}) bool { 22 | rvList := reflect.ValueOf(list) 23 | 24 | if rvList.Kind() == reflect.Slice { 25 | for i := 0; i < rvList.Len(); i++ { 26 | item := rvList.Index(i).Interface() 27 | if !reflect.TypeOf(elem).ConvertibleTo(reflect.TypeOf(item)) { 28 | continue 29 | } 30 | target := reflect.ValueOf(elem).Convert(reflect.TypeOf(item)).Interface() 31 | if ok := reflect.DeepEqual(item, target); ok { 32 | return true 33 | } 34 | } 35 | } 36 | return false 37 | } 38 | -------------------------------------------------------------------------------- /scripts/installer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | # [Description] 3 | # This shell script is the installer for the command. 4 | # This is created to be stored in tar.gz or zip for release files. 5 | ORG_COMMANDS="path serial ghrdc fakemovie mimixbox sddf" 6 | DOC_INSTALL_DIR="/usr/share/doc/mimixbox" 7 | ROOT_DIR=$(git rev-parse --show-toplevel) 8 | 9 | source ${ROOT_DIR}/scripts/libshell.sh 10 | 11 | function installMimixBox() { 12 | install -v -m 0755 -D mimixbox /usr/local/bin/. 13 | mimixbox --install /usr/local/bin/. 14 | } 15 | 16 | function installManPages() { 17 | warnMsg "Install man-pages" 18 | for i in ${ORG_COMMANDS}; 19 | do 20 | install -v -m 0644 -D docs/man/$i/en/$i.1.gz /usr/share/man/man1/$i.1.gz 21 | install -v -m 0644 -D docs/man/$i/ja/$i.1.gz /usr/share/man/ja/man1/$i.1.gz 22 | done 23 | } 24 | 25 | function installLicense() { 26 | warnMsg "Install LICENSE at ${DOC_INSTALL_DIR}" 27 | mkdir -p ${DOC_INSTALL_DIR} 28 | #install -v -m 0644 LICENSE ${DOC_INSTALL_DIR} 29 | #install -v -m 0644 NOTICE ${DOC_INSTALL_DIR} 30 | cp -rf licenses ${DOC_INSTALL_DIR} 31 | } 32 | 33 | IS_ROOT=$(isRoot) 34 | if [ "$IS_ROOT" = "1" ]; then 35 | errMsg "[Usage]" 36 | errMsg " $ sudo ./installer.sh" 37 | exit 1 38 | fi 39 | warnMsg "[Start] Install." 40 | installMimixBox 41 | installManPages 42 | installLicense 43 | warnMsg "[Done]" -------------------------------------------------------------------------------- /scripts/libshell.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # @(#) libshell.sh is bash function library. 3 | # 4 | # Description : 5 | # libshell.sh is bash function library. 6 | # If you use this library, source this library in bash script. 7 | # 8 | # [e.g. write down the following command in bash script(*.sh file)] 9 | # source /libshell.sh 10 | # 11 | 12 | # errMsg() output message in red to stdout. 13 | # arg1: message. 14 | function errMsg() { 15 | local message="$1" 16 | echo -n -e "\033[31m\c" # Escape sequence to make text color red 17 | echo "${message}" >&2 18 | echo -n -e "\033[m\c"  # Escape sequence to restore font color 19 | } 20 | 21 | 22 | # warnMsg() output message in yellow to stdout. 23 | # arg1: message. 24 | function warnMsg() { 25 | local message="$1" 26 | echo -n -e "\033[33m\c" # Escape sequence to make text color yellow 27 | echo "${message}" 28 | echo -n -e "\033[m\c"  # Escape sequence to restore font color 29 | } 30 | 31 | # isRoot() check whether user is root or not. 32 | function isRoot() { 33 | if [ ${EUID:-${UID}} != 0 ]; then 34 | echo "1" 35 | return 36 | fi 37 | echo "0" 38 | } 39 | 40 | # getAbsPath() get the absolute path where 41 | # the script exists. 42 | # arg1: script path(This mean "$0", itself) 43 | function getAbsPath() { 44 | local abs_path="" 45 | local script_name="$1" 46 | 47 | abs_path=$(cd $(dirname $1); pwd) 48 | echo ${abs_path} 49 | } 50 | 51 | 52 | # upper() change from lower case to upper case. 53 | # arg1: strings to be changed. 54 | function upper() { 55 | local str="$1" 56 | echo -n ${str} | tr '[a-z]' '[A-Z]' 57 | } 58 | 59 | # lower() change from upper case to lower case. 60 | # arg1: strings to be changed. 61 | function lower() { 62 | local str="$1" 63 | echo -n ${str} | tr '[A-Z]' '[a-z]' 64 | } 65 | -------------------------------------------------------------------------------- /scripts/mkJailForDebianFamily.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # [Description] 4 | # This shell script make rootfs(jail). Rootfs is created as /tmp/mimixbox/jail 5 | # by debootstrap command. It is used as the test environment for chroot 6 | # command and ischroot command. 7 | # This script cannot create rootfs on RHEL-based distributions. 8 | # Only work for Debian-based one. 9 | ROOT_DIR=$(git rev-parse --show-toplevel) 10 | SCRIPT_NAME=$(basename $0) 11 | JAIL="/tmp/mimixbox/jail" 12 | source ${ROOT_DIR}/scripts/libshell.sh 13 | 14 | function isDebian() { 15 | if [ ! -f /etc/debian_version ]; then 16 | errMsg "This script can only be used with Debian-based distributions." 17 | exit 1 18 | fi 19 | } 20 | 21 | function hasDebootstrap() { 22 | which debootstrap > /dev/null 23 | local exit_status="$?" 24 | if [ "${exit_status}" != "0" ]; then 25 | errMsg "This script use debootstrap command." 26 | errMsg "[How to install]" 27 | errMsg " $ sudo apt install debootstrap" 28 | exit 1 29 | fi 30 | } 31 | 32 | function deleteJailIfNeeded() { 33 | if [ -e ${JAIL} ]; then 34 | sudo rm -rf ${JAIL} 35 | fi 36 | } 37 | 38 | function mkJail() { 39 | sudo debootstrap bullseye ${JAIL} http://deb.debian.org/debian 40 | } 41 | 42 | function cpMimixboxIfNeeded() { 43 | if [ -f ${ROOT_DIR}/mimixbox ]; then 44 | cp ${ROOT_DIR}/mimixbox ${JAIL}/usr/bin/. 45 | fi 46 | } 47 | 48 | isDebian 49 | hasDebootstrap 50 | IS_ROOT=$(isRoot) 51 | if [ "$IS_ROOT" = "1" ]; then 52 | errMsg "You are not root user." 53 | exit 1 54 | fi 55 | deleteJailIfNeeded 56 | mkJail 57 | cpMimixboxIfNeeded -------------------------------------------------------------------------------- /scripts/mkManpages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ROOT_DIR=$(git rev-parse --show-toplevel) 3 | MAN_DIR="${ROOT_DIR}/docs/man" 4 | MAN_MD=$(find ${MAN_DIR} -name "*.md") 5 | 6 | for i in ${MAN_MD} 7 | do 8 | dir=$(dirname $i) 9 | base_with_ext=$(basename $i) 10 | base="${base_with_ext%.*}" 11 | 12 | # make man p(e.g. csv.1.md -> csv.1 -> cav.1.gz) 13 | echo "Make man-page: $dir/$base" 14 | pandoc $i -s -t man > $dir/$base 15 | echo "Gzip man-page: $dir/${base}.gz" 16 | gzip -f $dir/$base 17 | done -------------------------------------------------------------------------------- /test/it/.shellspec: -------------------------------------------------------------------------------- 1 | --require spec_helper 2 | 3 | ## Default kcov (coverage) options 4 | # --kcov-options "--include-path=. --path-strip-level=1" 5 | # --kcov-options "--include-pattern=.sh" 6 | # --kcov-options "--exclude-pattern=/.shellspec,/spec/,/coverage/,/report/" 7 | 8 | ## Example: Include script "myprog" with no extension 9 | # --kcov-options "--include-pattern=.sh,myprog" 10 | 11 | ## Example: Only specified files/directories 12 | # --kcov-options "--include-pattern=myprog,/lib/" 13 | -------------------------------------------------------------------------------- /test/it/fileutils/cp_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/cp 2 | export DIR_IN_TEST_DIR=/tmp/mimixbox/it/cp/inner 3 | export TEST_DIR2=/tmp/mimixbox/it/cp2 4 | export TEST_FILE=/tmp/mimixbox/it/cp/1.txt 5 | export TEST_FILE2=/tmp/mimixbox/it/cp/2.txt 6 | export TEST_FILE3=/tmp/mimixbox/it/cp/3.txt 7 | export TEST_FILE_INNER=${DIR_IN_TEST_DIR}/inner.txt 8 | 9 | Setup() { 10 | mkdir -p ${TEST_DIR} 11 | mkdir -p ${TEST_DIR2} 12 | mkdir -p ${DIR_IN_TEST_DIR} 13 | touch ${TEST_FILE} 14 | touch ${TEST_FILE2} 15 | touch ${TEST_FILE3} 16 | touch ${TEST_FILE_INNER} 17 | } 18 | 19 | Cleanup() { 20 | rm -rf ${TEST_DIR} 21 | rm -rf ${TEST_DIR2} 22 | } 23 | 24 | TestCopyOneFile() { 25 | cp ${TEST_FILE} ${TEST_DIR}/cp.txt 26 | ls ${TEST_DIR}/cp.txt 27 | } 28 | 29 | TestCopyOneFileStatus() { 30 | cp ${TEST_FILE} ${TEST_DIR}/cp.txt 31 | } 32 | 33 | TestCopyOndDirWithRecursiveOption() { 34 | cp -r ${TEST_DIR} ${TEST_DIR2} 35 | ls ${TEST_DIR2} 36 | ls ${TEST_DIR2}/cp 37 | } 38 | 39 | TestCopyOndDirWithRecursiveOptionStatus() { 40 | cp -r ${TEST_DIR} ${TEST_DIR2} 41 | } 42 | 43 | 44 | TestCopySrcAddDistAreSame() { 45 | cp -r ${TEST_DIR} ${TEST_DIR} 46 | ls ${TEST_DIR} 47 | } 48 | 49 | TestCopySrcAddDistAreSameStatus() { 50 | cp -r ${TEST_DIR} ${TEST_DIR} 51 | } 52 | 53 | TestCopyThreeFileAtSameTime() { 54 | cp ${TEST_FILE} ${TEST_FILE2} ${TEST_FILE3} ${TEST_DIR2} 55 | ls ${TEST_DIR2} 56 | } 57 | 58 | TestCopyThreeFileAtSameTimeStatus() { 59 | cp ${TEST_FILE} ${TEST_FILE2} ${TEST_FILE3} ${TEST_DIR2} 60 | } 61 | 62 | TestCopyDirctoryWithoutRecursiveOption() { 63 | cp ${TEST_DIR} ${TEST_DIR2} 64 | ls ${TEST_DIR2} 65 | } 66 | 67 | TestCopyDirctoryWithoutRecursiveOptionStatus() { 68 | cp ${TEST_DIR} ${TEST_DIR2} 69 | } 70 | 71 | TestCopyDirectoryAtRoot() { 72 | cp -r ${TEST_DIR} / 73 | } -------------------------------------------------------------------------------- /test/it/fileutils/mkdir_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/mkdir 2 | 3 | Setup() { 4 | mkdir -p ${TEST_DIR} 5 | } 6 | 7 | Cleanup() { 8 | rm -rf ${TEST_DIR} 9 | } 10 | 11 | TestMkdirSingle() { 12 | mkdir ${TEST_DIR}/single 13 | ls ${TEST_DIR} 14 | } 15 | 16 | TestMkdirSingleStatus() { 17 | mkdir ${TEST_DIR}/single 18 | } 19 | 20 | TestMkdirThreeDirectory() { 21 | mkdir ${TEST_DIR}/1 ${TEST_DIR}/2 ${TEST_DIR}/3 22 | ls ${TEST_DIR} 23 | } 24 | 25 | TestMkdirThreeDirectoryStatus() { 26 | mkdir ${TEST_DIR}/1 ${TEST_DIR}/2 ${TEST_DIR}/3 27 | } 28 | 29 | TestMkdirParent() { 30 | mkdir -p ${TEST_DIR}/parents/child 31 | ls ${TEST_DIR}/parents/ 32 | } 33 | 34 | TestMkdirParentStatus() { 35 | mkdir -p ${TEST_DIR}/parents/child 36 | } 37 | 38 | TestMkdirFromPipe() { 39 | echo "${TEST_DIR}/pipe" | xargs mkdir 40 | ls ${TEST_DIR} 41 | } 42 | 43 | TestMkdirFromPipeStatus() { 44 | echo "${TEST_DIR}/pipe" | xargs mkdir 45 | } 46 | 47 | TestMkdirNoArg() { 48 | mkdir 49 | } 50 | 51 | TestMkdirNoArgWithParentsOption() { 52 | mkdir -p 53 | } 54 | 55 | TestMkdirThreeDirAndOneIsFail() { 56 | mkdir ${TEST_DIR}/1 /mkdir/2 ${TEST_DIR}/3 57 | ls ${TEST_DIR}/ 58 | } 59 | 60 | TestMkdirThreeDirAndOneIsFailStatus() { 61 | mkdir ${TEST_DIR}/1 /mkdir/2 ${TEST_DIR}/3 62 | } -------------------------------------------------------------------------------- /test/it/fileutils/mkfifo_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/mkfifo 2 | export TEST_FILE1=${TEST_DIR}/1 3 | export TEST_FILE2=${TEST_DIR}/2 4 | export TEST_FILE3=${TEST_DIR}/3 5 | 6 | Setup() { 7 | mkdir -p ${TEST_DIR} 8 | chmod 775 ${TEST_DIR} 9 | } 10 | 11 | Cleanup() { 12 | rm -rf ${TEST_DIR} 13 | } 14 | 15 | TestMkfifoOneFifo() { 16 | mkfifo ${TEST_FILE1} 17 | ls -al ${TEST_FILE1} | cut -f 1 -d " " 18 | } 19 | 20 | TestMkfifoOneFileStatus() { 21 | mkfifo ${TEST_FILE1} 22 | } 23 | 24 | TestMkfifoThreeFifo() { 25 | mkfifo ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 26 | ls -al ${TEST_FILE1} | cut -f 1 -d " " 27 | ls -al ${TEST_FILE2} | cut -f 1 -d " " 28 | ls -al ${TEST_FILE3} | cut -f 1 -d " " 29 | } 30 | 31 | TestMkfifoThreeFifoStatus() { 32 | mkfifo ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 33 | } 34 | 35 | TestMkfifoNoExistPath() { 36 | mkfifo /no_exist_path/fifo 37 | } 38 | 39 | TestMkfifoAlreadyExistSameName() { 40 | mkfifo ${TEST_FILE1} 41 | mkfifo ${TEST_FILE1} 42 | } 43 | 44 | TestMkfifoThreeFileAndCreateOneFileFailed() { 45 | mkfifo ${TEST_FILE1} /no_exist_path/fifo ${TEST_FILE3} 46 | ls ${TEST_DIR} 47 | } 48 | 49 | TestMkfifoThreeFileAndCreateOneFileFailedStatus() { 50 | mkfifo ${TEST_FILE1} /no_exist_path/fifo ${TEST_FILE3} 51 | } -------------------------------------------------------------------------------- /test/it/fileutils/mv_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/mv 2 | export DIR_IN_TEST_DIR=/tmp/mimixbox/it/mv/inner 3 | export TEST_DIR2=/tmp/mimixbox/it/mv2 4 | export TEST_DIR3=/tmp/mimixbox/it/mv3 5 | export TEST_DIR4=/tmp/mimixbox/it/mv4 6 | export TEST_FILE=/tmp/mimixbox/it/mv/1.txt 7 | export TEST_FILE2=/tmp/mimixbox/it/mv/2.txt 8 | export TEST_FILE3=/tmp/mimixbox/it/mv/3.txt 9 | export TEST_FILE_INNER=${DIR_IN_TEST_DIR}/inner.txt 10 | 11 | Setup() { 12 | mkdir -p ${TEST_DIR} 13 | mkdir -p ${TEST_DIR2} 14 | mkdir -p ${TEST_DIR3} 15 | mkdir -p ${TEST_DIR4} 16 | mkdir -p ${DIR_IN_TEST_DIR} 17 | touch ${TEST_FILE} 18 | touch ${TEST_FILE2} 19 | touch ${TEST_FILE3} 20 | touch ${TEST_FILE_INNER} 21 | } 22 | 23 | Cleanup() { 24 | rm -rf /tmp/mimixbox 25 | } 26 | 27 | TestMvRename() { 28 | mv ${TEST_FILE} ${TEST_DIR}/rename.txt 29 | ls ${TEST_DIR}/rename.txt 30 | } 31 | 32 | TestMvRenameStatus() { 33 | mv ${TEST_FILE} ${TEST_DIR}/rename.txt 34 | } 35 | 36 | TestMvMoveFile() { 37 | mv ${TEST_FILE} ${DIR_IN_TEST_DIR} 38 | ls ${DIR_IN_TEST_DIR} 39 | } 40 | 41 | TestMvMoveFileStatus() { 42 | mv ${TEST_FILE} ${DIR_IN_TEST_DIR} 43 | } 44 | 45 | TestMvThreeFileAtSameTime() { 46 | mv ${TEST_FILE} ${TEST_FILE2} ${TEST_FILE3} ${DIR_IN_TEST_DIR} 47 | ls ${DIR_IN_TEST_DIR} 48 | } 49 | 50 | TestMvThreeFileAtSameTimeStatus() { 51 | mv ${TEST_FILE} ${TEST_FILE2} ${TEST_FILE3} ${DIR_IN_TEST_DIR} 52 | } 53 | 54 | TestMvThreeFileAndOneOfThreeFail() { 55 | mv ${TEST_FILE} ${TEST_DIR}/no_exist_file ${TEST_FILE3} ${DIR_IN_TEST_DIR} 56 | ls ${DIR_IN_TEST_DIR} 57 | } 58 | 59 | TestMvThreeFileAndOneOfThreeFailStatus() { 60 | mv ${TEST_FILE} ${TEST_DIR}/no_exist_file ${TEST_FILE3} ${DIR_IN_TEST_DIR} 61 | } 62 | 63 | TestMvDirToDir() { 64 | mv ${TEST_DIR2} ${TEST_DIR} 65 | ls ${TEST_DIR} 66 | } 67 | 68 | TestMvDirToDirStatus() { 69 | mv ${TEST_DIR2} ${TEST_DIR} 70 | } 71 | 72 | TestMvThreeDirs() { 73 | mv ${TEST_DIR2} ${TEST_DIR3} ${TEST_DIR4} ${TEST_DIR} 74 | ls ${TEST_DIR} 75 | } 76 | 77 | TestMvThreeStatus() { 78 | mv ${TEST_DIR2} ${TEST_DIR3} ${TEST_DIR4} ${TEST_DIR} 79 | } 80 | 81 | TestMvThreeDirsAndOneOfThreeFail() { 82 | mv ${TEST_DIR2} ${TEST_DIR}/no_exist_dir ${TEST_DIR4} ${DIR_IN_TEST_DIR} 83 | ls ${DIR_IN_TEST_DIR} 84 | } 85 | 86 | TestMvThreeDirsAndOneOfThreeFailStatus() { 87 | mv ${TEST_DIR2} ${TEST_DIR}/no_exist_dir ${TEST_DIR4} ${DIR_IN_TEST_DIR} 88 | } 89 | 90 | TestMvFileAtSampePath() { 91 | mv ${TEST_FILE} ${TEST_FILE} 92 | } 93 | 94 | TestMvSrcAndDestIsSameName() { 95 | touch ${TEST_DIR}/inner.txt 96 | mv ${TEST_DIR}/inner.txt ${TEST_FILE_INNER} 97 | ls ${TEST_DIR} 98 | ls ${DIR_IN_TEST_DIR} 99 | } 100 | 101 | TestMvSrcAndDestIsSameNameStatus() { 102 | touch ${TEST_DIR}/inner.txt 103 | mv ${TEST_DIR}/inner.txt ${TEST_FILE_INNER} 104 | } 105 | 106 | TestMvSrcAndDestIsSameNameWithBackupOpt() { 107 | touch ${TEST_DIR}/inner.txt 108 | mv -b ${TEST_DIR}/inner.txt ${DIR_IN_TEST_DIR} 109 | ls ${DIR_IN_TEST_DIR} 110 | } 111 | 112 | TestMvSrcAndDestIsSameNameWithBackupOptStatus() { 113 | touch ${TEST_DIR}/inner.txt 114 | mv -b ${TEST_DIR}/inner.txt ${DIR_IN_TEST_DIR} 115 | } -------------------------------------------------------------------------------- /test/it/fileutils/rm_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/rm 2 | export DIR_IN_TEST_DIR=${TEST_DIR}/inner 3 | export TEST_FILE1=${TEST_DIR}/1.txt 4 | export TEST_FILE2=${TEST_DIR}/2.txt 5 | export TEST_FILE3=${TEST_DIR}/3.txt 6 | export TEST_FILE_INNER=${DIR_IN_TEST_DIR}/inner.txt 7 | 8 | Setup() { 9 | mkdir -p ${TEST_DIR} 10 | mkdir -p ${DIR_IN_TEST_DIR} 11 | touch ${TEST_FILE1} 12 | touch ${TEST_FILE2} 13 | touch ${TEST_FILE3} 14 | touch ${TEST_FILE_INNER} 15 | } 16 | 17 | Cleanup() { 18 | rm -rf ${TEST_DIR} 19 | } 20 | 21 | TestRmOneFile() { 22 | rm ${TEST_FILE1} 23 | ls ${TEST_DIR} 24 | } 25 | 26 | TestRmOneStatus() { 27 | rm ${TEST_FILE1} 28 | } 29 | 30 | TestRmFileWithWildcard() { 31 | rm ${TEST_DIR}/*.txt 32 | ls ${TEST_DIR} 33 | } 34 | 35 | TestRmFileWithWildcardStatus() { 36 | rm ${TEST_DIR}/*.txt 37 | } 38 | 39 | TestRmThreeFileAtSameTime() { 40 | rm ${TEST_DIR}/1.txt ${TEST_DIR}/2.txt ${TEST_DIR}/3.txt 41 | ls ${TEST_DIR} 42 | } 43 | 44 | TestRmThreeFileAtSameTimeStatus() { 45 | rm ${TEST_DIR}/1.txt ${TEST_DIR}/2.txt ${TEST_DIR}/3.txt 46 | } 47 | 48 | TestRmThreeFileWithNoExistFile() { 49 | rm ${TEST_DIR}/1.txt ${TEST_DIR}/no_exist_file.txt ${TEST_DIR}/3.txt 50 | ls ${TEST_DIR} 51 | } 52 | 53 | TestRmThreeFileWithNoExistFileStatus() { 54 | rm ${TEST_DIR}/1.txt ${TEST_DIR}/no_exist_file.txt ${TEST_DIR}/3.txt 55 | } 56 | 57 | TestRmDirWithoutRecursiveOption() { 58 | rm ${TEST_DIR} 59 | ls ${TEST_DIR} 60 | } 61 | 62 | TestRmDirWithoutRecursiveOptionStatus() { 63 | rm ${TEST_DIR} 64 | } 65 | 66 | TestRmDirWithRecursiveOption() { 67 | rm -rf ${TEST_DIR} 68 | ls /tmp/mimixbox/it 69 | } 70 | 71 | TestRmDirWithRecursiveOptionStatus() { 72 | rm -rf ${TEST_DIR} 73 | } -------------------------------------------------------------------------------- /test/it/fileutils/touch_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/touch 2 | 3 | Setup() { 4 | mkdir -p ${TEST_DIR} 5 | } 6 | 7 | Cleanup() { 8 | rm -rf ${TEST_DIR} 9 | } 10 | 11 | TestTouchOneFile() { 12 | touch ${TEST_DIR}/touch.txt 13 | ls ${TEST_DIR}/touch.txt 14 | } 15 | 16 | TestTouchOneFileStatus() { 17 | touch ${TEST_DIR}/touch.txt 18 | } 19 | 20 | TestTouchThreeFileAtSameTime() { 21 | touch ${TEST_DIR}/1.txt ${TEST_DIR}/2.txt ${TEST_DIR}/3.txt 22 | ls ${TEST_DIR}/1.txt 23 | ls ${TEST_DIR}/2.txt 24 | ls ${TEST_DIR}/3.txt 25 | } 26 | 27 | TestTouchThreeFileAtSameTimeStatus() { 28 | touch ${TEST_DIR}/1.txt ${TEST_DIR}/2.txt ${TEST_DIR}/3.txt 29 | } 30 | 31 | TestTouchThreeFileAndNotMakeOneFile() { 32 | touch ${TEST_DIR}/1.txt /touch/2.txt ${TEST_DIR}/3.txt 33 | ls ${TEST_DIR}/1.txt 34 | ls ${TEST_DIR}/3.txt 35 | } 36 | 37 | TestTouchThreeFileAndNotMakeOneFile() { 38 | touch ${TEST_DIR}/1.txt /touch/2.txt ${TEST_DIR}/3.txt 39 | ls ${TEST_DIR}/1.txt 40 | ls ${TEST_DIR}/3.txt 41 | } 42 | 43 | TestTouchThreeFileAndNotMakeOneFileStatus() { 44 | touch ${TEST_DIR}/1.txt /touch/2.txt ${TEST_DIR}/3.txt 45 | } -------------------------------------------------------------------------------- /test/it/games/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nao1215/mimixbox/063fffce9c5b7165e5d8315711dd3fc74f22158e/test/it/games/.gitkeep -------------------------------------------------------------------------------- /test/it/jokeutils/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nao1215/mimixbox/063fffce9c5b7165e5d8315711dd3fc74f22158e/test/it/jokeutils/.gitkeep -------------------------------------------------------------------------------- /test/it/shellutils/basename_test.sh: -------------------------------------------------------------------------------- 1 | TestBasenameFilenameWithExt() { 2 | basename "/home/nao/test.txt" 3 | } 4 | 5 | TestBasenameFilenameWithoutExt() { 6 | basename "/home/nao/test" 7 | } 8 | 9 | TestBasenameHiddenFile() { 10 | basename "/home/nao/.test" 11 | } 12 | 13 | TestBasenameEndsWithThrash() { 14 | basename "/home/nao/" 15 | } 16 | 17 | TestBasenameNoOpertand() { 18 | basename 19 | } 20 | 21 | TestBasenameRoot() { 22 | basename "/" 23 | } 24 | 25 | TestBasenameEmptyString() { 26 | basename "" 27 | } 28 | 29 | TestBasenameWithThreeArg() { 30 | basename /bin/basename /home/nao /home 31 | } 32 | 33 | TestBasenameThreeArgWithMultipleOption() { 34 | basename -a /bin/basename /home/nao /home 35 | } 36 | 37 | TestBasenameThreeArgWithMultipleAndZeroOption() { 38 | basename -a -z /bin/basename /home/nao /home 39 | } 40 | 41 | TestBasenameWithSuffixOption() { 42 | basename -s .txt /home/nao/test.txt 43 | } 44 | 45 | TestBasenameFilenameWithEnvVar() { 46 | export TEST_DIR="/aaa/bbb/ccc" 47 | basename $TEST_DIR/ddd.txt 48 | } 49 | -------------------------------------------------------------------------------- /test/it/shellutils/dirname_test.sh: -------------------------------------------------------------------------------- 1 | TestDirnameAbsFilePath() { 2 | dirname "/home/nao/test.txt" 3 | } 4 | 5 | TestDirnameFilenameWithoutExt() { 6 | dirname "/home/nao/test" 7 | } 8 | 9 | TestDirnameHiddenFile() { 10 | dirname "/home/nao/.test" 11 | } 12 | 13 | TestDirnameEndsWithThrash() { 14 | dirname "/home/nao/" 15 | } 16 | 17 | TestDirnameNoOpertand() { 18 | dirname 19 | } 20 | 21 | TestDirnameRoot() { 22 | dirname "/" 23 | } 24 | 25 | TestDirnameEmptyString() { 26 | dirname "" 27 | } 28 | 29 | TestDirnameWithThreeArg() { 30 | dirname /bin/dirname /home/nao /home 31 | } 32 | 33 | TestDirnameThreeArgWithZeroOption() { 34 | dirname -z /bin/dirname /home/nao /home 35 | } 36 | 37 | TestDirnameFilenameWithEnvVar() { 38 | export TEST_DIR="/aaa/bbb/ccc" 39 | dirname $TEST_DIR/ddd.txt 40 | } 41 | -------------------------------------------------------------------------------- /test/it/shellutils/echo_test.sh: -------------------------------------------------------------------------------- 1 | TestEchoNormal() { 2 | echo "Hello World!" 3 | } 4 | 5 | TestEchoVariable() { 6 | echo "Hello $1" 7 | } 8 | 9 | TestEchoEnvVariable() { 10 | export TEST_ENV="TEST_ENV_VAR" 11 | echo ${TEST_ENV} 12 | } 13 | 14 | TestEchoPipeWithargs() { 15 | echo "pipe" | xargs echo 16 | } 17 | 18 | TestEchoNoArg() { 19 | echo 20 | } 21 | 22 | TestEchoRedirect() { 23 | echo "MimixBox" > /tmp/it/mimixbox/echo.txt 24 | cat /tmp/it/mimixbox/echo.txt 25 | } 26 | -------------------------------------------------------------------------------- /test/it/shellutils/false_test.sh: -------------------------------------------------------------------------------- 1 | TestFalse() { 2 | false 3 | } -------------------------------------------------------------------------------- /test/it/shellutils/true_test.sh: -------------------------------------------------------------------------------- 1 | TestTrue() { 2 | true 3 | } -------------------------------------------------------------------------------- /test/it/shellutils/which_test.sh: -------------------------------------------------------------------------------- 1 | TestWhichExistBinary() { 2 | which mimixbox 3 | } 4 | 5 | TestWhichNoExistBinary() { 6 | which no_exist_binary 7 | } 8 | 9 | TestWhichThreeBinary() { 10 | which mimixbox cat tac 11 | } 12 | 13 | TestWhichOneOfThreeBinNotExist() { 14 | which mimixbox not_exist_binary tac 15 | } 16 | 17 | TestWhichWithoutOperand() { 18 | which 19 | } 20 | 21 | TestWhichDataFromPipe() { 22 | echo "test" | which 23 | } -------------------------------------------------------------------------------- /test/it/spec/dirname_spec.sh: -------------------------------------------------------------------------------- 1 | Describe 'Get dirname from /home/nao/test.txt' 2 | Include shellutils/dirname_test.sh 3 | 4 | It 'print /home/nao' 5 | When call TestDirnameAbsFilePath 6 | The output should equal "/home/nao" 7 | The status should be success 8 | End 9 | End 10 | 11 | Describe 'Get dirname without extension' 12 | Include shellutils/dirname_test.sh 13 | 14 | It 'print test' 15 | When call TestDirnameFilenameWithoutExt 16 | The output should equal "/home/nao" 17 | The status should be success 18 | End 19 | End 20 | 21 | Describe 'Get dirname for hidden directory' 22 | Include shellutils/dirname_test.sh 23 | 24 | It 'print /home/nao/.test' 25 | When call TestDirnameHiddenFile 26 | The output should equal "/home/nao" 27 | The status should be success 28 | End 29 | End 30 | 31 | Describe 'Get dirname without operand' 32 | Include shellutils/dirname_test.sh 33 | 34 | It 'print error' 35 | When call TestDirnameNoOpertand 36 | The error should equal "dirname: no operand" 37 | The status should be failure 38 | End 39 | End 40 | 41 | Describe 'Get dirname for root directory' 42 | Include shellutils/dirname_test.sh 43 | 44 | It 'print /' 45 | When call TestDirnameRoot 46 | The output should equal "/" 47 | The status should be success 48 | End 49 | End 50 | 51 | Describe 'Get dirname for empty string' 52 | Include shellutils/dirname_test.sh 53 | 54 | It 'print "."' 55 | When call TestDirnameEmptyString 56 | The output should equal "." 57 | The status should be success 58 | End 59 | End 60 | 61 | Describe 'Get dirname for three arguments' 62 | Include shellutils/dirname_test.sh 63 | 64 | result() { %text 65 | #|/bin 66 | #|/home 67 | #|/ 68 | } 69 | 70 | It 'print "/bin" "/home" "/" with line feed' 71 | When call TestDirnameWithThreeArg 72 | The output should equal "$(result)" 73 | The status should be success 74 | End 75 | End 76 | 77 | Describe 'Get dirname for three arguments with zero option' 78 | Include shellutils/dirname_test.sh 79 | 80 | It 'print "/bin" "/home" "/" without line feed' 81 | When call TestDirnameThreeArgWithZeroOption 82 | The output should equal "/bin/home/" 83 | The status should be success 84 | End 85 | End 86 | 87 | Describe 'Get dirname with environment variable' 88 | Include shellutils/dirname_test.sh 89 | 90 | It 'print /aaa/bbb/ccc' 91 | When call TestDirnameFilenameWithEnvVar 92 | The output should equal "/aaa/bbb/ccc" 93 | The status should be success 94 | End 95 | End -------------------------------------------------------------------------------- /test/it/spec/echo_spec.sh: -------------------------------------------------------------------------------- 1 | Describe 'Echo text without variable' 2 | Include shellutils/echo_test.sh 3 | It 'says Hello World!' 4 | When call TestEchoNormal 5 | The output should equal 'Hello World!' 6 | The status should be success 7 | End 8 | End 9 | 10 | Describe 'Echo text with variable' 11 | Include shellutils/echo_test.sh 12 | It 'says Hello World! $1=World!' 13 | When call TestEchoNormal "World!" 14 | The output should equal 'Hello World!' 15 | The status should be success 16 | End 17 | End 18 | 19 | Describe 'Echo text with environment variable' 20 | Include shellutils/echo_test.sh 21 | It 'says ${TEST_ENV}=TEST_ENV_VAR' 22 | When call TestEchoEnvVariable 23 | The output should equal 'TEST_ENV_VAR' 24 | The status should be success 25 | End 26 | End 27 | 28 | Describe 'Echo pipe data with xargs command' 29 | Include shellutils/echo_test.sh 30 | It 'says pipe' 31 | When call TestEchoPipeWithargs 32 | The output should equal 'pipe' 33 | The status should be success 34 | End 35 | End 36 | 37 | Describe 'Echo with no arguments' 38 | Include shellutils/echo_test.sh 39 | It 'says nothing' 40 | When call TestEchoNoArg 41 | The output should equal '' 42 | The status should be success 43 | End 44 | End 45 | 46 | Describe 'Echo redirect to file.' 47 | Include shellutils/echo_test.sh 48 | setup() { mkdir -p /tmp/it/mimixbox; } 49 | cleanup() { rm /tmp/it/mimixbox/echo.txt; } 50 | BeforeEach 'setup' 51 | AfterEach 'cleanup' 52 | 53 | It 'redirect data to file and show it.' 54 | When call TestEchoRedirect 55 | The output should equal 'MimixBox' 56 | The status should be success 57 | End 58 | End 59 | -------------------------------------------------------------------------------- /test/it/spec/false_spec.sh: -------------------------------------------------------------------------------- 1 | Describe 'False is False' 2 | Include shellutils/false_test.sh 3 | It 'print nothing, and exit-status is 1' 4 | When call TestFalse 5 | The output should equal '' 6 | The status should be failure 7 | End 8 | End -------------------------------------------------------------------------------- /test/it/spec/md5sum_spec.sh: -------------------------------------------------------------------------------- 1 | Describe 'Get md5sum of one file' 2 | Include textutils/md5sum_test.sh 3 | BeforeEach 'Setup' 4 | AfterEach 'Cleanup' 5 | It 'says d0d8ffef81b3c7160ac655d5939548c5' 6 | When call TestMd5sumOneFile 7 | The output should equal 'd0d8ffef81b3c7160ac655d5939548c5 /tmp/mimixbox/it/md5sum/1.txt' 8 | The status should be success 9 | End 10 | End 11 | 12 | Describe 'Can not get md5sum of one directory' 13 | Include textutils/md5sum_test.sh 14 | BeforeEach 'Setup' 15 | AfterEach 'Cleanup' 16 | It 'says "It is directory"' 17 | When call TestMd5sumOneDirectory 18 | The error should equal 'md5sum: /tmp/mimixbox/it/md5sum: It is directory' 19 | The status should be failure 20 | End 21 | End 22 | 23 | Describe 'Can not get md5sum of not exist file' 24 | Include textutils/md5sum_test.sh 25 | BeforeEach 'Setup' 26 | AfterEach 'Cleanup' 27 | It 'says "No such file or directory"' 28 | When call TestMd5sumNotExistFile 29 | The error should equal 'md5sum: /not_exist_file: No such file or directory' 30 | The status should be failure 31 | End 32 | End 33 | 34 | Describe 'Get md5sum of three files' 35 | Include textutils/md5sum_test.sh 36 | BeforeEach 'Setup' 37 | AfterEach 'Cleanup' 38 | 39 | result() { %text 40 | #|d0d8ffef81b3c7160ac655d5939548c5 /tmp/mimixbox/it/md5sum/1.txt 41 | #|07e280ad4bd77b9321f0ce3386775019 /tmp/mimixbox/it/md5sum/2.txt 42 | #|15e924f84517598e828f49dc85765bc5 /tmp/mimixbox/it/md5sum/3.txt 43 | } 44 | 45 | It 'show checksum of three file' 46 | When call TestMd5sumThreeFiles 47 | The output should equal "$(result)" 48 | The status should be success 49 | End 50 | End 51 | 52 | Describe 'Check md5sum with --check option' 53 | Include textutils/md5sum_test.sh 54 | BeforeEach 'Setup' 55 | AfterEach 'Cleanup' 56 | 57 | result() { %text 58 | #|/tmp/mimixbox/it/md5sum/1.txt: OK 59 | #|/tmp/mimixbox/it/md5sum/2.txt: OK 60 | #|/tmp/mimixbox/it/md5sum/3.txt: OK 61 | } 62 | 63 | It 'show all files "OK"' 64 | When call TestMd5sumWithCheckOption 65 | The output should equal "$(result)" 66 | The status should be success 67 | End 68 | End 69 | 70 | Describe 'Get md5sum for pipe data' 71 | Include textutils/md5sum_test.sh 72 | BeforeEach 'Setup' 73 | AfterEach 'Cleanup' 74 | 75 | It 'show checksum' 76 | When call TestMd5sumDataFromPipe 77 | The output should equal "d8e8fca2dc0f896fd7cb4cb0031ba249 -" 78 | The status should be success 79 | End 80 | End 81 | 82 | Describe 'Get md5sum for pipe data and file at same time' 83 | Include textutils/md5sum_test.sh 84 | BeforeEach 'Setup' 85 | AfterEach 'Cleanup' 86 | 87 | It 'only show checksum of file.' 88 | When call TestMd5sumFileAndDataFromPipeAtSameTime 89 | The output should equal "d0d8ffef81b3c7160ac655d5939548c5 /tmp/mimixbox/it/md5sum/1.txt" 90 | The status should be success 91 | End 92 | End -------------------------------------------------------------------------------- /test/it/spec/mkfifo_spec.sh: -------------------------------------------------------------------------------- 1 | Describe 'Make one named pipe' 2 | Include fileutils/mkfifo_test.sh 3 | BeforeEach 'Setup' 4 | AfterEach 'Cleanup' 5 | It 'make named pipe by prw-rw-r--' 6 | When call TestMkfifoOneFifo 7 | The output should equal 'prw-r--r--' 8 | End 9 | End 10 | 11 | Describe 'Check status after making one named pipe' 12 | Include fileutils/mkfifo_test.sh 13 | BeforeEach 'Setup' 14 | AfterEach 'Cleanup' 15 | It 'status success' 16 | When call TestMkfifoOneFileStatus 17 | The status should be success 18 | End 19 | End 20 | 21 | Describe 'Make three named pipe' 22 | Include fileutils/mkfifo_test.sh 23 | BeforeEach 'Setup' 24 | AfterEach 'Cleanup' 25 | 26 | result() { %text 27 | #|prw-r--r-- 28 | #|prw-r--r-- 29 | #|prw-r--r-- 30 | } 31 | 32 | It 'make three named pipe by prw-rw-r--' 33 | When call TestMkfifoThreeFifo 34 | The output should equal "$(result)" 35 | End 36 | End 37 | 38 | Describe 'Check status after making three named pipe' 39 | Include fileutils/mkfifo_test.sh 40 | BeforeEach 'Setup' 41 | AfterEach 'Cleanup' 42 | It 'status success' 43 | When call TestMkfifoThreeFifoStatus 44 | The status should be success 45 | End 46 | End 47 | 48 | Describe 'Make named pipe at no exist path' 49 | Include fileutils/mkfifo_test.sh 50 | BeforeEach 'Setup' 51 | AfterEach 'Cleanup' 52 | 53 | It 'print "no such file or direcroty"' 54 | When call TestMkfifoNoExistPath 55 | The error should equal 'mkfifo: /no_exist_path/fifo: no such file or directory' 56 | The status should be failure 57 | End 58 | End 59 | 60 | Describe 'If the same name file already exists, ' 61 | Include fileutils/mkfifo_test.sh 62 | BeforeEach 'Setup' 63 | AfterEach 'Cleanup' 64 | 65 | It 'print "already exist"' 66 | When call TestMkfifoAlreadyExistSameName 67 | The error should equal "mkfifo: can't make /tmp/mimixbox/it/mkfifo/1: already exist" 68 | The status should be failure 69 | End 70 | End 71 | 72 | Describe 'If mkfifo fail to create one file while creating three files,' 73 | Include fileutils/mkfifo_test.sh 74 | BeforeEach 'Setup' 75 | AfterEach 'Cleanup' 76 | 77 | result() { %text 78 | #|1 79 | #|3 80 | } 81 | 82 | It 'make two named pipe' 83 | When call TestMkfifoThreeFileAndCreateOneFileFailed 84 | The output should equal "$(result)" 85 | The error should equal 'mkfifo: /no_exist_path/fifo: no such file or directory' 86 | The status should be success 87 | End 88 | End 89 | 90 | Describe 'Check status If mkfifo fail to create one while creating three files,' 91 | Include fileutils/mkfifo_test.sh 92 | BeforeEach 'Setup' 93 | AfterEach 'Cleanup' 94 | It 'status failure' 95 | When call TestMkfifoThreeFileAndCreateOneFileFailedStatus 96 | The error should equal 'mkfifo: /no_exist_path/fifo: no such file or directory' 97 | The status should be failure 98 | End 99 | End 100 | -------------------------------------------------------------------------------- /test/it/spec/nl_spec.sh: -------------------------------------------------------------------------------- 1 | Describe 'Show text file with number line' 2 | Include textutils/nl_test.sh 3 | BeforeEach 'Setup' 4 | AfterEach 'Cleanup' 5 | 6 | result() { %text 7 | #| 1 sh 8 | #| 2 ash 9 | #| 3 csh 10 | #| 4 bash 11 | } 12 | It 'show shell family-name wiht number line' 13 | When call TestNlNoArg 14 | The output should equal "$(result)" 15 | The status should be success 16 | End 17 | End 18 | 19 | Describe 'Show text file with number line' 20 | Include textutils/nl_test.sh 21 | BeforeEach 'Setup' 22 | AfterEach 'Cleanup' 23 | 24 | result() { %text 25 | #| 1 /tmp/mimixbox/it/nl.txt 26 | } 27 | It 'show shell family-name wiht number line' 28 | When call TestNlFromPipeData 29 | The output should equal "$(result)" 30 | The status should be success 31 | End 32 | End 33 | 34 | Describe 'If pass filename and pipe-data' 35 | Include textutils/nl_test.sh 36 | BeforeEach 'Setup' 37 | AfterEach 'Cleanup' 38 | 39 | result() { %text 40 | #| 1 sh 41 | #| 2 ash 42 | #| 3 csh 43 | #| 4 bash 44 | } 45 | It 'show only file-data' 46 | When call TestNlOnlyOperandWithPipeData 47 | The output should equal "$(result)" 48 | The status should be success 49 | End 50 | End 51 | 52 | Describe 'Concatenate two file' 53 | Include textutils/nl_test.sh 54 | BeforeEach 'Setup' 55 | AfterEach 'Cleanup' 56 | 57 | result() { %text 58 | #| 1 sh 59 | #| 2 ash 60 | #| 3 csh 61 | #| 4 bash 62 | #| 5 fish 63 | #| 6 zsh 64 | } 65 | It 'show only file-data' 66 | When call TestNlConcatenateTwoFile 67 | The output should equal "$(result)" 68 | The status should be success 69 | End 70 | End 71 | 72 | Describe 'Nl command using heaedoc' 73 | Include textutils/nl_test.sh 74 | BeforeEach 'Setup' 75 | AfterEach 'Cleanup' 76 | 77 | result() { %text 78 | #| 1 fish 79 | #| 2 zsh 80 | #| 3 sh 81 | #| 4 ash 82 | #| 5 csh 83 | #| 6 bash 84 | } 85 | It 'show shell family-name wiht number line' 86 | When call TestNlHeredoc 87 | The output should equal "$(result)" 88 | End 89 | End 90 | 91 | Describe 'Check status after using heaedoc' 92 | Include textutils/nl_test.sh 93 | BeforeEach 'Setup' 94 | AfterEach 'Cleanup' 95 | 96 | result() { %text 97 | #| 1 fish 98 | #| 2 zsh 99 | #| 3 sh 100 | #| 4 ash 101 | #| 5 csh 102 | #| 6 bash 103 | } 104 | It 'show success' 105 | When call TestNlHeredoc 106 | The output should equal "$(result)" 107 | The status should be success 108 | End 109 | End 110 | 111 | Describe 'nl does not exist file.' 112 | Include textutils/nl_test.sh 113 | 114 | It 'show error' 115 | When call TestNlNoOperand 116 | The error should equal "nl: open no_exist_file: no such file or directory" 117 | The status should be failure 118 | End 119 | End -------------------------------------------------------------------------------- /test/it/spec/sha1sum_spec.sh: -------------------------------------------------------------------------------- 1 | Describe 'Get sha1sum of one file' 2 | Include textutils/sha1sum_test.sh 3 | BeforeEach 'Setup' 4 | AfterEach 'Cleanup' 5 | It 'says 9dc2936d38932f9ffc6738cb677e4a8722116070' 6 | When call TestMd5sumOneFile 7 | The output should equal '9dc2936d38932f9ffc6738cb677e4a8722116070 /tmp/mimixbox/it/sha1sum/1.txt' 8 | The status should be success 9 | End 10 | End 11 | 12 | Describe 'Can not get sha1sum of one directory' 13 | Include textutils/sha1sum_test.sh 14 | BeforeEach 'Setup' 15 | AfterEach 'Cleanup' 16 | It 'says "It is directory"' 17 | When call TestMd5sumOneDirectory 18 | The error should equal 'sha1sum: /tmp/mimixbox/it/sha1sum: It is directory' 19 | The status should be failure 20 | End 21 | End 22 | 23 | Describe 'Can not get sha1sum of not exist file' 24 | Include textutils/sha1sum_test.sh 25 | BeforeEach 'Setup' 26 | AfterEach 'Cleanup' 27 | It 'says "No such file or directory"' 28 | When call TestMd5sumNotExistFile 29 | The error should equal 'sha1sum: /not_exist_file: No such file or directory' 30 | The status should be failure 31 | End 32 | End 33 | 34 | Describe 'Get sha1sum of three files' 35 | Include textutils/sha1sum_test.sh 36 | BeforeEach 'Setup' 37 | AfterEach 'Cleanup' 38 | 39 | result() { %text 40 | #|9dc2936d38932f9ffc6738cb677e4a8722116070 /tmp/mimixbox/it/sha1sum/1.txt 41 | #|317e30648976d62fae4662fe4435e6568648e8a7 /tmp/mimixbox/it/sha1sum/2.txt 42 | #|d4e9619d949de0c0182a09757346ad22e80114b3 /tmp/mimixbox/it/sha1sum/3.txt 43 | } 44 | 45 | It 'show checksum of three file' 46 | When call TestMd5sumThreeFiles 47 | The output should equal "$(result)" 48 | The status should be success 49 | End 50 | End 51 | 52 | Describe 'Check sha1sum with --check option' 53 | Include textutils/sha1sum_test.sh 54 | BeforeEach 'Setup' 55 | AfterEach 'Cleanup' 56 | 57 | result() { %text 58 | #|/tmp/mimixbox/it/sha1sum/1.txt: OK 59 | #|/tmp/mimixbox/it/sha1sum/2.txt: OK 60 | #|/tmp/mimixbox/it/sha1sum/3.txt: OK 61 | } 62 | 63 | It 'show all files "OK"' 64 | When call TestMd5sumWithCheckOption 65 | The output should equal "$(result)" 66 | The status should be success 67 | End 68 | End 69 | 70 | Describe 'Get sha1sum for pipe data' 71 | Include textutils/sha1sum_test.sh 72 | BeforeEach 'Setup' 73 | AfterEach 'Cleanup' 74 | 75 | It 'show checksum' 76 | When call TestMd5sumDataFromPipe 77 | The output should equal "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83 -" 78 | The status should be success 79 | End 80 | End 81 | 82 | Describe 'Get sha1sum for pipe data and file at same time' 83 | Include textutils/sha1sum_test.sh 84 | BeforeEach 'Setup' 85 | AfterEach 'Cleanup' 86 | 87 | It 'only show checksum of file.' 88 | When call TestMd5sumFileAndDataFromPipeAtSameTime 89 | The output should equal "9dc2936d38932f9ffc6738cb677e4a8722116070 /tmp/mimixbox/it/sha1sum/1.txt" 90 | The status should be success 91 | End 92 | End -------------------------------------------------------------------------------- /test/it/spec/spec_helper.sh: -------------------------------------------------------------------------------- 1 | # shellcheck shell=sh 2 | 3 | # Defining variables and functions here will affect all specfiles. 4 | # Change shell options inside a function may cause different behavior, 5 | # so it is better to set them here. 6 | # set -eu 7 | 8 | # This callback function will be invoked only once before loading specfiles. 9 | spec_helper_precheck() { 10 | # Available functions: info, warn, error, abort, setenv, unsetenv 11 | # Available variables: VERSION, SHELL_TYPE, SHELL_VERSION 12 | : minimum_version "0.28.1" 13 | } 14 | 15 | # This callback function will be invoked after a specfile has been loaded. 16 | spec_helper_loaded() { 17 | : 18 | } 19 | 20 | # This callback function will be invoked after core modules has been loaded. 21 | spec_helper_configure() { 22 | # Available functions: import, before_each, after_each, before_all, after_all 23 | : import 'support/custom_matcher' 24 | } 25 | -------------------------------------------------------------------------------- /test/it/spec/touch_spec.sh: -------------------------------------------------------------------------------- 1 | Describe 'Touch one file.' 2 | Include fileutils/touch_test.sh 3 | BeforeEach 'Setup' 4 | AfterEach 'Cleanup' 5 | It 'make touch.txt' 6 | When call TestTouchOneFile 7 | The output should equal '/tmp/mimixbox/it/touch/touch.txt' 8 | End 9 | End 10 | 11 | Describe 'Check status after making one file.' 12 | Include fileutils/touch_test.sh 13 | BeforeEach 'Setup' 14 | AfterEach 'Cleanup' 15 | It 'status success' 16 | When call TestTouchOneFileStatus 17 | The status should be success 18 | End 19 | End 20 | 21 | Describe 'Touch three file.' 22 | Include fileutils/touch_test.sh 23 | BeforeEach 'Setup' 24 | AfterEach 'Cleanup' 25 | 26 | result() { %text 27 | #|/tmp/mimixbox/it/touch/1.txt 28 | #|/tmp/mimixbox/it/touch/2.txt 29 | #|/tmp/mimixbox/it/touch/3.txt 30 | } 31 | 32 | It 'make 1.txt 2.txt 3.txt' 33 | When call TestTouchThreeFileAtSameTime 34 | The output should equal "$(result)" 35 | End 36 | End 37 | 38 | Describe 'Check status after making three file.' 39 | Include fileutils/touch_test.sh 40 | BeforeEach 'Setup' 41 | AfterEach 'Cleanup' 42 | 43 | It 'status success' 44 | When call TestTouchThreeFileAtSameTimeStatus 45 | The status should be success 46 | End 47 | End 48 | 49 | Describe 'Touch three file and not make one file' 50 | Include fileutils/touch_test.sh 51 | BeforeEach 'Setup' 52 | AfterEach 'Cleanup' 53 | 54 | result() { %text 55 | #|/tmp/mimixbox/it/touch/1.txt 56 | #|/tmp/mimixbox/it/touch/3.txt 57 | } 58 | 59 | It 'make 1.txt 2.txt 3.txt' 60 | When call TestTouchThreeFileAndNotMakeOneFile 61 | The output should equal "$(result)" 62 | The error should equal "touch: open /touch/2.txt: no such file or directory" 63 | End 64 | End 65 | 66 | Describe 'Check sttus touch three file and not make one file' 67 | Include fileutils/touch_test.sh 68 | BeforeEach 'Setup' 69 | AfterEach 'Cleanup' 70 | 71 | It 'make 1.txt 2.txt 3.txt' 72 | When call TestTouchThreeFileAndNotMakeOneFileStatus 73 | The error should equal "touch: open /touch/2.txt: no such file or directory" 74 | The status should be failure 75 | End 76 | End 77 | -------------------------------------------------------------------------------- /test/it/spec/true_spec.sh: -------------------------------------------------------------------------------- 1 | Describe 'True is True' 2 | Include shellutils/true_test.sh 3 | It 'print nothing, and exit-status is 0' 4 | When call TestTrue 5 | The output should equal '' 6 | The status should be success 7 | End 8 | End -------------------------------------------------------------------------------- /test/it/spec/which_spec.sh: -------------------------------------------------------------------------------- 1 | Describe 'Search mimixbox' 2 | Include shellutils/which_test.sh 3 | It 'print /usr/local/bin/mimixbox' 4 | When call TestWhichExistBinary 5 | The output should equal '/usr/local/bin/mimixbox' 6 | The status should be success 7 | End 8 | End 9 | 10 | Describe 'Search binary that does not exist in system' 11 | Include shellutils/which_test.sh 12 | It 'print nothig' 13 | When call TestWhichNoExistBinary 14 | The output should equal '' 15 | The status should be failure 16 | End 17 | End 18 | 19 | Describe 'Search three binary.' 20 | Include shellutils/which_test.sh 21 | 22 | result() { %text 23 | #|/usr/local/bin/mimixbox 24 | #|/usr/local/bin/cat 25 | #|/usr/local/bin/tac 26 | } 27 | 28 | It 'print paths of three binary' 29 | When call TestWhichThreeBinary 30 | The output should equal "$(result)" 31 | The status should be success 32 | End 33 | End 34 | 35 | Describe 'Search three binary. One of three binary does not exist' 36 | Include shellutils/which_test.sh 37 | 38 | result() { %text 39 | #|/usr/local/bin/mimixbox 40 | #|/usr/local/bin/tac 41 | } 42 | 43 | It 'print paths of two binary and exit-status is fail' 44 | When call TestWhichOneOfThreeBinNotExist 45 | The output should equal "$(result)" 46 | The status should be failure 47 | End 48 | End 49 | 50 | Describe 'Which without no operand' 51 | Include shellutils/which_test.sh 52 | 53 | It 'print nothing' 54 | When call TestWhichWithoutOperand 55 | The output should equal '' 56 | The status should be failure 57 | End 58 | End 59 | 60 | Describe 'Which data from pipe' 61 | Include shellutils/which_test.sh 62 | 63 | It 'print nothing' 64 | When call TestWhichDataFromPipe 65 | The output should equal '' 66 | The status should be failure 67 | End 68 | End -------------------------------------------------------------------------------- /test/it/textutils/cat_test.sh: -------------------------------------------------------------------------------- 1 | Setup() { 2 | export TEST_DIR=/tmp/mimixbox/it 3 | export TEST_FILE_CAT=/tmp/mimixbox/it/cat.txt 4 | export TEST_FILE_CAT2=/tmp/mimixbox/it/cat2.txt 5 | export LANG=C 6 | 7 | mkdir -p ${TEST_DIR} 8 | 9 | echo "sh" > ${TEST_FILE_CAT} 10 | echo "ash" >> ${TEST_FILE_CAT} 11 | echo "csh" >> ${TEST_FILE_CAT} 12 | echo "bash" >> ${TEST_FILE_CAT} 13 | 14 | echo "fish" > ${TEST_FILE_CAT2} 15 | echo "zsh" >> ${TEST_FILE_CAT2} 16 | } 17 | 18 | CleanUp() { 19 | export TEST_DIR=/tmp/mimixbox/it 20 | rm -rf ${TEST_DIR} 21 | } 22 | 23 | TestCatNoArg() { 24 | export TEST_FILE_CAT=/tmp/mimixbox/it/cat.txt 25 | cat ${TEST_FILE_CAT} 26 | } 27 | 28 | TestCatWithNumbetOption() { 29 | export TEST_FILE_CAT=/tmp/mimixbox/it/cat.txt 30 | cat -n ${TEST_FILE_CAT} 31 | } 32 | 33 | TestCatFromPipeData() { 34 | export TEST_FILE_CAT=/tmp/mimixbox/it/cat.txt 35 | echo ${TEST_FILE_CAT} | cat 36 | } 37 | 38 | TestCatOnlyOperandWithPipeData() { 39 | export TEST_FILE_CAT=/tmp/mimixbox/it/cat.txt 40 | export TEST_FILE_CAT2=/tmp/mimixbox/it/cat2.txt 41 | echo ${TEST_FILE_CAT2} | cat ${TEST_FILE_CAT} 42 | } 43 | 44 | TestCatConcatenateTwoFile() { 45 | export TEST_FILE_CAT=/tmp/mimixbox/it/cat.txt 46 | export TEST_FILE_CAT2=/tmp/mimixbox/it/cat2.txt 47 | cat ${TEST_FILE_CAT} ${TEST_FILE_CAT2} 48 | } 49 | 50 | TestCatConcatenateTwoFileWithNumberOption() { 51 | export TEST_FILE_CAT=/tmp/mimixbox/it/cat.txt 52 | export TEST_FILE_CAT2=/tmp/mimixbox/it/cat2.txt 53 | cat -n ${TEST_FILE_CAT} ${TEST_FILE_CAT2} 54 | } 55 | 56 | TestCatHeredoc() { 57 | export TEST_FILE_CAT=/tmp/mimixbox/it/cat.txt 58 | export TEST_FILE_CAT2=/tmp/mimixbox/it/cat2.txt 59 | cat - << EOS ${TEST_FILE_CAT} > ${TEST_FILE_CAT2} 60 | fish 61 | zsh 62 | EOS 63 | cat ${TEST_FILE_CAT2} 64 | } 65 | 66 | TestCatNoOperand() { 67 | cat no_exist_file 68 | } -------------------------------------------------------------------------------- /test/it/textutils/dos2unix_test.sh: -------------------------------------------------------------------------------- 1 | Setup() { 2 | export TEST_DIR=/tmp/mimixbox/it/dos2unix 3 | export TEST_FILE1=${TEST_DIR}/1.txt 4 | export TEST_FILE2=${TEST_DIR}/2.txt 5 | export TEST_FILE3=${TEST_DIR}/3.txt 6 | 7 | mkdir -p ${TEST_DIR} 8 | echo "abc" > ${TEST_FILE1} 9 | echo "def" >> ${TEST_FILE1} 10 | echo "ghi" >> ${TEST_FILE1} 11 | sed -i 's/$/\r/g' ${TEST_FILE1} 12 | 13 | cp ${TEST_FILE1} ${TEST_FILE2} 14 | cp ${TEST_FILE1} ${TEST_FILE3} 15 | } 16 | 17 | Cleanup() { 18 | export TEST_DIR=/tmp/mimixbox/it/dos2unix 19 | rm -rf ${TEST_DIR} 20 | } 21 | 22 | TestDos2unixCRLF() { 23 | export TEST_DIR=/tmp/mimixbox/it/dos2unix 24 | export TEST_FILE1=${TEST_DIR}/1.txt 25 | 26 | dos2unix ${TEST_FILE1} 27 | file ${TEST_FILE1} 28 | } 29 | 30 | TestDos2unixCRLFStatus() { 31 | export TEST_DIR=/tmp/mimixbox/it/dos2unix 32 | export TEST_FILE1=${TEST_DIR}/1.txt 33 | 34 | dos2unix ${TEST_FILE1} 35 | } 36 | 37 | TestDos2unixThreeFileAtSameTime() { 38 | export TEST_DIR=/tmp/mimixbox/it/dos2unix 39 | export TEST_FILE1=${TEST_DIR}/1.txt 40 | export TEST_FILE2=${TEST_DIR}/2.txt 41 | export TEST_FILE3=${TEST_DIR}/3.txt 42 | 43 | dos2unix ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 44 | file ${TEST_FILE1} 45 | file ${TEST_FILE2} 46 | file ${TEST_FILE3} 47 | } 48 | 49 | TestDos2unixThreeFileAtSameTime() { 50 | export TEST_DIR=/tmp/mimixbox/it/dos2unix 51 | export TEST_FILE1=${TEST_DIR}/1.txt 52 | export TEST_FILE2=${TEST_DIR}/2.txt 53 | export TEST_FILE3=${TEST_DIR}/3.txt 54 | 55 | dos2unix ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 56 | file ${TEST_FILE1} 57 | file ${TEST_FILE2} 58 | file ${TEST_FILE3} 59 | } 60 | 61 | TestDos2unixThreeFileAtSameTimeStatus() { 62 | export TEST_DIR=/tmp/mimixbox/it/dos2unix 63 | export TEST_FILE1=${TEST_DIR}/1.txt 64 | export TEST_FILE2=${TEST_DIR}/2.txt 65 | export TEST_FILE3=${TEST_DIR}/3.txt 66 | 67 | dos2unix ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 68 | } 69 | 70 | TestDos2unixDir() { 71 | export TEST_DIR=/tmp/mimixbox/it/dos2unix 72 | dos2unix ${TEST_DIR} 73 | } 74 | 75 | TestDos2unixOneOfThreeFail() { 76 | export TEST_DIR=/tmp/mimixbox/it/dos2unix 77 | export TEST_FILE1=${TEST_DIR}/1.txt 78 | export TEST_FILE2=${TEST_DIR}/2.txt 79 | export TEST_FILE3=${TEST_DIR}/3.txt 80 | 81 | dos2unix ${TEST_FILE1} ${TEST_DIR} ${TEST_FILE3} 82 | } -------------------------------------------------------------------------------- /test/it/textutils/md5sum_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/md5sum 2 | export TEST_FILE1=${TEST_DIR}/1.txt 3 | export TEST_FILE2=${TEST_DIR}/2.txt 4 | export TEST_FILE3=${TEST_DIR}/3.txt 5 | export CHECK_SUM_FILE=${TEST_DIR}/checksum.txt 6 | 7 | Setup() { 8 | mkdir -p ${TEST_DIR} 9 | echo "Dungeon of Regalias" > ${TEST_FILE1} 10 | echo "DEMONION" > ${TEST_FILE2} 11 | echo "Dungeon Crusadearz" > ${TEST_FILE3} 12 | 13 | echo "d0d8ffef81b3c7160ac655d5939548c5 /tmp/mimixbox/it/md5sum/1.txt" > ${CHECK_SUM_FILE} 14 | echo "07e280ad4bd77b9321f0ce3386775019 /tmp/mimixbox/it/md5sum/2.txt" >> ${CHECK_SUM_FILE} 15 | echo "15e924f84517598e828f49dc85765bc5 /tmp/mimixbox/it/md5sum/3.txt" >> ${CHECK_SUM_FILE} 16 | } 17 | 18 | Cleanup() { 19 | rm -rf ${TEST_DIR} 20 | } 21 | 22 | TestMd5sumOneFile() { 23 | md5sum ${TEST_FILE1} 24 | } 25 | 26 | TestMd5sumOneDirectory() { 27 | md5sum ${TEST_DIR} 28 | } 29 | 30 | TestMd5sumNotExistFile() { 31 | md5sum /not_exist_file 32 | } 33 | 34 | TestMd5sumThreeFiles() { 35 | md5sum ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 36 | } 37 | 38 | TestMd5sumWithCheckOption() { 39 | md5sum -c ${CHECK_SUM_FILE} 40 | } 41 | 42 | TestMd5sumDataFromPipe() { 43 | echo "test" | md5sum 44 | } 45 | 46 | TestMd5sumFileAndDataFromPipeAtSameTime() { 47 | echo "test" | md5sum ${TEST_FILE1} 48 | } 49 | -------------------------------------------------------------------------------- /test/it/textutils/nl_test.sh: -------------------------------------------------------------------------------- 1 | Setup() { 2 | export TEST_DIR=/tmp/mimixbox/it 3 | export TEST_FILE_NL=/tmp/mimixbox/it/nl.txt 4 | export TEST_FILE_NL2=/tmp/mimixbox/it/nl2.txt 5 | export LANG=C 6 | 7 | mkdir -p ${TEST_DIR} 8 | 9 | echo "sh" > ${TEST_FILE_NL} 10 | echo "ash" >> ${TEST_FILE_NL} 11 | echo "csh" >> ${TEST_FILE_NL} 12 | echo "bash" >> ${TEST_FILE_NL} 13 | 14 | echo "fish" > ${TEST_FILE_NL2} 15 | echo "zsh" >> ${TEST_FILE_NL2} 16 | } 17 | 18 | Cleanup() { 19 | export TEST_DIR=/tmp/mimixbox/it 20 | rm -rf ${TEST_DIR} 21 | } 22 | 23 | TestNlNoArg() { 24 | export TEST_FILE_NL=/tmp/mimixbox/it/nl.txt 25 | nl ${TEST_FILE_NL} 26 | } 27 | 28 | TestNlFromPipeData() { 29 | export TEST_FILE_NL=/tmp/mimixbox/it/nl.txt 30 | echo ${TEST_FILE_NL} | nl 31 | } 32 | 33 | TestNlOnlyOperandWithPipeData() { 34 | export TEST_FILE_NL=/tmp/mimixbox/it/nl.txt 35 | echo ${TEST_FILE_NL} | nl ${TEST_FILE_NL} 36 | } 37 | 38 | TestNlConcatenateTwoFile() { 39 | export TEST_FILE_NL=/tmp/mimixbox/it/nl.txt 40 | export TEST_FILE_NL2=/tmp/mimixbox/it/nl2.txt 41 | nl ${TEST_FILE_NL} ${TEST_FILE_NL2} 42 | } 43 | 44 | TestNlHeredoc() { 45 | export TEST_FILE_NL=/tmp/mimixbox/it/nl.txt 46 | export TEST_FILE_NL2=/tmp/mimixbox/it/nl2.txt 47 | nl - << EOS ${TEST_FILE_NL} > ${TEST_FILE_NL2} 48 | fish 49 | zsh 50 | EOS 51 | cat ${TEST_FILE_NL2} 52 | } 53 | 54 | TestNlHeredocStatus() { 55 | export TEST_FILE_NL=/tmp/mimixbox/it/nl.txt 56 | export TEST_FILE_NL2=/tmp/mimixbox/it/nl2.txt 57 | nl - << EOS ${TEST_FILE_NL} > ${TEST_FILE_NL2} 58 | fish 59 | zsh 60 | EOS 61 | } 62 | 63 | TestNlNoOperand() { 64 | nl no_exist_file 65 | } -------------------------------------------------------------------------------- /test/it/textutils/sha1sum_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/sha1sum 2 | export TEST_FILE1=${TEST_DIR}/1.txt 3 | export TEST_FILE2=${TEST_DIR}/2.txt 4 | export TEST_FILE3=${TEST_DIR}/3.txt 5 | export CHECK_SUM_FILE=${TEST_DIR}/checksum.txt 6 | 7 | Setup() { 8 | mkdir -p ${TEST_DIR} 9 | echo "Dungeon of Regalias" > ${TEST_FILE1} 10 | echo "DEMONION" > ${TEST_FILE2} 11 | echo "Dungeon Crusadearz" > ${TEST_FILE3} 12 | 13 | echo "9dc2936d38932f9ffc6738cb677e4a8722116070 /tmp/mimixbox/it/sha1sum/1.txt" > ${CHECK_SUM_FILE} 14 | echo "317e30648976d62fae4662fe4435e6568648e8a7 /tmp/mimixbox/it/sha1sum/2.txt" >> ${CHECK_SUM_FILE} 15 | echo "d4e9619d949de0c0182a09757346ad22e80114b3 /tmp/mimixbox/it/sha1sum/3.txt" >> ${CHECK_SUM_FILE} 16 | } 17 | 18 | Cleanup() { 19 | rm -rf ${TEST_DIR} 20 | } 21 | 22 | TestMd5sumOneFile() { 23 | sha1sum ${TEST_FILE1} 24 | } 25 | 26 | TestMd5sumOneDirectory() { 27 | sha1sum ${TEST_DIR} 28 | } 29 | 30 | TestMd5sumNotExistFile() { 31 | sha1sum /not_exist_file 32 | } 33 | 34 | TestMd5sumThreeFiles() { 35 | sha1sum ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 36 | } 37 | 38 | TestMd5sumWithCheckOption() { 39 | sha1sum -c ${CHECK_SUM_FILE} 40 | } 41 | 42 | TestMd5sumDataFromPipe() { 43 | echo "test" | sha1sum 44 | } 45 | 46 | TestMd5sumFileAndDataFromPipeAtSameTime() { 47 | echo "test" | sha1sum ${TEST_FILE1} 48 | } 49 | -------------------------------------------------------------------------------- /test/it/textutils/sha256sum_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/sha256sum 2 | export TEST_FILE1=${TEST_DIR}/1.txt 3 | export TEST_FILE2=${TEST_DIR}/2.txt 4 | export TEST_FILE3=${TEST_DIR}/3.txt 5 | export CHECK_SUM_FILE=${TEST_DIR}/checksum.txt 6 | 7 | Setup() { 8 | mkdir -p ${TEST_DIR} 9 | echo "Dungeon of Regalias" > ${TEST_FILE1} 10 | echo "DEMONION" > ${TEST_FILE2} 11 | echo "Dungeon Crusadearz" > ${TEST_FILE3} 12 | 13 | echo "5f2864b5833190b07b0b95228682ff5ec43a13a2a3f31514c57d5c92aa3fb2e7 /tmp/mimixbox/it/sha256sum/1.txt" > ${CHECK_SUM_FILE} 14 | echo "833d8136112b60552a0f83165a2ebffeac4b0c0249480d651ea58b9073ec925b /tmp/mimixbox/it/sha256sum/2.txt" >> ${CHECK_SUM_FILE} 15 | echo "8e774f75a5a23c83e6f7d5e92863a2615e0335e06aec18d9c3ec1c5315d1a777 /tmp/mimixbox/it/sha256sum/3.txt" >> ${CHECK_SUM_FILE} 16 | } 17 | 18 | Cleanup() { 19 | rm -rf ${TEST_DIR} 20 | } 21 | 22 | TestMd5sumOneFile() { 23 | sha256sum ${TEST_FILE1} 24 | } 25 | 26 | TestMd5sumOneDirectory() { 27 | sha256sum ${TEST_DIR} 28 | } 29 | 30 | TestMd5sumNotExistFile() { 31 | sha256sum /not_exist_file 32 | } 33 | 34 | TestMd5sumThreeFiles() { 35 | sha256sum ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 36 | } 37 | 38 | TestMd5sumWithCheckOption() { 39 | sha256sum -c ${CHECK_SUM_FILE} 40 | } 41 | 42 | TestMd5sumDataFromPipe() { 43 | echo "test" | sha256sum 44 | } 45 | 46 | TestMd5sumFileAndDataFromPipeAtSameTime() { 47 | echo "test" | sha256sum ${TEST_FILE1} 48 | } 49 | -------------------------------------------------------------------------------- /test/it/textutils/sha512sum_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/sha512sum 2 | export TEST_FILE1=${TEST_DIR}/1.txt 3 | export TEST_FILE2=${TEST_DIR}/2.txt 4 | export TEST_FILE3=${TEST_DIR}/3.txt 5 | export CHECK_SUM_FILE=${TEST_DIR}/checksum.txt 6 | 7 | Setup() { 8 | mkdir -p ${TEST_DIR} 9 | echo "Dungeon of Regalias" > ${TEST_FILE1} 10 | echo "DEMONION" > ${TEST_FILE2} 11 | echo "Dungeon Crusadearz" > ${TEST_FILE3} 12 | 13 | echo "05eec7dcf412f63d5a291d019f6b3d62d4f8f5236592815ed171f7d6d0a7969f65a589a092740bd04a2f181d7d5a27ff36808e04a69bd84a854aad0a01da3612 /tmp/mimixbox/it/sha512sum/1.txt" > ${CHECK_SUM_FILE} 14 | echo "cb2389a103184f607973b1acd073dc15310c8172b03f340a52bdc3843621cf9fbc6263c7dbbd786ceb0244f5147a83aa32ce09a485f544093b7fc5c7533e564f /tmp/mimixbox/it/sha512sum/2.txt" >> ${CHECK_SUM_FILE} 15 | echo "3dafa5f1ec7f09cbe551dc0d4bdb153dedb81104b7e930b7c20733965f7ebb86ee2abea64b6bfa1c54045032865044a3feca5dcc89c28def410b2954094a1890 /tmp/mimixbox/it/sha512sum/3.txt" >> ${CHECK_SUM_FILE} 16 | } 17 | 18 | Cleanup() { 19 | rm -rf ${TEST_DIR} 20 | } 21 | 22 | TestMd5sumOneFile() { 23 | sha512sum ${TEST_FILE1} 24 | } 25 | 26 | TestMd5sumOneDirectory() { 27 | sha512sum ${TEST_DIR} 28 | } 29 | 30 | TestMd5sumNotExistFile() { 31 | sha512sum /not_exist_file 32 | } 33 | 34 | TestMd5sumThreeFiles() { 35 | sha512sum ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 36 | } 37 | 38 | TestMd5sumWithCheckOption() { 39 | sha512sum -c ${CHECK_SUM_FILE} 40 | } 41 | 42 | TestMd5sumDataFromPipe() { 43 | echo "test" | sha512sum 44 | } 45 | 46 | TestMd5sumFileAndDataFromPipeAtSameTime() { 47 | echo "test" | sha512sum ${TEST_FILE1} 48 | } 49 | -------------------------------------------------------------------------------- /test/it/textutils/unix2dos_test.sh: -------------------------------------------------------------------------------- 1 | export TEST_DIR=/tmp/mimixbox/it/unix2dos 2 | export TEST_FILE1=${TEST_DIR}/1.txt 3 | export TEST_FILE2=${TEST_DIR}/2.txt 4 | export TEST_FILE3=${TEST_DIR}/3.txt 5 | 6 | 7 | Setup() { 8 | mkdir -p ${TEST_DIR} 9 | echo "abc" > ${TEST_FILE1} 10 | echo "def" >> ${TEST_FILE1} 11 | echo "ghi" >> ${TEST_FILE1} 12 | 13 | cp ${TEST_FILE1} ${TEST_FILE2} 14 | cp ${TEST_FILE1} ${TEST_FILE3} 15 | } 16 | 17 | Cleanup() { 18 | rm -rf ${TEST_DIR} 19 | } 20 | 21 | TestUnix2dosCRLF() { 22 | /usr/local/bin/unix2dos ${TEST_FILE1} 23 | file ${TEST_FILE1} 24 | } 25 | 26 | TestUnix2dosCRLFStatus() { 27 | /usr/local/bin/unix2dos ${TEST_FILE1} 28 | } 29 | 30 | TestUnix2dosThreeFileAtSameTime() { 31 | /usr/local/bin/unix2dos ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 32 | file ${TEST_FILE1} 33 | file ${TEST_FILE2} 34 | file ${TEST_FILE3} 35 | } 36 | 37 | TestUnix2dosThreeFileAtSameTime() { 38 | /usr/local/bin/unix2dos ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 39 | file ${TEST_FILE1} 40 | file ${TEST_FILE2} 41 | file ${TEST_FILE3} 42 | } 43 | 44 | TestUnix2dosThreeFileAtSameTimeStatus() { 45 | /usr/local/bin/unix2dos ${TEST_FILE1} ${TEST_FILE2} ${TEST_FILE3} 46 | } 47 | 48 | TestUnix2dosDir() { 49 | /usr/local/bin/unix2dos ${TEST_DIR} 50 | } 51 | 52 | TestUnix2dosOneOfThreeFail() { 53 | /usr/local/bin/unix2dos ${TEST_FILE1} ${TEST_DIR} ${TEST_FILE3} 54 | } -------------------------------------------------------------------------------- /test/it/textutils/wc_test.sh: -------------------------------------------------------------------------------- 1 | Setup() { 2 | export TEST_DIR=/tmp/mimixbox/it 3 | export TEST_FILE_GAMENAME=/tmp/mimixbox/it/game.txt 4 | export TEST_FILE_METAL=/tmp/mimixbox/it/metal.txt 5 | export EMPTY_FILE=/tmp/mimixbox/it/empty.txt 6 | export LANG=C 7 | 8 | mkdir -p ${TEST_DIR} 9 | 10 | echo "NieR Replicant ver.1.22474487139..." > ${TEST_FILE_GAMENAME} 11 | echo "NieR:Automata" >> ${TEST_FILE_GAMENAME} 12 | echo "The Legend of Zelda: Majora's Mask" >> ${TEST_FILE_GAMENAME} 13 | echo "KICHIKUOU RANCE" >> ${TEST_FILE_GAMENAME} 14 | echo "DARK SOULS" >> ${TEST_FILE_GAMENAME} 15 | echo "SHADOW HEARTS" >> ${TEST_FILE_GAMENAME} 16 | 17 | echo "MEGADETH" > ${TEST_FILE_METAL} 18 | echo "GALNERYUS" >> ${TEST_FILE_METAL} 19 | echo "SYSTEM OF A DOWN" >> ${TEST_FILE_METAL} 20 | 21 | touch ${EMPTY_FILE} 22 | } 23 | 24 | CleanUp() { 25 | export TEST_FILE_GAMENAME=/tmp/mimixbox/it/game.txt 26 | export TEST_FILE_METAL=/tmp/mimixbox/it/metal.txt 27 | export EMPTY_FILE=/tmp/mimixbox/it/empty.txt 28 | 29 | rm ${TEST_FILE_GAMENAME} ${EMPTY_FILE} ${TEST_FILE_METAL} 30 | } 31 | 32 | TestWcWithNoOption() { 33 | export TEST_FILE_GAMENAME=/tmp/mimixbox/it/game.txt 34 | wc ${TEST_FILE_GAMENAME} 35 | } 36 | 37 | TestWcWithLinesOption() { 38 | export TEST_FILE_GAMENAME=/tmp/mimixbox/it/game.txt 39 | wc -l ${TEST_FILE_GAMENAME} 40 | } 41 | 42 | TestWcWithBytesOption() { 43 | export TEST_FILE_GAMENAME=/tmp/mimixbox/it/game.txt 44 | wc -c ${TEST_FILE_GAMENAME} 45 | } 46 | 47 | TestWcWithMaxLineLengthOption() { 48 | export TEST_FILE_GAMENAME=/tmp/mimixbox/it/game.txt 49 | wc -L ${TEST_FILE_GAMENAME} 50 | } 51 | 52 | TestWcReadingEmptyFile() { 53 | export EMPTY_FILE=/tmp/mimixbox/it/empty.txt 54 | wc ${EMPTY_FILE} 55 | } 56 | 57 | TestWcReadingThreeFile() { 58 | export TEST_FILE_GAMENAME=/tmp/mimixbox/it/game.txt 59 | export TEST_FILE_METAL=/tmp/mimixbox/it/metal.txt 60 | export EMPTY_FILE=/tmp/mimixbox/it/empty.txt 61 | wc ${EMPTY_FILE} ${TEST_FILE_GAMENAME} ${TEST_FILE_METAL} 62 | } 63 | 64 | TestWcWithPipe() { 65 | export TEST_FILE_GAMENAME=/tmp/mimixbox/it/game.txt 66 | echo ${TEST_FILE_GAMENAME} | wc 67 | } 68 | 69 | TestWcWithPipeAndArgument() { 70 | export TEST_FILE_GAMENAME=/tmp/mimixbox/it/game.txt 71 | echo ${TEST_FILE_GAMENAME} | wc ${TEST_FILE_GAMENAME} 72 | } 73 | 74 | TestWcNotFile() { 75 | export TEST_DIR=/tmp/mimixbox/it 76 | wc ${TEST_DIR} 77 | } 78 | 79 | TestWcDirectoryAndFileSameTime() { 80 | export TEST_DIR=/tmp/mimixbox/it 81 | wc ${TEST_DIR} ${TEST_FILE_GAMENAME} 82 | } 83 | 84 | TestWcNoExistFileNameFromPipeWithLinesOption() { 85 | echo "no_exist_file" | wc -l 86 | } 87 | -------------------------------------------------------------------------------- /test/ut/prepareUnitTest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | TEST_DIR=/tmp/mimixbox/ut 3 | FILES="Executable.txt Writable.txt Readable.txt NonExecutable.txt \ 4 | NonWritable.txt NonReadable.txt AllZero.txt .hidden.txt" 5 | DIRS="NoWritableDir NonExecutableDir EmptyDir NoEmptyDir .HiddenDir" 6 | 7 | function makeFile { 8 | touch $1 9 | if [ $? -ne 0 ]; then 10 | exit 1 11 | fi 12 | } 13 | 14 | function makeDir { 15 | if [ -e $1 ]; then 16 | return 17 | fi 18 | 19 | mkdir -p $1 20 | if [ $? -ne 0 ]; then 21 | exit 1 22 | fi 23 | } 24 | 25 | mkdir -p ${TEST_DIR} 26 | for file in $FILES; 27 | do 28 | makeFile ${TEST_DIR}/$file 29 | done 30 | 31 | for dir in $DIRS; 32 | do 33 | makeDir ${TEST_DIR}/$dir 34 | done 35 | 36 | chmod a+x ${TEST_DIR}/Executable.txt 37 | chmod a+w ${TEST_DIR}/Writable.txt 38 | chmod a+r ${TEST_DIR}/Readable.txt 39 | chmod a-x ${TEST_DIR}/NonExecutable.txt 40 | chmod a-w ${TEST_DIR}/NonWritable.txt 41 | chmod a-r ${TEST_DIR}/NonReadable.txt 42 | chmod a-x ${TEST_DIR}/NonExecutable.txt 43 | chmod a-w ${TEST_DIR}/NonWritable.txt 44 | chmod a-r ${TEST_DIR}/NonReadable.txt 45 | chmod 000 ${TEST_DIR}/AllZero.txt 46 | 47 | chmod a-w ${TEST_DIR}/NoWritableDir 48 | chmod a-x ${TEST_DIR}/NonExecutableDir 49 | 50 | ln -sf ${TEST_DIR}/Executable.txt ${TEST_DIR}/symbolic.txt 51 | 52 | touch ${TEST_DIR}/NoEmptyDir/aaa.txt 53 | touch ${TEST_DIR}/NoEmptyDir/bbb.txt 54 | touch ${TEST_DIR}/NoEmptyDir/ccc.txt --------------------------------------------------------------------------------