長い間失われ、ほとんど忘れられていました。
コードなどをリファクタリングするつもりですが、投稿はそのままです。このコードは32ビットシステムで使用されます。64ビット(またはその他)でどのように動作するかわかりません。
Cコードをどこかでハックする(PIDを抽出する)。
ハックして微調整するための投稿として残してください。私の現在のスクリプト全体(pid
オプションとして使用すると、「GUI-PID /プログラム」とその使用などが与えられたGUIで動作するはずですwmctrl -l -p
):
#!/bin/bash
# Please leave in place:
# http://vi.stackexchange.com/q/562/220
declare -i debug=1
declare -i pid=0
opt=j
# Usage
usage()
{
printf "Usage: %s [[opt] <PID>] | [[opt] <SWP>]\n" "${0/*\//}"
printf "\nopt:\n"
printf " j : Jump to window. (Default)\n"
printf " g : Get window. (E.g. from other workspace.)\n"
printf " l : List windows.\n"
printf " p : Only print. (With some extra info.)\n"
printf " s : Alias for j. (switch)\n"
printf " i : Alias for p. (information)\n"
printf " h : This help.\n"
printf "\n"
printf " <PID>: Process ID.\n"
printf " <SWP>: Read PID from Vim swap file.\n"
if (($#)); then
printf "\nERR: Unknown option %s\n" "$1"
fi
}
# Check if PID is a (G)Vim process
check_vim_pid()
{
local comm=
if ! [[ "$1" =~ ^[0-9]+$ ]];then
printf "ERR: Some weird thing has happened (P: $1).\n" >&2
exit 1
fi
comm="$(ps -p $1 -o comm=)"
[[ "$comm" =~ ^g?vim$ ]] && return 0 || return 1
}
# First two bytes should be b0, bc or bC
# Or in hex 0x6230, 0x6263 or 0x6243
check_b0()
{
local b01="${1:0:2}"
local b02="${1:2:2}"
if [[ $b01 != '62' ]] ||
([[ "$b02" != '30' && "$b02" != '63' && "$b02" != '43' ]]); then
return 1
fi
return 0
}
# Read PID from swap file.
# Se notes below for information.
vim_file=""
vim_swp_pid()
{
local swp="$1"
if ! [[ -r "$swp" ]]; then
printf "ERR: Not able to read $swp.\n" >&2
exit 2
fi
# Read b0 ID
local b0_id="$(xxd -l 2 -p "$swp")"
if ! check_b0 "$b0_id"; then
printf "ERR: Bad b0 ID in file (Not Vim-swap?): %s\n" "$b0_id" >&2
exit 3
fi
# Read PID from .swp file
local -a opid=($(xxd -s 24 -l 4 -p -c 1 "$swp"))
# Read int magic from .swp file
local magic=$(xxd -s 1008 -l 8 -p "$swp")
if [[ "${magic:0:8}" == "33323130" ]]; then
# Intel (LittleEndian)
pid=$(printf "%d" "0x${opid[3]}${opid[2]}${opid[1]}${opid[0]}")
elif [[ "${magic:0:8}" == "30313233" ]] ||
[[ "${magic:8:8}" == "30313233" ]]; then
# Motorola (BigEndian)
pid=$(printf "%d" "0x${opid[0]}${opid[1]}${opid[2]}${opid[3]}")
else
printf "ERR: Unknown byteroder: %s\n" "$magic" >&2
exit 4
fi
if ! check_vim_pid $pid; then
printf "N010: PID %d is not a Vim process.\n" "$pid" >&2
exit 10
fi
# Read file name
vim_file="$(xxd -s 108 -l 800 -ps "$1" | xxd -r -p)"
}
list_windows()
{
local winid desk pid host title comm
printf "%-10s %-3s %-6s %-16s %s\n" "WINID" "DSK" "PID" "COMM" "TITLE"
while IFS=$' \n' read -r winid desk pid host title; do
cf="/proc/$pid/comm"
[[ -r "$cf" ]] && read -r comm < "$cf"
printf "%10s %3d %6d %-16s %s\n" "$winid" "$desk" "$pid" "$comm" "$title"
done <<< "$(wmctrl -lp)"
}
# ------------------------- RUN -------------------------------------------- #
# Check if any arguments (a bit redundant, but OK)
if [[ -z "$1" ]]; then
usage >&2
exit 1
fi
# Loop arguments
while [[ "$1" ]]; do
if [[ "$1" =~ ^[0-9]+$ ]]; then
pid=$1
else
[[ "${1:0:1}" == "-" ]] && op=${1:1} || op=$1
case "$op" in
l) list_windows; exit 0;;
d) debug=1;;
h|-help) usage; exit 0;;
j|s|g|p|i) opt=$op;;
*)
if ! [[ -e "$1" ]]; then
usage >&2;
printf "\nE006: Can't stat \`%s'\n" "$1" >&2
exit 2
fi
vim_swp_pid "$1"
;;
esac
fi
shift
done
# Check if PID is set
if !(($pid)); then
usage >&2
printf "E011: PID required / Not found.\n" >&2
exit 11
fi
# Read WindowID, Workspace, PID of all-windows then filter by PID
read -r wid ws <<<$(wmctrl -l -p | awk -v p="$pid" '$3 == p {print $1,"\t",$2}')
pikoli()
{
local pp=$1
while :; do
awk '/^PPid:/{print $2;next}/^Name:/{print $2;next}' /proc/$pp/status 2>/dev/null || return
pp=$(awk '/^PPid:/{print $2;next}' /proc/$pp/status)
done
}
if ! [[ "$wid" ]]; then
pikoli $pid
printf "ERR: Window not fround from PID %d.\n" "$pid" >&2
exit 12
fi
# As most DM's names desktops from 1 and not 0, a more user-friendly number.
((dmws=ws + 1))
# Do the action!
((debug)) && printf "PID=%d, WID=%s, WS=%d\n" "$pid" "$wid" "$ws"
case "$opt" in
j|s) printf "Swithching to workspace %d raising window %s by PID %d.\n" \
"$dmws" "$wid" "$pid";
wmctrl -ia "$wid"
;;
g) printf "Getting window %s by PID %d from workspace %d.\n" \
"$wid" "$pid" "$dmws";
wmctrl -iR "$wid"
;;
i|p) printf "Window is on workspace %d having window ID %s by PID %d.\n" \
"$dmws" "$wid" "$pid";
xwininfo -id $wid
;;
esac
exit 0
#############################################################################
# ----------------- Vim swap file block zero format ----------------------- #
#############################################################################
#
# No script / bash code beyond here
#
NOTES 'memline.c:139':
:62
#define BLOCK0_ID0 'b' /* block 0 id 0 */
#define BLOCK0_ID1 '0' /* block 0 id 1 */
#define BLOCK0_ID1_C0 'c' /* block 0 id 1 'cm' 0 */
#define BLOCK0_ID1_C1 'C' /* block 0 id 1 'cm' 1 */
:124
#define B0_FNAME_SIZE_ORG 900 /* what it was in older versions */
#define B0_FNAME_SIZE_NOCRYPT 898 /* 2 bytes used for other things */
#define B0_FNAME_SIZE_CRYPT 890 /* 10 bytes used for other things */
#define B0_UNAME_SIZE 40
#define B0_HNAME_SIZE 40
/*
* Restrict the numbers to 32 bits, otherwise most compilers will complain.
* This won\'t detect a 64 bit machine that only swaps a byte in the top 32
* bits, but that is crazy anyway.
*/
#define B0_MAGIC_LONG 0x30313233L
#define B0_MAGIC_INT 0x20212223L
#define B0_MAGIC_SHORT 0x10111213L
#define B0_MAGIC_CHAR 0x55
:139
/*
* Block zero holds all info about the swap file.
*
* NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing
* swap files unusable!
*
* If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in vim.h!!
*
* This block is built up of single bytes, to make it portable across
* different machines. b0_magic_* is used to check the byte order and size of
* variables, because the rest of the swap file is not portable.
*/
struct block0
{
char_u b0_id[2]; /* id for block 0: BLOCK0_ID0 and BLOCK0_ID1,
* BLOCK0_ID1_C0, BLOCK0_ID1_C1 */
char_u b0_version[10]; /* Vim version string */
char_u b0_page_size[4];/* number of bytes per page */
char_u b0_mtime[4]; /* last modification time of file */
char_u b0_ino[4]; /* inode of b0_fname */
char_u b0_pid[4]; /* process id of creator (or 0) */
char_u b0_uname[B0_UNAME_SIZE]; /* name of user (uid if no name) */
char_u b0_hname[B0_HNAME_SIZE]; /* host name (if it has a name) */
char_u b0_fname[B0_FNAME_SIZE_ORG]; /* name of file being edited */
long b0_magic_long; /* check for byte order of long */
int b0_magic_int; /* check for byte order of int */
short b0_magic_short; /* check for byte order of short */
char_u b0_magic_char; /* check for last char */
};
offs len what
0 2 id
2 10 version
12 4 bytes per page
16 4 mtime
20 4 inode
24 4 PID or 0
28 40 name of user or uid
68 40 host name
108 900 fname
1008 4/8/ magic long*
1012 4/8/ magic int*
1016 2/ magic short*
1018 1/ magic char*
Length of magics is arch dependant.
Offset for magic, in example above, is by standard 32 bit.