sites

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

dwm-sshawarespawn-6.2.diff (8820B)


      1 From fc232a3075835e01c1dab6b199ec8817d911d0be Mon Sep 17 00:00:00 2001
      2 From: blatzfab <fabian.blatz@gmail.com>
      3 Date: Fri, 16 Oct 2020 09:44:24 +0000
      4 Subject: [PATCH] Adds ssh aware spawn command
      5 
      6 ---
      7  config.def.h |   2 +-
      8  config.mk    |   3 +-
      9  dwm.c        | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++
     10  3 files changed, 177 insertions(+), 2 deletions(-)
     11 
     12 diff --git a/config.def.h b/config.def.h
     13 index 1c0b587..1121d4d 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 6d36cb7..5272bdc 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=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
     42 diff --git a/dwm.c b/dwm.c
     43 index 4465af1..bd35817 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 @@ -171,6 +182,7 @@ static void focusmon(const Arg *arg);
     86  static void focusstack(const Arg *arg);
     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 @@ -206,6 +218,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 @@ -229,6 +243,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 @@ -267,6 +282,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 @@ -575,6 +591,63 @@ configurenotify(XEvent *e)
    119  	}
    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 +
    179  void
    180  configurerequest(XEvent *e)
    181  {
    182 @@ -899,6 +972,19 @@ getstate(Window w)
    183  	return result;
    184  }
    185  
    186 +int
    187 +getprocinfo(pid_t pid, proc_t *procinfo)
    188 +{
    189 +	int res = 1;
    190 +	if(!procinfo)
    191 +		return 0;
    192 +	PROCTAB *pt_ptr = openproc(PROC_FILLARG | PROC_EDITCMDLCVT | PROC_FILLSTATUS | PROC_PID, &pid);
    193 +	if(readproc(pt_ptr, procinfo))
    194 +		res = 0;
    195 +	closeproc(pt_ptr);
    196 +	return res;
    197 +}
    198 +
    199  int
    200  gettextprop(Window w, Atom atom, char *text, unsigned int size)
    201  {
    202 @@ -1023,6 +1109,7 @@ manage(Window w, XWindowAttributes *wa)
    203  
    204  	c = ecalloc(1, sizeof(Client));
    205  	c->win = w;
    206 +	c->pid = winpid(w);
    207  	/* geometry */
    208  	c->x = c->oldx = wa->x;
    209  	c->y = c->oldy = wa->y;
    210 @@ -1636,6 +1723,38 @@ sigchld(int unused)
    211  	while (0 < waitpid(-1, NULL, WNOHANG));
    212  }
    213  
    214 +void
    215 +spawnsshaware(const Arg *arg)
    216 +{
    217 +	if(selmon->sel) {
    218 +		char* sshcmdline = checksshsession(selmon->sel->pid);
    219 +		if(sshcmdline){
    220 +			const char* sshcmd[] = {"st", "-e", "/bin/bash", "-c", sshcmdline, NULL};
    221 +			Arg a = {.v=sshcmd};
    222 +			spawn(&a);
    223 +			free(sshcmdline);
    224 +		}else{
    225 +			spawn(arg);
    226 +		}
    227 +	}else{
    228 +		spawn(arg);
    229 +	}
    230 +}
    231 +
    232 +int
    233 +strtopid(char *s, pid_t *pid)
    234 +{
    235 +	long result = 0;
    236 +	char *eptr;
    237 +	if(!pid)
    238 +		return 0;
    239 +	result = strtol(s, &eptr, 10);
    240 +	if((eptr && *eptr!='\0') || errno == ERANGE)
    241 +		return 0;
    242 +	*pid=(pid_t) result;
    243 +	return 1;
    244 +}
    245 +
    246  void
    247  spawn(const Arg *arg)
    248  {
    249 @@ -2074,6 +2193,59 @@ wintomon(Window w)
    250  	return selmon;
    251  }
    252  
    253 +
    254 +pid_t
    255 +winpid(Window w)
    256 +{
    257 +	pid_t result = 0;
    258 +
    259 +	#ifdef __linux__
    260 +	xcb_res_client_id_spec_t spec = {0};
    261 +	spec.client = w;
    262 +	spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
    263 +
    264 +	xcb_generic_error_t *e = NULL;
    265 +	xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
    266 +	xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
    267 +
    268 +	if (!r)
    269 +		return (pid_t)0;
    270 +
    271 +	xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
    272 +	for (; i.rem; xcb_res_client_id_value_next(&i)) {
    273 +		spec = i.data->spec;
    274 +		if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
    275 +			uint32_t *t = xcb_res_client_id_value_value(i.data);
    276 +			result = *t;
    277 +			break;
    278 +		}
    279 +	}
    280 +
    281 +	free(r);
    282 +
    283 +	if (result == (pid_t)-1)
    284 +		result = 0;
    285 +
    286 +	#endif /* __linux__ */
    287 +
    288 +	#ifdef __OpenBSD__
    289 +        Atom type;
    290 +        int format;
    291 +        unsigned long len, bytes;
    292 +        unsigned char *prop;
    293 +        pid_t ret;
    294 +
    295 +        if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop)
    296 +               return 0;
    297 +
    298 +        ret = *(pid_t*)prop;
    299 +        XFree(prop);
    300 +        result = ret;
    301 +
    302 +	#endif /* __OpenBSD__ */
    303 +	return result;
    304 +}
    305 +
    306  /* There's no way to check accesses to destroyed windows, thus those cases are
    307   * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
    308   * default error handler, which may call exit. */
    309 @@ -2135,6 +2307,8 @@ main(int argc, char *argv[])
    310  		fputs("warning: no locale support\n", stderr);
    311  	if (!(dpy = XOpenDisplay(NULL)))
    312  		die("dwm: cannot open display");
    313 +	if (!(xcon = XGetXCBConnection(dpy)))
    314 +		die("dwm: cannot get xcb connection\n");
    315  	checkotherwm();
    316  	setup();
    317  #ifdef __OpenBSD__
    318 -- 
    319 2.28.0
    320