sarugaku / shellingham

Tool to Detect Surrounding Shell
ISC License
228 stars 33 forks source link

BUG: detect_shell fails when process contains single quote/apostrophe #12

Closed r4lv closed 6 years ago

r4lv commented 6 years ago

I had the following process running in the background:

$ ps -ww -o pid= -o ppid= -o args=
...
  252   197 lame --silent -V 0 -h -r - /Users/r4lv/Je m'voyais déjà.mp3
...

(note the apostrophe)

…which leads to

In [9]: shellingham.detect_shell()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-9-fdb1f77cdcba> in <module>()
----> 1 shellingham.detect_shell()

~/.local/share/virtualenvs/test-shellingham-Ew4jglHR/lib/python3.6/site-packages/shellingham/__init__.py in detect_shell(pid, max_depth)
     20     except AttributeError:
     21         raise RuntimeError('get_shell not implemented for {0!r}'.format(name))
---> 22     shell = get_shell(pid, max_depth=max_depth)
     23     if shell:
     24         return shell

~/.local/share/virtualenvs/test-shellingham-Ew4jglHR/lib/python3.6/site-packages/shellingham/posix/__init__.py in get_shell(pid, max_depth)
     52     """
     53     pid = str(pid or os.getpid())
---> 54     mapping = _get_process_mapping()
     55     for proc_cmd in _iter_process_command(mapping, pid, max_depth):
     56         if proc_cmd.startswith('-'):    # Login shell! Let's use this.

~/.local/share/virtualenvs/test-shellingham-Ew4jglHR/lib/python3.6/site-packages/shellingham/posix/__init__.py in _get_process_mapping()
     13     for impl in (proc, ps):
     14         try:
---> 15             mapping = impl.get_process_mapping()
     16         except EnvironmentError:
     17             continue

~/.local/share/virtualenvs/test-shellingham-Ew4jglHR/lib/python3.6/site-packages/shellingham/posix/ps.py in get_process_mapping()
     32             continue
     33         processes[pid] = Process(
---> 34             args=tuple(shlex.split(args)), pid=pid, ppid=ppid,
     35         )
     36     return processes

/usr/local/var/pyenv/versions/3.6.5/lib/python3.6/shlex.py in split(s, comments, posix)
    303     if not comments:
    304         lex.commenters = ''
--> 305     return list(lex)
    306 
    307 

/usr/local/var/pyenv/versions/3.6.5/lib/python3.6/shlex.py in __next__(self)
    293 
    294     def __next__(self):
--> 295         token = self.get_token()
    296         if token == self.eof:
    297             raise StopIteration

/usr/local/var/pyenv/versions/3.6.5/lib/python3.6/shlex.py in get_token(self)
    103             return tok
    104         # No pushback.  Get a token.
--> 105         raw = self.read_token()
    106         # Handle inclusions
    107         if self.source is not None:

/usr/local/var/pyenv/versions/3.6.5/lib/python3.6/shlex.py in read_token(self)
    185                         print("shlex: I see EOF in quotes state")
    186                     # XXX what error should be raised here?
--> 187                     raise ValueError("No closing quotation")
    188                 if nextchar == self.state:
    189                     if not self.posix:

ValueError: No closing quotation

Maybe the ps output lines which cannot be parsed using shlex.split could be skipped?

python 3.6.5 (pyenv) shellingham 1.2.6 macOS High Sierra 10.13.4

uranusjr commented 6 years ago

I think this may have exposed a deeper bug. Maybe it is wrong to parse the command line with shlex.split() in the first place.