Latest commit

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ctty

ctty is a controlling tty discovery tool (and library) for Linux.

What is a tty?

In Linux, users can issue commands to the operating system through a command line. In the modern era, a command line is implemented as a shell attached to a pseudo-terminal. The pseudo-terminal itself is a type of tty and leverages the tty driver section of the Linux kernel.

What is a controlling tty?

A controlling tty is a tty that has a special relationship with a process session. When a tty is "controlling" for a session, it will send the session leader, and other members of that session, signals to help control the user experience.

What is a session?

Processes are grouped into process groups for job control. Process groups themselves are grouped together into a session to facilitate the resource sharing of a tty. The man page for credentials is an excellent resource on this topic.

What part of the operating system keeps track of all this?

The tty driver in the kernel will know what session ID a tty is "controlling" for. Likewise, every process in a session will know which tty is "controlling" for it. There is no single authoritative point on the topic and a stable system requires the cooperation of all the players involved.

This sounds totally crazy? How did it end up this way?

Back in late 1960s, computers were finally fast enough to interact with users in real time. Coincidentally, the old teletype terminals were broadly used throughout the telecommunications industry. The engineers of the day, being appropriately lazy, simply re-purposed this existing technology to fit their needs. This was the birth of the command line.

Make sure you read The TTY demystified by Linus Åkesson. His page is the most enlightening for this topic anywhere on the internet. Many thanks to Linus for putting it together!

How can you tell what the controlling tty is for any given process?

The ctermid function will return the name of the controlling tty for the process that calls it, but this output is not particularly helpful for discovery. This function exists only to aid in portability and will always return the string "/dev/tty" regardless of which terminal or pseudo-terminal device is controlling for the process.

Further, there is no system or library call that will report the controlling tty for another process. The stat file for any given process will contain that information, though not in a format easily consumed by humans:

tty_nr %d The controlling terminal of the process. (The minor device number is contained in
the combination of bits 31 to 20 and 7 to 0; the major device number is in bits
15 to 8.)

The "ps j -p PID" command will report the controlling tty in a human readable format for any given PID.

How can you tell which session is controlled by any given tty?

Traditionally, there is no easy way to see this information programmatically. (Again, examining the results of the "ps j" command will allow you to perform this discovery manually.) I wrote ctty to fill this gap. It does the needed detective work, and reports back to the user. libctty gives you a C interface to this functionality.

ctty Usage

usage: ctty [-v] [TTY_NAME]
-v	verbose reporting format

To see the session information for a particular tty:

empty@monkey:~$ ctty /dev/pts/3
/dev/pts/3:empty:3099:3099:3099:0,1,2,255
/dev/pts/3:empty:3099:3158:3158:0,1,2
/dev/pts/3:empty:3099:3158:3170:1,2
/dev/pts/3:empty:3099:3176:3176:15,16,17,18,19
/dev/pts/3:empty:3099:3184:3184:0,1,2,5,6,7

The format is:

TTY_NAME:USER:SID:PGID:PID:FD1,FD2,...,FDn

The fields are:

  • TTY_NAME: tty name
  • USER: user name (or uid if no match in /etc/passwd)
  • SID: session ID
  • PGID: process group ID
  • PID: process ID
  • FDs: file descriptors which this process has open to the controlling tty.

Note:

  • Running ctty without any arguments will attempt to return the results for all ttys.
  • The -v switch will give a different output format that is a bit easier to read, though much longer and not fit for scripting.

libctty Usage

This is best documented inside the source code. However, as a quick overview, libctty.h defines the following interfaces:

/* ctty_get_name() is used to discover the controlling tty for a process. */
char *ctty_get_name(int pid);
/* ctty_get_session() is used to map out the entire process session. */
struct sid_node *ctty_get_session(char *tty_name);
/* ctty_free_session() is used to release the session data structure. */
void ctty_free_session(struct sid_node *session);
/* ctty_stat_parse() will pull ctty and session related info from the processes stat file. */
int ctty_stat_parse(int pid, struct proc_stat *stat_info);
/* ctty_get_fds() returns the list of file descriptors open to the tty you're interested in. */
int ctty_get_fds(int pid, char *tty, int **fds);

Installation

git clone https://github.com/emptymonkey/ctty.git
cd ctty
make

About

A library and tool for discovering and mapping Controlling TTYs in Linux.

Resources

Stars

24 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ctty

ctty is a controlling tty discovery tool (and library) for Linux.

What is a tty?

In Linux, users can issue commands to the operating system through a command line. In the modern era, a command line is implemented as a shell attached to a pseudo-terminal. The pseudo-terminal itself is a type of tty and leverages the tty driver section of the Linux kernel.

What is a controlling tty?

A controlling tty is a tty that has a special relationship with a process session. When a tty is "controlling" for a session, it will send the session leader, and other members of that session, signals to help control the user experience.

What is a session?

Processes are grouped into process groups for job control. Process groups themselves are grouped together into a session to facilitate the resource sharing of a tty. The man page for credentials is an excellent resource on this topic.

What part of the operating system keeps track of all this?

The tty driver in the kernel will know what session ID a tty is "controlling" for. Likewise, every process in a session will know which tty is "controlling" for it. There is no single authoritative point on the topic and a stable system requires the cooperation of all the players involved.

This sounds totally crazy? How did it end up this way?

Back in late 1960s, computers were finally fast enough to interact with users in real time. Coincidentally, the old teletype terminals were broadly used throughout the telecommunications industry. The engineers of the day, being appropriately lazy, simply re-purposed this existing technology to fit their needs. This was the birth of the command line.

Make sure you read The TTY demystified by Linus Åkesson. His page is the most enlightening for this topic anywhere on the internet. Many thanks to Linus for putting it together!

How can you tell what the controlling tty is for any given process?

The ctermid function will return the name of the controlling tty for the process that calls it, but this output is not particularly helpful for discovery. This function exists only to aid in portability and will always return the string "/dev/tty" regardless of which terminal or pseudo-terminal device is controlling for the process.

Further, there is no system or library call that will report the controlling tty for another process. The stat file for any given process will contain that information, though not in a format easily consumed by humans:

tty_nr %d The controlling terminal of the process. (The minor device number is contained in
the combination of bits 31 to 20 and 7 to 0; the major device number is in bits
15 to 8.)

The "ps j -p PID" command will report the controlling tty in a human readable format for any given PID.

How can you tell which session is controlled by any given tty?

Traditionally, there is no easy way to see this information programmatically. (Again, examining the results of the "ps j" command will allow you to perform this discovery manually.) I wrote ctty to fill this gap. It does the needed detective work, and reports back to the user. libctty gives you a C interface to this functionality.

ctty Usage

usage: ctty [-v] [TTY_NAME]
-v	verbose reporting format

To see the session information for a particular tty:

empty@monkey:~$ ctty /dev/pts/3
/dev/pts/3:empty:3099:3099:3099:0,1,2,255
/dev/pts/3:empty:3099:3158:3158:0,1,2
/dev/pts/3:empty:3099:3158:3170:1,2
/dev/pts/3:empty:3099:3176:3176:15,16,17,18,19
/dev/pts/3:empty:3099:3184:3184:0,1,2,5,6,7

The format is:

TTY_NAME:USER:SID:PGID:PID:FD1,FD2,...,FDn

The fields are:

  • TTY_NAME: tty name
  • USER: user name (or uid if no match in /etc/passwd)
  • SID: session ID
  • PGID: process group ID
  • PID: process ID
  • FDs: file descriptors which this process has open to the controlling tty.

Note:

  • Running ctty without any arguments will attempt to return the results for all ttys.
  • The -v switch will give a different output format that is a bit easier to read, though much longer and not fit for scripting.

libctty Usage

This is best documented inside the source code. However, as a quick overview, libctty.h defines the following interfaces:

/* ctty_get_name() is used to discover the controlling tty for a process. */
char *ctty_get_name(int pid);
/* ctty_get_session() is used to map out the entire process session. */
struct sid_node *ctty_get_session(char *tty_name);
/* ctty_free_session() is used to release the session data structure. */
void ctty_free_session(struct sid_node *session);
/* ctty_stat_parse() will pull ctty and session related info from the processes stat file. */
int ctty_stat_parse(int pid, struct proc_stat *stat_info);
/* ctty_get_fds() returns the list of file descriptors open to the tty you're interested in. */
int ctty_get_fds(int pid, char *tty, int **fds);

Installation

git clone https://github.com/emptymonkey/ctty.git
cd ctty
make

About

A library and tool for discovering and mapping Controlling TTYs in Linux.

Resources

Stars

24 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ctty

ctty is a controlling tty discovery tool (and library) for Linux.

What is a tty?

In Linux, users can issue commands to the operating system through a command line. In the modern era, a command line is implemented as a shell attached to a pseudo-terminal. The pseudo-terminal itself is a type of tty and leverages the tty driver section of the Linux kernel.

What is a controlling tty?

A controlling tty is a tty that has a special relationship with a process session. When a tty is "controlling" for a session, it will send the session leader, and other members of that session, signals to help control the user experience.

What is a session?

Processes are grouped into process groups for job control. Process groups themselves are grouped together into a session to facilitate the resource sharing of a tty. The man page for credentials is an excellent resource on this topic.

What part of the operating system keeps track of all this?

The tty driver in the kernel will know what session ID a tty is "controlling" for. Likewise, every process in a session will know which tty is "controlling" for it. There is no single authoritative point on the topic and a stable system requires the cooperation of all the players involved.

This sounds totally crazy? How did it end up this way?

Back in late 1960s, computers were finally fast enough to interact with users in real time. Coincidentally, the old teletype terminals were broadly used throughout the telecommunications industry. The engineers of the day, being appropriately lazy, simply re-purposed this existing technology to fit their needs. This was the birth of the command line.

Make sure you read The TTY demystified by Linus Åkesson. His page is the most enlightening for this topic anywhere on the internet. Many thanks to Linus for putting it together!

How can you tell what the controlling tty is for any given process?

The ctermid function will return the name of the controlling tty for the process that calls it, but this output is not particularly helpful for discovery. This function exists only to aid in portability and will always return the string "/dev/tty" regardless of which terminal or pseudo-terminal device is controlling for the process.

Further, there is no system or library call that will report the controlling tty for another process. The stat file for any given process will contain that information, though not in a format easily consumed by humans:

tty_nr %d The controlling terminal of the process. (The minor device number is contained in
the combination of bits 31 to 20 and 7 to 0; the major device number is in bits
15 to 8.)

The "ps j -p PID" command will report the controlling tty in a human readable format for any given PID.

How can you tell which session is controlled by any given tty?

Traditionally, there is no easy way to see this information programmatically. (Again, examining the results of the "ps j" command will allow you to perform this discovery manually.) I wrote ctty to fill this gap. It does the needed detective work, and reports back to the user. libctty gives you a C interface to this functionality.

ctty Usage

usage: ctty [-v] [TTY_NAME]
-v	verbose reporting format

To see the session information for a particular tty:

empty@monkey:~$ ctty /dev/pts/3
/dev/pts/3:empty:3099:3099:3099:0,1,2,255
/dev/pts/3:empty:3099:3158:3158:0,1,2
/dev/pts/3:empty:3099:3158:3170:1,2
/dev/pts/3:empty:3099:3176:3176:15,16,17,18,19
/dev/pts/3:empty:3099:3184:3184:0,1,2,5,6,7

The format is:

TTY_NAME:USER:SID:PGID:PID:FD1,FD2,...,FDn

The fields are:

  • TTY_NAME: tty name
  • USER: user name (or uid if no match in /etc/passwd)
  • SID: session ID
  • PGID: process group ID
  • PID: process ID
  • FDs: file descriptors which this process has open to the controlling tty.

Note:

  • Running ctty without any arguments will attempt to return the results for all ttys.
  • The -v switch will give a different output format that is a bit easier to read, though much longer and not fit for scripting.

libctty Usage

This is best documented inside the source code. However, as a quick overview, libctty.h defines the following interfaces:

/* ctty_get_name() is used to discover the controlling tty for a process. */
char *ctty_get_name(int pid);
/* ctty_get_session() is used to map out the entire process session. */
struct sid_node *ctty_get_session(char *tty_name);
/* ctty_free_session() is used to release the session data structure. */
void ctty_free_session(struct sid_node *session);
/* ctty_stat_parse() will pull ctty and session related info from the processes stat file. */
int ctty_stat_parse(int pid, struct proc_stat *stat_info);
/* ctty_get_fds() returns the list of file descriptors open to the tty you're interested in. */
int ctty_get_fds(int pid, char *tty, int **fds);

Installation

git clone https://github.com/emptymonkey/ctty.git
cd ctty
make

About

A library and tool for discovering and mapping Controlling TTYs in Linux.

Resources

Stars

24 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ctty

ctty is a controlling tty discovery tool (and library) for Linux.

What is a tty?

In Linux, users can issue commands to the operating system through a command line. In the modern era, a command line is implemented as a shell attached to a pseudo-terminal. The pseudo-terminal itself is a type of tty and leverages the tty driver section of the Linux kernel.

What is a controlling tty?

A controlling tty is a tty that has a special relationship with a process session. When a tty is "controlling" for a session, it will send the session leader, and other members of that session, signals to help control the user experience.

What is a session?

Processes are grouped into process groups for job control. Process groups themselves are grouped together into a session to facilitate the resource sharing of a tty. The man page for credentials is an excellent resource on this topic.

What part of the operating system keeps track of all this?

The tty driver in the kernel will know what session ID a tty is "controlling" for. Likewise, every process in a session will know which tty is "controlling" for it. There is no single authoritative point on the topic and a stable system requires the cooperation of all the players involved.

This sounds totally crazy? How did it end up this way?

Back in late 1960s, computers were finally fast enough to interact with users in real time. Coincidentally, the old teletype terminals were broadly used throughout the telecommunications industry. The engineers of the day, being appropriately lazy, simply re-purposed this existing technology to fit their needs. This was the birth of the command line.

Make sure you read The TTY demystified by Linus Åkesson. His page is the most enlightening for this topic anywhere on the internet. Many thanks to Linus for putting it together!

How can you tell what the controlling tty is for any given process?

The ctermid function will return the name of the controlling tty for the process that calls it, but this output is not particularly helpful for discovery. This function exists only to aid in portability and will always return the string "/dev/tty" regardless of which terminal or pseudo-terminal device is controlling for the process.

Further, there is no system or library call that will report the controlling tty for another process. The stat file for any given process will contain that information, though not in a format easily consumed by humans:

tty_nr %d The controlling terminal of the process. (The minor device number is contained in
the combination of bits 31 to 20 and 7 to 0; the major device number is in bits
15 to 8.)

The "ps j -p PID" command will report the controlling tty in a human readable format for any given PID.

How can you tell which session is controlled by any given tty?

Traditionally, there is no easy way to see this information programmatically. (Again, examining the results of the "ps j" command will allow you to perform this discovery manually.) I wrote ctty to fill this gap. It does the needed detective work, and reports back to the user. libctty gives you a C interface to this functionality.

ctty Usage

usage: ctty [-v] [TTY_NAME]
-v	verbose reporting format

To see the session information for a particular tty:

empty@monkey:~$ ctty /dev/pts/3
/dev/pts/3:empty:3099:3099:3099:0,1,2,255
/dev/pts/3:empty:3099:3158:3158:0,1,2
/dev/pts/3:empty:3099:3158:3170:1,2
/dev/pts/3:empty:3099:3176:3176:15,16,17,18,19
/dev/pts/3:empty:3099:3184:3184:0,1,2,5,6,7

The format is:

TTY_NAME:USER:SID:PGID:PID:FD1,FD2,...,FDn

The fields are:

  • TTY_NAME: tty name
  • USER: user name (or uid if no match in /etc/passwd)
  • SID: session ID
  • PGID: process group ID
  • PID: process ID
  • FDs: file descriptors which this process has open to the controlling tty.

Note:

  • Running ctty without any arguments will attempt to return the results for all ttys.
  • The -v switch will give a different output format that is a bit easier to read, though much longer and not fit for scripting.

libctty Usage

This is best documented inside the source code. However, as a quick overview, libctty.h defines the following interfaces:

/* ctty_get_name() is used to discover the controlling tty for a process. */
char *ctty_get_name(int pid);
/* ctty_get_session() is used to map out the entire process session. */
struct sid_node *ctty_get_session(char *tty_name);
/* ctty_free_session() is used to release the session data structure. */
void ctty_free_session(struct sid_node *session);
/* ctty_stat_parse() will pull ctty and session related info from the processes stat file. */
int ctty_stat_parse(int pid, struct proc_stat *stat_info);
/* ctty_get_fds() returns the list of file descriptors open to the tty you're interested in. */
int ctty_get_fds(int pid, char *tty, int **fds);

Installation

git clone https://github.com/emptymonkey/ctty.git
cd ctty
make

About

A library and tool for discovering and mapping Controlling TTYs in Linux.

Resources

Stars

24 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ctty

ctty is a controlling tty discovery tool (and library) for Linux.

What is a tty?

In Linux, users can issue commands to the operating system through a command line. In the modern era, a command line is implemented as a shell attached to a pseudo-terminal. The pseudo-terminal itself is a type of tty and leverages the tty driver section of the Linux kernel.

What is a controlling tty?

A controlling tty is a tty that has a special relationship with a process session. When a tty is "controlling" for a session, it will send the session leader, and other members of that session, signals to help control the user experience.

What is a session?

Processes are grouped into process groups for job control. Process groups themselves are grouped together into a session to facilitate the resource sharing of a tty. The man page for credentials is an excellent resource on this topic.

What part of the operating system keeps track of all this?

The tty driver in the kernel will know what session ID a tty is "controlling" for. Likewise, every process in a session will know which tty is "controlling" for it. There is no single authoritative point on the topic and a stable system requires the cooperation of all the players involved.

This sounds totally crazy? How did it end up this way?

Back in late 1960s, computers were finally fast enough to interact with users in real time. Coincidentally, the old teletype terminals were broadly used throughout the telecommunications industry. The engineers of the day, being appropriately lazy, simply re-purposed this existing technology to fit their needs. This was the birth of the command line.

Make sure you read The TTY demystified by Linus Åkesson. His page is the most enlightening for this topic anywhere on the internet. Many thanks to Linus for putting it together!

How can you tell what the controlling tty is for any given process?

The ctermid function will return the name of the controlling tty for the process that calls it, but this output is not particularly helpful for discovery. This function exists only to aid in portability and will always return the string "/dev/tty" regardless of which terminal or pseudo-terminal device is controlling for the process.

Further, there is no system or library call that will report the controlling tty for another process. The stat file for any given process will contain that information, though not in a format easily consumed by humans:

tty_nr %d The controlling terminal of the process. (The minor device number is contained in
the combination of bits 31 to 20 and 7 to 0; the major device number is in bits
15 to 8.)

The "ps j -p PID" command will report the controlling tty in a human readable format for any given PID.

How can you tell which session is controlled by any given tty?

Traditionally, there is no easy way to see this information programmatically. (Again, examining the results of the "ps j" command will allow you to perform this discovery manually.) I wrote ctty to fill this gap. It does the needed detective work, and reports back to the user. libctty gives you a C interface to this functionality.

ctty Usage

usage: ctty [-v] [TTY_NAME]
-v	verbose reporting format

To see the session information for a particular tty:

empty@monkey:~$ ctty /dev/pts/3
/dev/pts/3:empty:3099:3099:3099:0,1,2,255
/dev/pts/3:empty:3099:3158:3158:0,1,2
/dev/pts/3:empty:3099:3158:3170:1,2
/dev/pts/3:empty:3099:3176:3176:15,16,17,18,19
/dev/pts/3:empty:3099:3184:3184:0,1,2,5,6,7

The format is:

TTY_NAME:USER:SID:PGID:PID:FD1,FD2,...,FDn

The fields are:

  • TTY_NAME: tty name
  • USER: user name (or uid if no match in /etc/passwd)
  • SID: session ID
  • PGID: process group ID
  • PID: process ID
  • FDs: file descriptors which this process has open to the controlling tty.

Note:

  • Running ctty without any arguments will attempt to return the results for all ttys.
  • The -v switch will give a different output format that is a bit easier to read, though much longer and not fit for scripting.

libctty Usage

This is best documented inside the source code. However, as a quick overview, libctty.h defines the following interfaces:

/* ctty_get_name() is used to discover the controlling tty for a process. */
char *ctty_get_name(int pid);
/* ctty_get_session() is used to map out the entire process session. */
struct sid_node *ctty_get_session(char *tty_name);
/* ctty_free_session() is used to release the session data structure. */
void ctty_free_session(struct sid_node *session);
/* ctty_stat_parse() will pull ctty and session related info from the processes stat file. */
int ctty_stat_parse(int pid, struct proc_stat *stat_info);
/* ctty_get_fds() returns the list of file descriptors open to the tty you're interested in. */
int ctty_get_fds(int pid, char *tty, int **fds);

Installation

git clone https://github.com/emptymonkey/ctty.git
cd ctty
make

About

A library and tool for discovering and mapping Controlling TTYs in Linux.

Resources

Stars

24 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ctty

ctty is a controlling tty discovery tool (and library) for Linux.

What is a tty?

In Linux, users can issue commands to the operating system through a command line. In the modern era, a command line is implemented as a shell attached to a pseudo-terminal. The pseudo-terminal itself is a type of tty and leverages the tty driver section of the Linux kernel.

What is a controlling tty?

A controlling tty is a tty that has a special relationship with a process session. When a tty is "controlling" for a session, it will send the session leader, and other members of that session, signals to help control the user experience.

What is a session?

Processes are grouped into process groups for job control. Process groups themselves are grouped together into a session to facilitate the resource sharing of a tty. The man page for credentials is an excellent resource on this topic.

What part of the operating system keeps track of all this?

The tty driver in the kernel will know what session ID a tty is "controlling" for. Likewise, every process in a session will know which tty is "controlling" for it. There is no single authoritative point on the topic and a stable system requires the cooperation of all the players involved.

This sounds totally crazy? How did it end up this way?

Back in late 1960s, computers were finally fast enough to interact with users in real time. Coincidentally, the old teletype terminals were broadly used throughout the telecommunications industry. The engineers of the day, being appropriately lazy, simply re-purposed this existing technology to fit their needs. This was the birth of the command line.

Make sure you read The TTY demystified by Linus Åkesson. His page is the most enlightening for this topic anywhere on the internet. Many thanks to Linus for putting it together!

How can you tell what the controlling tty is for any given process?

The ctermid function will return the name of the controlling tty for the process that calls it, but this output is not particularly helpful for discovery. This function exists only to aid in portability and will always return the string "/dev/tty" regardless of which terminal or pseudo-terminal device is controlling for the process.

Further, there is no system or library call that will report the controlling tty for another process. The stat file for any given process will contain that information, though not in a format easily consumed by humans:

tty_nr %d The controlling terminal of the process. (The minor device number is contained in
the combination of bits 31 to 20 and 7 to 0; the major device number is in bits
15 to 8.)

The "ps j -p PID" command will report the controlling tty in a human readable format for any given PID.

How can you tell which session is controlled by any given tty?

Traditionally, there is no easy way to see this information programmatically. (Again, examining the results of the "ps j" command will allow you to perform this discovery manually.) I wrote ctty to fill this gap. It does the needed detective work, and reports back to the user. libctty gives you a C interface to this functionality.

ctty Usage

usage: ctty [-v] [TTY_NAME]
-v	verbose reporting format

To see the session information for a particular tty:

empty@monkey:~$ ctty /dev/pts/3
/dev/pts/3:empty:3099:3099:3099:0,1,2,255
/dev/pts/3:empty:3099:3158:3158:0,1,2
/dev/pts/3:empty:3099:3158:3170:1,2
/dev/pts/3:empty:3099:3176:3176:15,16,17,18,19
/dev/pts/3:empty:3099:3184:3184:0,1,2,5,6,7

The format is:

TTY_NAME:USER:SID:PGID:PID:FD1,FD2,...,FDn

The fields are:

  • TTY_NAME: tty name
  • USER: user name (or uid if no match in /etc/passwd)
  • SID: session ID
  • PGID: process group ID
  • PID: process ID
  • FDs: file descriptors which this process has open to the controlling tty.

Note:

  • Running ctty without any arguments will attempt to return the results for all ttys.
  • The -v switch will give a different output format that is a bit easier to read, though much longer and not fit for scripting.

libctty Usage

This is best documented inside the source code. However, as a quick overview, libctty.h defines the following interfaces:

/* ctty_get_name() is used to discover the controlling tty for a process. */
char *ctty_get_name(int pid);
/* ctty_get_session() is used to map out the entire process session. */
struct sid_node *ctty_get_session(char *tty_name);
/* ctty_free_session() is used to release the session data structure. */
void ctty_free_session(struct sid_node *session);
/* ctty_stat_parse() will pull ctty and session related info from the processes stat file. */
int ctty_stat_parse(int pid, struct proc_stat *stat_info);
/* ctty_get_fds() returns the list of file descriptors open to the tty you're interested in. */
int ctty_get_fds(int pid, char *tty, int **fds);

Installation

git clone https://github.com/emptymonkey/ctty.git
cd ctty
make

About

A library and tool for discovering and mapping Controlling TTYs in Linux.

Resources

Stars

24 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ctty

ctty is a controlling tty discovery tool (and library) for Linux.

What is a tty?

In Linux, users can issue commands to the operating system through a command line. In the modern era, a command line is implemented as a shell attached to a pseudo-terminal. The pseudo-terminal itself is a type of tty and leverages the tty driver section of the Linux kernel.

What is a controlling tty?

A controlling tty is a tty that has a special relationship with a process session. When a tty is "controlling" for a session, it will send the session leader, and other members of that session, signals to help control the user experience.

What is a session?

Processes are grouped into process groups for job control. Process groups themselves are grouped together into a session to facilitate the resource sharing of a tty. The man page for credentials is an excellent resource on this topic.

What part of the operating system keeps track of all this?

The tty driver in the kernel will know what session ID a tty is "controlling" for. Likewise, every process in a session will know which tty is "controlling" for it. There is no single authoritative point on the topic and a stable system requires the cooperation of all the players involved.

This sounds totally crazy? How did it end up this way?

Back in late 1960s, computers were finally fast enough to interact with users in real time. Coincidentally, the old teletype terminals were broadly used throughout the telecommunications industry. The engineers of the day, being appropriately lazy, simply re-purposed this existing technology to fit their needs. This was the birth of the command line.

Make sure you read The TTY demystified by Linus Åkesson. His page is the most enlightening for this topic anywhere on the internet. Many thanks to Linus for putting it together!

How can you tell what the controlling tty is for any given process?

The ctermid function will return the name of the controlling tty for the process that calls it, but this output is not particularly helpful for discovery. This function exists only to aid in portability and will always return the string "/dev/tty" regardless of which terminal or pseudo-terminal device is controlling for the process.

Further, there is no system or library call that will report the controlling tty for another process. The stat file for any given process will contain that information, though not in a format easily consumed by humans:

tty_nr %d The controlling terminal of the process. (The minor device number is contained in
the combination of bits 31 to 20 and 7 to 0; the major device number is in bits
15 to 8.)

The "ps j -p PID" command will report the controlling tty in a human readable format for any given PID.

How can you tell which session is controlled by any given tty?

Traditionally, there is no easy way to see this information programmatically. (Again, examining the results of the "ps j" command will allow you to perform this discovery manually.) I wrote ctty to fill this gap. It does the needed detective work, and reports back to the user. libctty gives you a C interface to this functionality.

ctty Usage

usage: ctty [-v] [TTY_NAME]
-v	verbose reporting format

To see the session information for a particular tty:

empty@monkey:~$ ctty /dev/pts/3
/dev/pts/3:empty:3099:3099:3099:0,1,2,255
/dev/pts/3:empty:3099:3158:3158:0,1,2
/dev/pts/3:empty:3099:3158:3170:1,2
/dev/pts/3:empty:3099:3176:3176:15,16,17,18,19
/dev/pts/3:empty:3099:3184:3184:0,1,2,5,6,7

The format is:

TTY_NAME:USER:SID:PGID:PID:FD1,FD2,...,FDn

The fields are:

  • TTY_NAME: tty name
  • USER: user name (or uid if no match in /etc/passwd)
  • SID: session ID
  • PGID: process group ID
  • PID: process ID
  • FDs: file descriptors which this process has open to the controlling tty.

Note:

  • Running ctty without any arguments will attempt to return the results for all ttys.
  • The -v switch will give a different output format that is a bit easier to read, though much longer and not fit for scripting.

libctty Usage

This is best documented inside the source code. However, as a quick overview, libctty.h defines the following interfaces:

/* ctty_get_name() is used to discover the controlling tty for a process. */
char *ctty_get_name(int pid);
/* ctty_get_session() is used to map out the entire process session. */
struct sid_node *ctty_get_session(char *tty_name);
/* ctty_free_session() is used to release the session data structure. */
void ctty_free_session(struct sid_node *session);
/* ctty_stat_parse() will pull ctty and session related info from the processes stat file. */
int ctty_stat_parse(int pid, struct proc_stat *stat_info);
/* ctty_get_fds() returns the list of file descriptors open to the tty you're interested in. */
int ctty_get_fds(int pid, char *tty, int **fds);

Installation

git clone https://github.com/emptymonkey/ctty.git
cd ctty
make

About

A library and tool for discovering and mapping Controlling TTYs in Linux.

Resources

Stars

24 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ctty

ctty is a controlling tty discovery tool (and library) for Linux.

What is a tty?

In Linux, users can issue commands to the operating system through a command line. In the modern era, a command line is implemented as a shell attached to a pseudo-terminal. The pseudo-terminal itself is a type of tty and leverages the tty driver section of the Linux kernel.

What is a controlling tty?

A controlling tty is a tty that has a special relationship with a process session. When a tty is "controlling" for a session, it will send the session leader, and other members of that session, signals to help control the user experience.

What is a session?

Processes are grouped into process groups for job control. Process groups themselves are grouped together into a session to facilitate the resource sharing of a tty. The man page for credentials is an excellent resource on this topic.

What part of the operating system keeps track of all this?

The tty driver in the kernel will know what session ID a tty is "controlling" for. Likewise, every process in a session will know which tty is "controlling" for it. There is no single authoritative point on the topic and a stable system requires the cooperation of all the players involved.

This sounds totally crazy? How did it end up this way?

Back in late 1960s, computers were finally fast enough to interact with users in real time. Coincidentally, the old teletype terminals were broadly used throughout the telecommunications industry. The engineers of the day, being appropriately lazy, simply re-purposed this existing technology to fit their needs. This was the birth of the command line.

Make sure you read The TTY demystified by Linus Åkesson. His page is the most enlightening for this topic anywhere on the internet. Many thanks to Linus for putting it together!

How can you tell what the controlling tty is for any given process?

The ctermid function will return the name of the controlling tty for the process that calls it, but this output is not particularly helpful for discovery. This function exists only to aid in portability and will always return the string "/dev/tty" regardless of which terminal or pseudo-terminal device is controlling for the process.

Further, there is no system or library call that will report the controlling tty for another process. The stat file for any given process will contain that information, though not in a format easily consumed by humans:

tty_nr %d The controlling terminal of the process. (The minor device number is contained in
the combination of bits 31 to 20 and 7 to 0; the major device number is in bits
15 to 8.)

The "ps j -p PID" command will report the controlling tty in a human readable format for any given PID.

How can you tell which session is controlled by any given tty?

Traditionally, there is no easy way to see this information programmatically. (Again, examining the results of the "ps j" command will allow you to perform this discovery manually.) I wrote ctty to fill this gap. It does the needed detective work, and reports back to the user. libctty gives you a C interface to this functionality.

ctty Usage

usage: ctty [-v] [TTY_NAME]
-v	verbose reporting format

To see the session information for a particular tty:

empty@monkey:~$ ctty /dev/pts/3
/dev/pts/3:empty:3099:3099:3099:0,1,2,255
/dev/pts/3:empty:3099:3158:3158:0,1,2
/dev/pts/3:empty:3099:3158:3170:1,2
/dev/pts/3:empty:3099:3176:3176:15,16,17,18,19
/dev/pts/3:empty:3099:3184:3184:0,1,2,5,6,7

The format is:

TTY_NAME:USER:SID:PGID:PID:FD1,FD2,...,FDn

The fields are:

  • TTY_NAME: tty name
  • USER: user name (or uid if no match in /etc/passwd)
  • SID: session ID
  • PGID: process group ID
  • PID: process ID
  • FDs: file descriptors which this process has open to the controlling tty.

Note:

  • Running ctty without any arguments will attempt to return the results for all ttys.
  • The -v switch will give a different output format that is a bit easier to read, though much longer and not fit for scripting.

libctty Usage

This is best documented inside the source code. However, as a quick overview, libctty.h defines the following interfaces:

/* ctty_get_name() is used to discover the controlling tty for a process. */
char *ctty_get_name(int pid);
/* ctty_get_session() is used to map out the entire process session. */
struct sid_node *ctty_get_session(char *tty_name);
/* ctty_free_session() is used to release the session data structure. */
void ctty_free_session(struct sid_node *session);
/* ctty_stat_parse() will pull ctty and session related info from the processes stat file. */
int ctty_stat_parse(int pid, struct proc_stat *stat_info);
/* ctty_get_fds() returns the list of file descriptors open to the tty you're interested in. */
int ctty_get_fds(int pid, char *tty, int **fds);

Installation

git clone https://github.com/emptymonkey/ctty.git
cd ctty
make

About

A library and tool for discovering and mapping Controlling TTYs in Linux.

Resources

Stars

24 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages