Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
40fbee4
feat: add support for node 12 and node 13
jrmclaurin Apr 11, 2020
7c47fce
feat: support node 8 through 13, port from nan to node-addon-api
jrmclaurin Apr 11, 2020
2ce4ec3
Merge remote-tracking branch 'jcoreio/kexec-pr-squash'
StorytellerCZ Oct 3, 2020
5dd8450
Add tests for Node 14
StorytellerCZ Oct 3, 2020
3b597f6
Update tests and compatibility
StorytellerCZ Oct 3, 2020
098f9de
Bump lodash from 4.17.15 to 4.17.20
dependabot[bot] Oct 3, 2020
9a519c8
Bump node-fetch from 2.6.0 to 2.6.1
dependabot[bot] Oct 3, 2020
971e343
Bump npm-registry-fetch from 4.0.3 to 4.0.7
dependabot[bot] Oct 3, 2020
1779738
Merge pull request #1 from StorytellerCZ/dependabot/npm_and_yarn/loda…
StorytellerCZ Oct 3, 2020
40c27bd
Merge pull request #2 from StorytellerCZ/dependabot/npm_and_yarn/node…
StorytellerCZ Oct 3, 2020
8304d19
Merge pull request #3 from StorytellerCZ/dependabot/npm_and_yarn/npm-…
StorytellerCZ Oct 3, 2020
00bf16d
Bump npm from 6.14.4 to 6.14.8
dependabot[bot] Oct 3, 2020
7a69f2d
Merge pull request #4 from StorytellerCZ/dependabot/npm_and_yarn/npm-…
StorytellerCZ Oct 3, 2020
8b1fae9
Update travis configuration file
StorytellerCZ Oct 3, 2020
c5444da
Bump npm-user-validate from 1.0.0 to 1.0.1
dependabot[bot] Oct 16, 2020
e7b0c23
Merge pull request #5 from StorytellerCZ/dependabot/npm_and_yarn/npm-…
StorytellerCZ Oct 18, 2020
24b175b
Bump semantic-release from 17.1.2 to 17.2.3
dependabot[bot] Nov 18, 2020
8006a53
Bump ini from 1.3.5 to 1.3.8
dependabot[bot] Dec 13, 2020
7459deb
Bump y18n from 3.2.1 to 3.2.2
dependabot[bot] Apr 1, 2021
4856ed9
Merge pull request #8 from StorytellerCZ/dependabot/npm_and_yarn/y18n…
StorytellerCZ Apr 28, 2021
dd8f323
Merge pull request #7 from StorytellerCZ/dependabot/npm_and_yarn/ini-…
StorytellerCZ Apr 28, 2021
3789a7a
Merge pull request #6 from StorytellerCZ/dependabot/npm_and_yarn/sema…
StorytellerCZ Apr 28, 2021
34fc118
Bump ssri from 6.0.1 to 6.0.2
dependabot[bot] Apr 28, 2021
cdbc2bf
Merge pull request #9 from StorytellerCZ/dependabot/npm_and_yarn/ssri…
StorytellerCZ Apr 28, 2021
508cb62
Update dependencies
StorytellerCZ Apr 29, 2021
65a84b3
Bump handlebars from 4.7.6 to 4.7.7
dependabot[bot] May 9, 2021
a56bea6
Bump lodash from 4.17.20 to 4.17.21
dependabot[bot] May 11, 2021
ccfa85f
Merge pull request #10 from StorytellerCZ/dependabot/npm_and_yarn/han…
StorytellerCZ May 11, 2021
c0dd95c
Revert undesirable changes to package.json
StorytellerCZ May 17, 2021
a1b4ef5
Bump normalize-url from 5.0.0 to 5.3.1
dependabot[bot] Jun 9, 2021
f59057d
Bump glob-parent from 5.1.1 to 5.1.2
dependabot[bot] Jun 12, 2021
e18a5af
Bump path-parse from 1.0.6 to 1.0.7
dependabot[bot] Aug 12, 2021
0d91fe2
Bump tar from 4.4.13 to 4.4.19
dependabot[bot] Sep 2, 2021
bcb38a5
Bump minimist from 1.2.5 to 1.2.6
dependabot[bot] Mar 28, 2022
58e94a0
Bump semver-regex from 3.1.2 to 3.1.4
dependabot[bot] Jun 3, 2022
92c204b
Bump semantic-release from 17.4.2 to 19.0.3
dependabot[bot] Jun 10, 2022
b490a85
Bump node-fetch from 2.6.1 to 2.6.7
dependabot[bot] Jun 25, 2022
27dd1e5
Bump decode-uri-component from 0.2.0 to 0.2.2
dependabot[bot] Dec 7, 2022
33c5015
Bump qs from 6.5.2 to 6.5.3
dependabot[bot] Dec 11, 2022
d089e89
Merge pull request #11 from StorytellerCZ/dependabot/npm_and_yarn/lod…
StorytellerCZ Jul 23, 2025
9c68c3e
Merge pull request #12 from StorytellerCZ/dependabot/npm_and_yarn/nor…
StorytellerCZ Jul 23, 2025
aa5d2bc
Merge pull request #13 from StorytellerCZ/dependabot/npm_and_yarn/glo…
StorytellerCZ Jul 23, 2025
350cccd
Merge pull request #15 from StorytellerCZ/dependabot/npm_and_yarn/pat…
StorytellerCZ Jul 23, 2025
2253c6c
Merge pull request #16 from StorytellerCZ/dependabot/npm_and_yarn/tar…
StorytellerCZ Jul 23, 2025
fe2ce5d
Merge pull request #18 from StorytellerCZ/dependabot/npm_and_yarn/min…
StorytellerCZ Jul 23, 2025
657cd1a
Merge pull request #19 from StorytellerCZ/dependabot/npm_and_yarn/sem…
StorytellerCZ Jul 23, 2025
18d03fc
Bump braces from 3.0.2 to 3.0.3
dependabot[bot] Jul 23, 2025
d577033
Merge pull request #21 from StorytellerCZ/dependabot/npm_and_yarn/nod…
StorytellerCZ Jul 23, 2025
23fac5f
Merge pull request #22 from StorytellerCZ/dependabot/npm_and_yarn/dec…
StorytellerCZ Jul 23, 2025
513da62
Merge pull request #23 from StorytellerCZ/dependabot/npm_and_yarn/qs-…
StorytellerCZ Jul 23, 2025
5aee931
Merge pull request #24 from StorytellerCZ/dependabot/npm_and_yarn/bra…
StorytellerCZ Jul 23, 2025
c82b050
Merge branch 'master' into dependabot/npm_and_yarn/semantic-release-1…
StorytellerCZ Jul 23, 2025
86f1cfa
Merge pull request #20 from StorytellerCZ/dependabot/npm_and_yarn/sem…
StorytellerCZ Jul 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: 2
jobs:
build:
docker:
- image: circleci/node:14.13.0

steps:
- checkout
- restore_cache:
name: Restore Yarn Package Cache
keys:
- yarn-packages-{{ checksum "yarn.lock" }}

- run:
name: Install Dependencies
command: yarn install --frozen-lockfile
- save_cache:
name: Save Yarn Package Cache
key: yarn-packages-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
- run:
name: lint
command: yarn lint
- run:
name: test
command: yarn unit
- run:
name: release
command: yarn semantic-release
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ build/
.lock-wscript
node_modules
npm-debug.log

.idea/
7 changes: 7 additions & 0 deletions .mocharc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

module.exports = {
ui: 'qunit',
reporter: 'spec',
timeout: 2000,
}
10 changes: 5 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
sudo: false
language: node_js
os: linux
dist: bionic
node_js:
- "6"
- "5"
- "4"
- "0.12"
- "14"
- "12"
- "10"
env:
- CXX=g++-4.8
addons:
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
4.0.0 / 2020-10-03
------------------
- add support for Node 12 and 14
- drop support for all Node versions before 10 and Node 11
- port from NaN to node-addon-api
- throw JS errors for all system call failures
- updated Mocha tests

3.0.0 / 2016-09-11
------------------
- port to NaN [#31]
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ Node.js - kexec

This module causes your current Node.js process to be replaced by the process invoked by the parameter of this function. It's like the Ruby exec function. It currently does not work on Windows.

Fully compatible with Node.js version v0.10 and v0.11.


Usage
-----
Expand Down
11 changes: 4 additions & 7 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@
'targets': [
{
'target_name': 'kexec',
'cflags!': [ '-fno-exceptions' ],
'cflags_cc!': [ '-fno-exceptions' ],
'sources': [ 'src/kexec.cc' ],
'defines': [
'<!@(node -v |grep "v[^0]" > /dev/null && echo "__NODE_GE_V4__" || true)',
'<!@(node -v |grep "v0\.1[12]" > /dev/null && echo "__NODE_V0_11_OR_12__" || true)',
'<!@(command -v iojs > /dev/null && echo "__NODE_V0_11_OR_12__" || true)',
'<!@(node -v |grep "v0\.10" > /dev/null && echo "__NODE_V0_10__" || true)',
],
"include_dirs": ["<!(node -e \"require('nan')\")"]
'include_dirs': [ "<!@(node -p \"require('node-addon-api').include\")" ],
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
}
]
}
9 changes: 0 additions & 9 deletions circle.yml

This file was deleted.

2 changes: 1 addition & 1 deletion demo/demovp-pids.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ var kexec = require('../')

console.log(process.pid + ' - PID before exec')

kexec('sh', [ '-c', 'echo "$$ - PID after exec"' ])
kexec('sh', ['-c', 'echo "$$ - PID after exec"'])
2 changes: 1 addition & 1 deletion demo/demovp.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
var kexec = require('../')
kexec('less', [ '/etc/fstab' ])
kexec('less', ['/etc/fstab'])
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
module.exports = require('./build/Release/kexec.node').kexec
module.exports = require('bindings')('kexec.node').kexec
15 changes: 9 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kexec",
"version": "3.0.0",
"version": "4.0.0",
"description": "Replace your Node.js process with another process. Like Ruby exec.",
"homepage": "https://github.com/jprichardson/node-kexec",
"repository": {
Expand All @@ -10,7 +10,8 @@
"scripts": {
"lint": "standard",
"test": "npm run lint && npm run unit",
"unit": "mocha"
"unit": "mocha",
"semantic-release": "semantic-release"
},
"keywords": [
"exec",
Expand All @@ -22,13 +23,15 @@
"license": "MIT",
"main": "./index",
"engines": {
"node": ">=0.10"
"node": ">=10"
},
"devDependencies": {
"mocha": "^2.3.3",
"standard": "^8.0.0"
"mocha": "^8.3.2",
"semantic-release": "^19.0.3",
"standard": "^14.3.4"
},
"dependencies": {
"nan": "^2.4.0"
"bindings": "^1.5.0",
"node-addon-api": "^3.1.0"
}
}
169 changes: 71 additions & 98 deletions src/kexec.cc
Original file line number Diff line number Diff line change
@@ -1,117 +1,90 @@
#include <cstdio>
#include <stdlib.h>
#include <string.h>
#if defined(__NODE_V0_11_OR_12__) || defined(__NODE_GE_V4__)
#include <fcntl.h>
#endif

//#ifdef __POSIX__
#include <unistd.h>
/*#else
#include <process.h>
#endif*/

#include <nan.h>


using v8::Array;
using v8::FunctionTemplate;
using v8::Handle;
using v8::Integer;
using v8::Local;
using v8::Object;
using v8::String;
#include <napi.h>

#include <sstream>
#include <string>
#include <vector>

static int clear_cloexec (int desc)
{
int flags = fcntl (desc, F_GETFD, 0);
if (flags < 0)
return flags; //return if reading failed
#include <unistd.h>
#include <fcntl.h>

flags &= ~FD_CLOEXEC; //clear FD_CLOEXEC bit
return fcntl (desc, F_SETFD, flags);
static void invalidArgs(Napi::Env env) {
Napi::TypeError::New(env, "invalid arguments: expected string or string, Array<string>").ThrowAsJavaScriptException();
}

static int do_exec(char *argv[])
{
clear_cloexec(0); //stdin
clear_cloexec(1); //stdout
clear_cloexec(2); //stderr
return execvp(argv[0], argv);
static void operationError(Napi::Env env, const char *operation, int code) {
std::ostringstream msg;
msg << operation << " failed with code " << code;
Napi::Error::New(env, msg.str()).ThrowAsJavaScriptException();
}

NAN_METHOD(kexec) {
/*
* Steve Blott: 17 Jan, 2014
* Temporary comment by way of explanation...
* To be deleted.
*
* With a single argument:
* - pass it to execvp as "sh -c 'args[0]'"
* - this is the existing usage
*
* With exactly two arguments:
* - the first is the command name
* - the second is an array of arguments
* ...as in process.child_process.spawn()
*
* This approach is not great, but it allows the established usage to
* coexist with direct execvp-usage, and avoids making any changes to the
* established API.
*/

if ( 1 == info.Length() && info[0]->IsString() )
{
String::Utf8Value str(info[0]);
char* argv[] = { const_cast<char *>("/bin/sh"), const_cast<char *>("-c"), *str, NULL};
void Kexec(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();

int err = do_exec(argv);

info.GetReturnValue().Set(Nan::New<Integer>(err));
if (info.Length() < 1 || info.Length() > 2 || !info[0].IsString()) {
invalidArgs(env);
return;
}

if ( 2 == info.Length() && info[0]->IsString() && info[1]->IsArray() )
{
String::Utf8Value str(info[0]);

// Substantially copied from:
// https://github.com/joyent/node/blob/2944e03/src/node_child_process.cc#L92-104
Local<Array> argv_handle = Local<Array>::Cast(info[1]);
int argc = argv_handle->Length();

int argv_length = argc + 1 + 1;
char **argv = new char*[argv_length];

argv[0] = *str;
argv[argv_length-1] = NULL;
for (int i = 0; i < argc; i++) {
String::Utf8Value arg(argv_handle->Get(Nan::New<Integer>(i))->ToString());
argv[i+1] = strdup(*arg);
// Hold onto a reference to the std::string, to ensure the backing store for the c_str value isn't de-allocated.
std::string strCmd = info[0].As<Napi::String>().Utf8Value();
char *cmd = const_cast<char*>(strCmd.c_str());

char **argv;
if (1 == info.Length()) {
argv = new char*[4];
argv[0] = const_cast<char *>("/bin/sh");
argv[1] = const_cast<char *>("-c");
argv[2] = cmd;
argv[3] = NULL;
} else {
if (!info[1].IsArray()) {
invalidArgs(env);
return;
}
Napi::Array argsFromJS = info[1].As<Napi::Array>();
const int numArgs = argsFromJS.Length();

std::vector<std::string> strArgs(numArgs);
argv = new char*[numArgs + 2];
argv[0] = cmd;
for (int argIdx = 0; argIdx < numArgs; ++argIdx) {
Napi::Value arg = argsFromJS[argIdx];
if (!arg.IsString()) {
invalidArgs(env);
return;
}
strArgs[argIdx] = arg.As<Napi::String>().Utf8Value();
argv[argIdx + 1] = const_cast<char *>(strArgs[argIdx].c_str());
}
argv[numArgs + 1] = NULL;
}

int err = do_exec(argv);

// Failed...!
// FIXME: It might be better to raise an exception here.
for (int i = 0; i < argc; i++)
free(argv[i+1]);
delete [] argv;
// Run setfd on descriptors 0 through 2
for (int descriptor = 0; descriptor <= 2; ++descriptor) {
int flags = fcntl (descriptor, F_GETFD, 0);
if (flags < 0) {
operationError(env, "fcntl GETFD", flags);
return;
}

info.GetReturnValue().Set(Nan::New<Integer>(err));
flags &= ~FD_CLOEXEC; //clear FD_CLOEXEC bit
int setfdErrCode = fcntl (descriptor, F_SETFD, flags);
if (setfdErrCode) {
operationError(env, "fcntl SETFD", setfdErrCode);
return;
}
}

return Nan::ThrowTypeError("kexec: invalid arguments");
}
int execvpErrCode = execvp(argv[0], argv);

// Because of the exec, we only get here if there's a failure.
delete [] argv;

#define EXPORT(name, symbol) exports->Set( \
Nan::New<String>(name).ToLocalChecked(), \
Nan::New<FunctionTemplate>(symbol)->GetFunction() \
)
operationError(env, "execvp", execvpErrCode);
}

void init (Handle<Object> exports) {
EXPORT("kexec", kexec);
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "kexec"), Napi::Function::New(env, Kexec));
return exports;
}

NODE_MODULE(kexec, init);
NODE_API_MODULE(kexec, Init)
3 changes: 0 additions & 3 deletions test/mocha.opts

This file was deleted.

Loading