dwm-sshawarespawn-20201015-61bb8b2.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) 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