sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

dwm-sshawarespawn-20201015-61bb8b2.diff (8906B)


      1 From b9b693eafe2925f323f54ff6444e09dbe8d9591a Mon Sep 17 00:00:00 2001
      2 From: blatzfab <fabian.blatz@gmail.com>
      3 Date: Thu, 15 Oct 2020 21:28:36 +0000
      4 Subject: [PATCH] Adds ssh aware spawn command
      5 
      6 ---
      7  config.def.h |   2 +-
      8  config.mk    |   3 +-
      9  dwm.c        | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++
     10  3 files changed, 176 insertions(+), 2 deletions(-)
     11 
     12 diff --git a/config.def.h b/config.def.h
     13 index 1c0b587..1a26f32 100644
     14 --- a/config.def.h
     15 +++ b/config.def.h
     16 @@ -62,7 +62,7 @@ static const char *termcmd[]  = { "st", NULL };
     17  static Key keys[] = {
     18  	/* modifier                     key        function        argument */
     19  	{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } },
     20 -	{ MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } },
     21 +	{ MODKEY|ShiftMask,       	XK_Return, spawnsshaware,  {.v = termcmd } },
     22  	{ MODKEY,                       XK_b,      togglebar,      {0} },
     23  	{ MODKEY,                       XK_j,      focusstack,     {.i = +1 } },
     24  	{ MODKEY,                       XK_k,      focusstack,     {.i = -1 } },
     25 diff --git a/config.mk b/config.mk
     26 index 7084c33..bc99153 100644
     27 --- a/config.mk
     28 +++ b/config.mk
     29 @@ -19,10 +19,11 @@ FREETYPELIBS = -lfontconfig -lXft
     30  FREETYPEINC = /usr/include/freetype2
     31  # OpenBSD (uncomment)
     32  #FREETYPEINC = ${X11INC}/freetype2
     33 +#KVMLIB = -lkvm
     34  
     35  # includes and libs
     36  INCS = -I${X11INC} -I${FREETYPEINC}
     37 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
     38 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} -lprocps
     39  
     40  # flags
     41  CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
     42 diff --git a/dwm.c b/dwm.c
     43 index 664c527..0f623ea 100644
     44 --- a/dwm.c
     45 +++ b/dwm.c
     46 @@ -28,6 +28,8 @@
     47  #include <stdlib.h>
     48  #include <string.h>
     49  #include <unistd.h>
     50 +#include <proc/readproc.h>
     51 +#include <sys/stat.h>
     52  #include <sys/types.h>
     53  #include <sys/wait.h>
     54  #include <X11/cursorfont.h>
     55 @@ -40,6 +42,12 @@
     56  #include <X11/extensions/Xinerama.h>
     57  #endif /* XINERAMA */
     58  #include <X11/Xft/Xft.h>
     59 +#include <X11/Xlib-xcb.h>
     60 +#include <xcb/res.h>
     61 +#ifdef __OpenBSD__
     62 +#include <sys/sysctl.h>
     63 +#include <kvm.h>
     64 +#endif /* __OpenBSD */
     65  
     66  #include "drw.h"
     67  #include "util.h"
     68 @@ -93,6 +101,7 @@ struct Client {
     69  	int bw, oldbw;
     70  	unsigned int tags;
     71  	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
     72 +	pid_t pid;
     73  	Client *next;
     74  	Client *snext;
     75  	Monitor *mon;
     76 @@ -156,6 +165,8 @@ static void clientmessage(XEvent *e);
     77  static void configure(Client *c);
     78  static void configurenotify(XEvent *e);
     79  static void configurerequest(XEvent *e);
     80 +static char* checksshsession(pid_t process);
     81 +static int checkparents(pid_t pid, pid_t target);
     82  static Monitor *createmon(void);
     83  static void destroynotify(XEvent *e);
     84  static void detach(Client *c);
     85 @@ -172,6 +183,7 @@ static void focusstack(const Arg *arg);
     86  static Atom getatomprop(Client *c, Atom prop);
     87  static int getrootptr(int *x, int *y);
     88  static long getstate(Window w);
     89 +static int getprocinfo(pid_t pid, proc_t *procinfo);
     90  static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
     91  static void grabbuttons(Client *c, int focused);
     92  static void grabkeys(void);
     93 @@ -207,6 +219,8 @@ static void seturgent(Client *c, int urg);
     94  static void showhide(Client *c);
     95  static void sigchld(int unused);
     96  static void spawn(const Arg *arg);
     97 +static void spawnsshaware(const Arg *arg);
     98 +static int strtopid(char *s, pid_t *pid);
     99  static void tag(const Arg *arg);
    100  static void tagmon(const Arg *arg);
    101  static void tile(Monitor *);
    102 @@ -230,6 +244,7 @@ static void updatewmhints(Client *c);
    103  static void view(const Arg *arg);
    104  static Client *wintoclient(Window w);
    105  static Monitor *wintomon(Window w);
    106 +static pid_t winpid(Window w);
    107  static int xerror(Display *dpy, XErrorEvent *ee);
    108  static int xerrordummy(Display *dpy, XErrorEvent *ee);
    109  static int xerrorstart(Display *dpy, XErrorEvent *ee);
    110 @@ -268,6 +283,7 @@ static Display *dpy;
    111  static Drw *drw;
    112  static Monitor *mons, *selmon;
    113  static Window root, wmcheckwin;
    114 +static xcb_connection_t *xcon;
    115  
    116  /* configuration, allows nested code to access above variables */
    117  #include "config.h"
    118 @@ -628,6 +644,62 @@ configurerequest(XEvent *e)
    119  	XSync(dpy, False);
    120  }
    121  
    122 +int
    123 +checkparents(pid_t pid, pid_t target)
    124 +{
    125 +	proc_t *pinf = calloc(1, sizeof(proc_t));
    126 +	pid_t current = pid;
    127 +
    128 +	while(current!=(pid_t)0 && current!=(pid_t)1 && current!=target){
    129 +		getprocinfo(current, pinf);
    130 +		current = pinf->ppid;
    131 +	}
    132 +	freeproc(pinf);
    133 +	if(current==target)
    134 +		return 1;
    135 +	return 0;
    136 +}
    137 +
    138 +char*
    139 +checksshsession(pid_t process)
    140 +{
    141 +	struct dirent *dp;
    142 +	DIR *dfd;
    143 +	const char *dir = "/proc";
    144 +	char filename_qfd[100] ;
    145 +	pid_t pid;
    146 +	proc_t* process_info = calloc(1, sizeof(proc_t));
    147 +	struct stat stbuf;
    148 +	char* res = 0;
    149 +
    150 +	if ((dfd = opendir(dir)) == NULL) {
    151 +		fprintf(stderr, "Can't open %s\n", dir);
    152 +		freeproc(process_info);
    153 +		return 0;
    154 +	}
    155 +
    156 +	while ((dp = readdir(dfd)) != NULL && res == 0) {
    157 +		sprintf( filename_qfd , "%s/%s",dir,dp->d_name);
    158 +		if(stat(filename_qfd,&stbuf ) == -1) {
    159 +			fprintf(stderr, "Unable to stat file: %s\n",filename_qfd);
    160 +			continue;
    161 +		}
    162 +		if (((stbuf.st_mode & S_IFMT) == S_IFDIR) && strtopid(dp->d_name, &pid)) {
    163 +			getprocinfo(pid, process_info);
    164 +			if(!process_info->cmdline)
    165 +				continue;
    166 +			char* cmdline = *process_info->cmdline;
    167 +			if(strncmp("ssh ", cmdline, 4) == 0 && checkparents(pid, process)){
    168 +				res = calloc(strlen(cmdline)+1, sizeof(char));
    169 +				strcpy(res, cmdline);
    170 +			}
    171 +		}
    172 +	}
    173 +	freeproc(process_info);
    174 +	free(dfd);
    175 +	return res;
    176 +}
    177 +
    178  Monitor *
    179  createmon(void)
    180  {
    181 @@ -900,6 +972,19 @@ getstate(Window w)
    182  	return result;
    183  }
    184  
    185 +int
    186 +getprocinfo(pid_t pid, proc_t *procinfo)
    187 +{
    188 +	int res = 1;
    189 +	if(!procinfo)
    190 +	return 0;
    191 +	PROCTAB *pt_ptr = openproc(PROC_FILLARG | PROC_EDITCMDLCVT | PROC_FILLSTATUS | PROC_PID, &pid);
    192 +	if(readproc(pt_ptr, procinfo))
    193 +		res = 0;
    194 +	closeproc(pt_ptr);
    195 +	return res;
    196 +}
    197 +
    198  int
    199  gettextprop(Window w, Atom atom, char *text, unsigned int size)
    200  {
    201 @@ -1024,6 +1109,7 @@ manage(Window w, XWindowAttributes *wa)
    202  
    203  	c = ecalloc(1, sizeof(Client));
    204  	c->win = w;
    205 +	c->pid = winpid(w);
    206  	/* geometry */
    207  	c->x = c->oldx = wa->x;
    208  	c->y = c->oldy = wa->y;
    209 @@ -1637,6 +1723,38 @@ sigchld(int unused)
    210  	while (0 < waitpid(-1, NULL, WNOHANG));
    211  }
    212  
    213 +void
    214 +spawnsshaware(const Arg *arg)
    215 +{
    216 +	if(selmon->sel) {
    217 +		char* sshcmdline = checksshsession(selmon->sel->pid);
    218 +		if(sshcmdline){
    219 +			const char* sshcmd[] = {"st", "-e", "/bin/bash", "-c", sshcmdline, NULL};
    220 +			Arg a = {.v=sshcmd};
    221 +			spawn(&a);
    222 +			free(sshcmdline);
    223 +		}else{
    224 +			spawn(arg);
    225 +		}
    226 +	}else{
    227 +		spawn(arg);
    228 +	}
    229 +}
    230 +
    231 +int
    232 +strtopid(char *s, pid_t *pid)
    233 +{
    234 +       long result = 0;
    235 +       char *eptr;
    236 +       if(!pid)
    237 +               return 0;
    238 +       result = strtol(s, &eptr, 10);
    239 +       if((eptr && *eptr!='\0') || errno == ERANGE)
    240 +               return 0;
    241 +       *pid=(pid_t) result;
    242 +       return 1;
    243 +}
    244 +
    245  void
    246  spawn(const Arg *arg)
    247  {
    248 @@ -2077,6 +2195,59 @@ wintomon(Window w)
    249  	return selmon;
    250  }
    251  
    252 +pid_t
    253 +winpid(Window w)
    254 +{
    255 +
    256 +	pid_t result = 0;
    257 +
    258 +	#ifdef __linux__
    259 +	xcb_res_client_id_spec_t spec = {0};
    260 +	spec.client = w;
    261 +	spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
    262 +
    263 +	xcb_generic_error_t *e = NULL;
    264 +	xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
    265 +	xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
    266 +
    267 +	if (!r)
    268 +		return (pid_t)0;
    269 +
    270 +	xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
    271 +	for (; i.rem; xcb_res_client_id_value_next(&i)) {
    272 +		spec = i.data->spec;
    273 +		if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
    274 +			uint32_t *t = xcb_res_client_id_value_value(i.data);
    275 +			result = *t;
    276 +			break;
    277 +		}
    278 +	}
    279 +
    280 +	free(r);
    281 +
    282 +	if (result == (pid_t)-1)
    283 +		result = 0;
    284 +
    285 +	#endif /* __linux__ */
    286 +
    287 +	#ifdef __OpenBSD__
    288 +        Atom type;
    289 +        int format;
    290 +        unsigned long len, bytes;
    291 +        unsigned char *prop;
    292 +        pid_t ret;
    293 +
    294 +        if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop)
    295 +               return 0;
    296 +
    297 +        ret = *(pid_t*)prop;
    298 +        XFree(prop);
    299 +        result = ret;
    300 +
    301 +	#endif /* __OpenBSD__ */
    302 +	return result;
    303 +}
    304 +
    305  /* There's no way to check accesses to destroyed windows, thus those cases are
    306   * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
    307   * default error handler, which may call exit. */
    308 @@ -2138,6 +2309,8 @@ main(int argc, char *argv[])
    309  		fputs("warning: no locale support\n", stderr);
    310  	if (!(dpy = XOpenDisplay(NULL)))
    311  		die("dwm: cannot open display");
    312 +	if (!(xcon = XGetXCBConnection(dpy)))
    313 +		die("dwm: cannot get xcb connection\n");
    314  	checkotherwm();
    315  	setup();
    316  #ifdef __OpenBSD__
    317 -- 
    318 2.28.0
    319