{"action":"created","comment":{"url":"https://api.github.com/repos/neovim/neovim/pulls/comments/25861688","id":25861688,"diff_hunk":"@@ -0,0 +1,225 @@\n+// Some of the code came from pangoterm and libuv\n+#include <stdbool.h>\n+#include <stdlib.h>\n+#include <string.h>\n+\n+#include <unistd.h>\n+#include <termios.h>\n+#include <sys/types.h>\n+#include <sys/wait.h>\n+#include <sys/ioctl.h>\n+\n+// forkpty is not in POSIX, so headers are platform-specific\n+#if defined(__FreeBSD__)\n+# include <libutil.h>\n+#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)\n+# include <util.h>\n+#else\n+# include <pty.h>\n+#endif\n+\n+#include <uv.h>\n+\n+#include \"nvim/os/job.h\"\n+#include \"nvim/os/job_defs.h\"\n+#include \"nvim/os/job_private.h\"\n+#include \"nvim/os/pty_process.h\"\n+#include \"nvim/memory.h\"\n+\n+#ifdef INCLUDE_GENERATED_DECLARATIONS\n+# include \"os/pty_process.c.generated.h\"\n+#endif\n+\n+typedef struct {\n+  struct winsize winsize;\n+  uv_pipe_t proc_stdin, proc_stdout, proc_stderr;\n+  uv_signal_t schld;\n+  int tty_fd;\n+} PtyProcess;\n+\n+void pty_process_init(Job *job)\n+{\n+  PtyProcess *ptyproc = xmalloc(sizeof(PtyProcess));\n+\n+  if (job->opts.writable) {\n+    uv_pipe_init(uv_default_loop(), &ptyproc->proc_stdin, 0);\n+    ptyproc->proc_stdin.data = NULL;\n+  }\n+\n+  if (job->opts.stdout_cb) {\n+    uv_pipe_init(uv_default_loop(), &ptyproc->proc_stdout, 0);\n+    ptyproc->proc_stdout.data = NULL;\n+  }\n+\n+  if (job->opts.stderr_cb) {\n+    uv_pipe_init(uv_default_loop(), &ptyproc->proc_stderr, 0);\n+    ptyproc->proc_stderr.data = NULL;\n+  }\n+\n+  job->proc_stdin = (uv_stream_t *)&ptyproc->proc_stdin;\n+  job->proc_stdout = (uv_stream_t *)&ptyproc->proc_stdout;\n+  job->proc_stderr = (uv_stream_t *)&ptyproc->proc_stderr;\n+  job->process = ptyproc;\n+}\n+\n+void pty_process_destroy(Job *job)\n+{\n+  free(job->opts.term_name);\n+  free(job->process);\n+  job->process = NULL;\n+}\n+\n+bool pty_process_spawn(Job *job)\n+{\n+  int master;\n+  PtyProcess *ptyproc = job->process;\n+  ptyproc->winsize = (struct winsize){job->opts.height, job->opts.width, 0, 0};\n+  struct termios termios;\n+  init_termios(&termios);\n+  uv_disable_stdio_inheritance();\n+\n+  int pid = forkpty(&master, NULL, &termios, &ptyproc->winsize);\n+\n+  if (pid < 0) {\n+    return false;\n+  } else if (pid == 0) {\n+    init_child(job);\n+    abort();\n+  }\n+\n+  // make sure the master file descriptor is non blocking\n+  fcntl(master, F_SETFL, fcntl(master, F_GETFL) | O_NONBLOCK);\n+\n+  if (job->opts.writable) {\n+    uv_pipe_open(&ptyproc->proc_stdin, dup(master));\n+  }\n+\n+  if (job->opts.stdout_cb) {\n+    uv_pipe_open(&ptyproc->proc_stdout, dup(master));\n+  }\n+\n+  if (job->opts.stderr_cb) {\n+    uv_pipe_open(&ptyproc->proc_stderr, dup(master));","path":"src/nvim/os/pty_process.c","position":102,"original_position":102,"commit_id":"d7e560e5b309578f142c23467d566877cb54ee9a","original_commit_id":"d7e560e5b309578f142c23467d566877cb54ee9a","user":{"login":"tarruda","id":842846,"avatar_url":"https://avatars.githubusercontent.com/u/842846?v=3","gravatar_id":"","url":"https://api.github.com/users/tarruda","html_url":"https://github.com/tarruda","followers_url":"https://api.github.com/users/tarruda/followers","following_url":"https://api.github.com/users/tarruda/following{/other_user}","gists_url":"https://api.github.com/users/tarruda/gists{/gist_id}","starred_url":"https://api.github.com/users/tarruda/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tarruda/subscriptions","organizations_url":"https://api.github.com/users/tarruda/orgs","repos_url":"https://api.github.com/users/tarruda/repos","events_url":"https://api.github.com/users/tarruda/events{/privacy}","received_events_url":"https://api.github.com/users/tarruda/received_events","type":"User","site_admin":false},"body":"They are closed by libuv when the stream is closed: https://github.com/libuv/libuv/blob/v1.x/src/unix/stream.c#L1563-L1568","created_at":"2015-03-05T13:08:09Z","updated_at":"2015-03-05T13:08:09Z","html_url":"https://github.com/neovim/neovim/pull/2037#discussion_r25861688","pull_request_url":"https://api.github.com/repos/neovim/neovim/pulls/2037","_links":{"self":{"href":"https://api.github.com/repos/neovim/neovim/pulls/comments/25861688"},"html":{"href":"https://github.com/neovim/neovim/pull/2037#discussion_r25861688"},"pull_request":{"href":"https://api.github.com/repos/neovim/neovim/pulls/2037"}}},"pull_request":{"url":"https://api.github.com/repos/neovim/neovim/pulls/2037","id":29758034,"html_url":"https://github.com/neovim/neovim/pull/2037","diff_url":"https://github.com/neovim/neovim/pull/2037.diff","patch_url":"https://github.com/neovim/neovim/pull/2037.patch","issue_url":"https://api.github.com/repos/neovim/neovim/issues/2037","number":2037,"state":"closed","locked":false,"title":"[RDY] Job control fixes and pseudo terminal support","user":{"login":"tarruda","id":842846,"avatar_url":"https://avatars.githubusercontent.com/u/842846?v=3","gravatar_id":"","url":"https://api.github.com/users/tarruda","html_url":"https://github.com/tarruda","followers_url":"https://api.github.com/users/tarruda/followers","following_url":"https://api.github.com/users/tarruda/following{/other_user}","gists_url":"https://api.github.com/users/tarruda/gists{/gist_id}","starred_url":"https://api.github.com/users/tarruda/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tarruda/subscriptions","organizations_url":"https://api.github.com/users/tarruda/orgs","repos_url":"https://api.github.com/users/tarruda/repos","events_url":"https://api.github.com/users/tarruda/events{/privacy}","received_events_url":"https://api.github.com/users/tarruda/received_events","type":"User","site_admin":false},"body":"The end goal is to spawn bang commands connected to pseudo terminals, which will fix issues such as #1716. For windows an alternative implementation of pty_process.c will be required, probably on top of [winpty](https://github.com/rprichard/winpty/blob/master/include/winpty.h)","created_at":"2015-02-21T19:01:05Z","updated_at":"2015-03-05T13:08:09Z","closed_at":"2015-02-24T01:26:22Z","merged_at":"2015-02-24T01:26:22Z","merge_commit_sha":"c83d2d99d68933c92a7d9880e1d26e1657ab9bbd","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/neovim/neovim/pulls/2037/commits","review_comments_url":"https://api.github.com/repos/neovim/neovim/pulls/2037/comments","review_comment_url":"https://api.github.com/repos/neovim/neovim/pulls/comments{/number}","comments_url":"https://api.github.com/repos/neovim/neovim/issues/2037/comments","statuses_url":"https://api.github.com/repos/neovim/neovim/statuses/d7e560e5b309578f142c23467d566877cb54ee9a","head":{"label":"tarruda:job-pty","ref":"job-pty","sha":"d7e560e5b309578f142c23467d566877cb54ee9a","user":{"login":"tarruda","id":842846,"avatar_url":"https://avatars.githubusercontent.com/u/842846?v=3","gravatar_id":"","url":"https://api.github.com/users/tarruda","html_url":"https://github.com/tarruda","followers_url":"https://api.github.com/users/tarruda/followers","following_url":"https://api.github.com/users/tarruda/following{/other_user}","gists_url":"https://api.github.com/users/tarruda/gists{/gist_id}","starred_url":"https://api.github.com/users/tarruda/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tarruda/subscriptions","organizations_url":"https://api.github.com/users/tarruda/orgs","repos_url":"https://api.github.com/users/tarruda/repos","events_url":"https://api.github.com/users/tarruda/events{/privacy}","received_events_url":"https://api.github.com/users/tarruda/received_events","type":"User","site_admin":false},"repo":{"id":17170945,"name":"neovim","full_name":"tarruda/neovim","owner":{"login":"tarruda","id":842846,"avatar_url":"https://avatars.githubusercontent.com/u/842846?v=3","gravatar_id":"","url":"https://api.github.com/users/tarruda","html_url":"https://github.com/tarruda","followers_url":"https://api.github.com/users/tarruda/followers","following_url":"https://api.github.com/users/tarruda/following{/other_user}","gists_url":"https://api.github.com/users/tarruda/gists{/gist_id}","starred_url":"https://api.github.com/users/tarruda/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tarruda/subscriptions","organizations_url":"https://api.github.com/users/tarruda/orgs","repos_url":"https://api.github.com/users/tarruda/repos","events_url":"https://api.github.com/users/tarruda/events{/privacy}","received_events_url":"https://api.github.com/users/tarruda/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tarruda/neovim","description":"vim's rebirth for the 21st century","fork":true,"url":"https://api.github.com/repos/tarruda/neovim","forks_url":"https://api.github.com/repos/tarruda/neovim/forks","keys_url":"https://api.github.com/repos/tarruda/neovim/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tarruda/neovim/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tarruda/neovim/teams","hooks_url":"https://api.github.com/repos/tarruda/neovim/hooks","issue_events_url":"https://api.github.com/repos/tarruda/neovim/issues/events{/number}","events_url":"https://api.github.com/repos/tarruda/neovim/events","assignees_url":"https://api.github.com/repos/tarruda/neovim/assignees{/user}","branches_url":"https://api.github.com/repos/tarruda/neovim/branches{/branch}","tags_url":"https://api.github.com/repos/tarruda/neovim/tags","blobs_url":"https://api.github.com/repos/tarruda/neovim/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tarruda/neovim/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tarruda/neovim/git/refs{/sha}","trees_url":"https://api.github.com/repos/tarruda/neovim/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tarruda/neovim/statuses/{sha}","languages_url":"https://api.github.com/repos/tarruda/neovim/languages","stargazers_url":"https://api.github.com/repos/tarruda/neovim/stargazers","contributors_url":"https://api.github.com/repos/tarruda/neovim/contributors","subscribers_url":"https://api.github.com/repos/tarruda/neovim/subscribers","subscription_url":"https://api.github.com/repos/tarruda/neovim/subscription","commits_url":"https://api.github.com/repos/tarruda/neovim/commits{/sha}","git_commits_url":"https://api.github.com/repos/tarruda/neovim/git/commits{/sha}","comments_url":"https://api.github.com/repos/tarruda/neovim/comments{/number}","issue_comment_url":"https://api.github.com/repos/tarruda/neovim/issues/comments{/number}","contents_url":"https://api.github.com/repos/tarruda/neovim/contents/{+path}","compare_url":"https://api.github.com/repos/tarruda/neovim/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tarruda/neovim/merges","archive_url":"https://api.github.com/repos/tarruda/neovim/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tarruda/neovim/downloads","issues_url":"https://api.github.com/repos/tarruda/neovim/issues{/number}","pulls_url":"https://api.github.com/repos/tarruda/neovim/pulls{/number}","milestones_url":"https://api.github.com/repos/tarruda/neovim/milestones{/number}","notifications_url":"https://api.github.com/repos/tarruda/neovim/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tarruda/neovim/labels{/name}","releases_url":"https://api.github.com/repos/tarruda/neovim/releases{/id}","created_at":"2014-02-25T11:35:55Z","updated_at":"2014-12-23T20:52:21Z","pushed_at":"2015-03-05T13:06:35Z","git_url":"git://github.com/tarruda/neovim.git","ssh_url":"git@github.com:tarruda/neovim.git","clone_url":"https://github.com/tarruda/neovim.git","svn_url":"https://github.com/tarruda/neovim","homepage":"http://neovim.org/","size":35483,"stargazers_count":1,"watchers_count":1,"language":"C","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"neovim:master","ref":"master","sha":"0df6b9168e9dc09d3e0ae6050d67b7c31c603782","user":{"login":"neovim","id":6471485,"avatar_url":"https://avatars.githubusercontent.com/u/6471485?v=3","gravatar_id":"","url":"https://api.github.com/users/neovim","html_url":"https://github.com/neovim","followers_url":"https://api.github.com/users/neovim/followers","following_url":"https://api.github.com/users/neovim/following{/other_user}","gists_url":"https://api.github.com/users/neovim/gists{/gist_id}","starred_url":"https://api.github.com/users/neovim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/neovim/subscriptions","organizations_url":"https://api.github.com/users/neovim/orgs","repos_url":"https://api.github.com/users/neovim/repos","events_url":"https://api.github.com/users/neovim/events{/privacy}","received_events_url":"https://api.github.com/users/neovim/received_events","type":"Organization","site_admin":false},"repo":{"id":16408992,"name":"neovim","full_name":"neovim/neovim","owner":{"login":"neovim","id":6471485,"avatar_url":"https://avatars.githubusercontent.com/u/6471485?v=3","gravatar_id":"","url":"https://api.github.com/users/neovim","html_url":"https://github.com/neovim","followers_url":"https://api.github.com/users/neovim/followers","following_url":"https://api.github.com/users/neovim/following{/other_user}","gists_url":"https://api.github.com/users/neovim/gists{/gist_id}","starred_url":"https://api.github.com/users/neovim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/neovim/subscriptions","organizations_url":"https://api.github.com/users/neovim/orgs","repos_url":"https://api.github.com/users/neovim/repos","events_url":"https://api.github.com/users/neovim/events{/privacy}","received_events_url":"https://api.github.com/users/neovim/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/neovim/neovim","description":"vim out of the box","fork":false,"url":"https://api.github.com/repos/neovim/neovim","forks_url":"https://api.github.com/repos/neovim/neovim/forks","keys_url":"https://api.github.com/repos/neovim/neovim/keys{/key_id}","collaborators_url":"https://api.github.com/repos/neovim/neovim/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/neovim/neovim/teams","hooks_url":"https://api.github.com/repos/neovim/neovim/hooks","issue_events_url":"https://api.github.com/repos/neovim/neovim/issues/events{/number}","events_url":"https://api.github.com/repos/neovim/neovim/events","assignees_url":"https://api.github.com/repos/neovim/neovim/assignees{/user}","branches_url":"https://api.github.com/repos/neovim/neovim/branches{/branch}","tags_url":"https://api.github.com/repos/neovim/neovim/tags","blobs_url":"https://api.github.com/repos/neovim/neovim/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/neovim/neovim/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/neovim/neovim/git/refs{/sha}","trees_url":"https://api.github.com/repos/neovim/neovim/git/trees{/sha}","statuses_url":"https://api.github.com/repos/neovim/neovim/statuses/{sha}","languages_url":"https://api.github.com/repos/neovim/neovim/languages","stargazers_url":"https://api.github.com/repos/neovim/neovim/stargazers","contributors_url":"https://api.github.com/repos/neovim/neovim/contributors","subscribers_url":"https://api.github.com/repos/neovim/neovim/subscribers","subscription_url":"https://api.github.com/repos/neovim/neovim/subscription","commits_url":"https://api.github.com/repos/neovim/neovim/commits{/sha}","git_commits_url":"https://api.github.com/repos/neovim/neovim/git/commits{/sha}","comments_url":"https://api.github.com/repos/neovim/neovim/comments{/number}","issue_comment_url":"https://api.github.com/repos/neovim/neovim/issues/comments{/number}","contents_url":"https://api.github.com/repos/neovim/neovim/contents/{+path}","compare_url":"https://api.github.com/repos/neovim/neovim/compare/{base}...{head}","merges_url":"https://api.github.com/repos/neovim/neovim/merges","archive_url":"https://api.github.com/repos/neovim/neovim/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/neovim/neovim/downloads","issues_url":"https://api.github.com/repos/neovim/neovim/issues{/number}","pulls_url":"https://api.github.com/repos/neovim/neovim/pulls{/number}","milestones_url":"https://api.github.com/repos/neovim/neovim/milestones{/number}","notifications_url":"https://api.github.com/repos/neovim/neovim/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/neovim/neovim/labels{/name}","releases_url":"https://api.github.com/repos/neovim/neovim/releases{/id}","created_at":"2014-01-31T13:39:22Z","updated_at":"2015-03-05T11:37:26Z","pushed_at":"2015-03-04T09:17:55Z","git_url":"git://github.com/neovim/neovim.git","ssh_url":"git@github.com:neovim/neovim.git","clone_url":"https://github.com/neovim/neovim.git","svn_url":"https://github.com/neovim/neovim","homepage":"http://neovim.org","size":53555,"stargazers_count":12221,"watchers_count":12221,"language":"VimL","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":802,"mirror_url":null,"open_issues_count":392,"forks":802,"open_issues":392,"watchers":12221,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/neovim/neovim/pulls/2037"},"html":{"href":"https://github.com/neovim/neovim/pull/2037"},"issue":{"href":"https://api.github.com/repos/neovim/neovim/issues/2037"},"comments":{"href":"https://api.github.com/repos/neovim/neovim/issues/2037/comments"},"review_comments":{"href":"https://api.github.com/repos/neovim/neovim/pulls/2037/comments"},"review_comment":{"href":"https://api.github.com/repos/neovim/neovim/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/neovim/neovim/pulls/2037/commits"},"statuses":{"href":"https://api.github.com/repos/neovim/neovim/statuses/d7e560e5b309578f142c23467d566877cb54ee9a"}}}}