| /*--------------------------------------------------------- | |
| * Copyright 2021 The Go Authors. All rights reserved. | |
| * Licensed under the MIT License. See LICENSE in the project root for license information. | |
| *--------------------------------------------------------*/ | |
| 'use strict'; | |
| import { AttachItem, ProcessListCommand } from '../pickProcess'; | |
| // lsofDarwinCommand uses the lsof command to find the executable path. | |
| // Argument explanation: | |
| // - '-Pnl' disables the conversion of network numbers (n), user id numbers (l), | |
| // and port number (P) to potentially make the command run faster. | |
| // - '-F ptnc' specifies the output to be printed for use in another program | |
| // and to include the pid (p), file descriptor and type (t), and name (n). | |
| // - '-d txt' limits the files to be included to be those with file descriptor='txt'. | |
| export const lsofDarwinCommand: ProcessListCommand = { | |
| command: 'lsof', | |
| args: ['-Pnl', '-F', 'pn', '-d', 'txt'] | |
| }; | |
| export function parseLsofProcesses(processes: string): AttachItem[] { | |
| const lines: string[] = processes.split('\n'); | |
| return parseProcessesFromLsofArray(lines); | |
| } | |
| function parseProcessesFromLsofArray(processArray: string[]): AttachItem[] { | |
| const processEntries: AttachItem[] = []; | |
| let i = 0; | |
| while (i < processArray.length) { | |
| const line = processArray[i]; | |
| i++; | |
| if (!line) { | |
| continue; | |
| } | |
| // The output for each process begins with a line containing the pid. | |
| const out = line[0]; | |
| const val = line.substr(1); | |
| if (out !== 'p') { | |
| continue; | |
| } | |
| const processEntry: AttachItem = { id: val, label: '' }; | |
| // Loop through every file which will have 3 lines containing: f=filedescriptor, t=type, n=name. | |
| while (i < processArray.length && processArray[i].length > 0 && processArray[i][0] !== 'p') { | |
| // Assume the first file with type 'txt' is the executable | |
| if (!processEntry.executable) { | |
| const file: { | |
| fd?: string; | |
| name?: string; | |
| } = parseFile(i, processArray); | |
| processEntry.executable = file.name; | |
| } | |
| i += 2; | |
| } | |
| if (processEntry) { | |
| processEntries.push(processEntry); | |
| } | |
| } | |
| return processEntries; | |
| } | |
| function parseFile(start: number, lines: string[]): { fd?: string; name?: string } { | |
| const file: { | |
| fd?: string; | |
| name?: string; | |
| } = {}; | |
| for (let j = start; j < start + 2; j++) { | |
| const line = lines[j]; | |
| if (!line) { | |
| continue; | |
| } | |
| const out = line[0]; | |
| const val = line.substr(1); | |
| switch (out) { | |
| case 'f': | |
| file.fd = val; | |
| break; | |
| case 'n': | |
| file.name = val; | |
| break; | |
| } | |
| } | |
| return file; | |
| } |