1# -*- coding: utf-8 -*-
2#
3# (c) Copyright 2015 HP Development Company, L.P.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18#
19# Author: Goutam Kodu, Amarnath Chitumalla
20#
21#
22#
23
24
25
26# Std Lib
27import sys
28import os
29from subprocess import Popen, PIPE
30import grp
31import fnmatch
32import tempfile
33import socket
34import struct
35import select
36import time
37import fcntl
38import errno
39import stat
40import string
41import glob
42import subprocess # TODO: Replace with subprocess (commands is deprecated in Python 3.0)
43import io
44import re
45import getpass
46import locale
47from .sixext.moves import html_entities
48
49# Local
50from .g import *
51from .codes import *
52from . import utils, tui
53from . import logger
54
55
56# System wide logger
57log = logger.Logger('', logger.Logger.LOG_LEVEL_INFO, logger.Logger.LOG_TO_CONSOLE)
58log.set_level('info')
59
60def running_as_root():
61    return os.geteuid() == 0
62
63def restart_cups():
64    if os.path.exists('/usr/local/etc/rc.d/cups'):
65        return '/usr/local/etc/rc.d/cups restart'
66
67    elif os.path.exists('/usr/local/etc/rc.d/cupsys'):
68        return '/usr/local/etc/rc.d/cupsys restart'
69
70    else:
71        return 'killall -HUP cupsd'
72
73def restart(passwordObj):
74    ok = False
75    shutdown = utils.which('shutdown')
76    if shutdown and passwordObj:
77        cmd = "%s -r now" % (os.path.join(shutdown, "shutdown"))
78        cmd = passwordObj.getAuthCmd() % cmd
79        status, output = utils.run(cmd, passwordObj, "Need authentication to restart system")
80
81        ok = (status == 0)
82    return ok
83
84
85def run_open_mdns_port(core, passwordObj, callback=None):
86    open_mdns_port_cmd = core.get_distro_ver_data('open_mdns_port')
87    log.debug(open_mdns_port_cmd)
88    if open_mdns_port_cmd and passwordObj:
89        x = 1
90        for cmd in open_mdns_port_cmd:
91            cmd = passwordObj.getAuthCmd() % cmd
92            status, output = utils.run(cmd, passwordObj, "Need authentication to open mdns port [%s]"%cmd)
93
94            if status != 0:
95                log.warn("An error occurred running '%s'" % cmd)
96                log.warn(output)
97
98            if callback is not None:
99                callback(cmd, "Open mDNS/Bonjour step %d" % x)
100
101            x += 1
102
103
104def run_hp_tools(cmd):
105    if cmd is not None:
106        hpCommand = utils.which(cmd, True)
107
108        if not hpCommand:
109            hpCommand = cmd
110
111        log.debug(hpCommand)
112        status, output = utils.run(hpCommand)
113        return status == 0
114    else:
115        log.error("Command not found")
116        return False
117
118
119def run_hp_tools_with_auth(cmd, passwordObj):
120    if cmd is not None and passwordObj  is not None :
121        hpCommand = utils.which(cmd,True)
122
123        if not hpCommand:   #if it is local command like. ./setup.py
124            hpCommand = cmd
125
126        hpCommand = passwordObj.getAuthCmd() % hpCommand
127
128        log.debug(hpCommand)
129        status, output = utils.run(hpCommand, passwordObj, "Need authentication to run %s command"%cmd)
130        return status == 0
131    else:
132        log.error("Command not found or password object is not valid")
133        return False
134
135
136# start_service() starts the services
137# Input:
138#       service_name (string) --> service name to be started.
139#       passwordObj     --> root required services, needs to pass base/password object
140# Output:
141#       ret_val (bool)  --> returns True, if service is started or already running also.
142#                       --> returns False, if failed to start service.
143def start_service( service_name, passwordObj):
144    ret_Val = False
145    if not service_name or not passwordObj:
146        return ret_Val
147
148    if utils.which('systemctl'):
149        cmd_status = passwordObj.getAuthCmd()%("systemctl status %s.service"%service_name)
150        log.debug(cmd_status)
151        sts,out = utils.run(cmd_status, passwordObj, "Need authentication to get %s service status"%service_name)
152        if sts ==0:
153            if 'stop' in out or 'inactive' in out:
154                cmd_start = passwordObj.getAuthCmd()%("systemctl start %s.service"%service_name)
155                log.debug("cmd_start=%s"%cmd_start)
156                sts,out = utils.run(cmd_start, passwordObj, "Need authentication to start/restart %s service"%service_name)
157                if sts ==0:
158                    ret_Val = True
159            else:
160                ret_Val = True
161        else:
162            log.error("Fail to start %s service, please start %s service manually."%(service_name,service_name))
163
164    elif utils.which('service'):
165        cmd_status = passwordObj.getAuthCmd()%("service %s status"%service_name)
166        log.debug(cmd_status)
167        sts,out = utils.run(cmd_status, passwordObj, "Need authentication to get %s service status"%service_name)
168        if sts ==0:
169            if 'stop' in out or 'inactive' in out:
170                cmd_start = passwordObj.getAuthCmd()%("service %s start"%service_name)
171                log.debug("cmd_start=%s"%cmd_start)
172                sts,out = utils.run(cmd_start, passwordObj, "Need authentication to start/restart %s service"%service_name)
173                if sts ==0:
174                    ret_Val = True
175            elif 'unrecognized service' in out:
176                log.error("Failed to Start since %s is unrecognized service"%service_name)
177            else:
178                ret_Val = True
179        else:
180            log.error("Fail to start %s service, please start %s service manually."%(service_name,service_name))
181
182    elif os.path.exists('/usr/local/etc/rc.d/%s'%service_name):
183        cmd_status = passwordObj.getAuthCmd()%('/usr/local/etc/rc.d/%s status'%service_name)
184        log.debug(cmd_status)
185        sts,out = utils.run(cmd_status, passwordObj, "Need authentication to get %s service status"%service_name)
186        if sts ==0:
187            if 'stop' in out or 'inactive' in out:
188                cmd_start = passwordObj.getAuthCmd()%('/usr/local/etc/rc.d/%s start'%service_name)
189                log.debug("cmd_start=%s"%cmd_start)
190                sts,out = utils.run(cmd_start, passwordObj, "Need authentication to start/restart %s service"%service_name)
191                if sts ==0:
192                    ret_Val = True
193            else:
194                ret_Val = True
195        else:
196            log.error("Fail to start %s service, please start %s service manually."%(service_name,service_name))
197    else:
198        if service_name == 'cups':
199            cmd = 'lpstat -r'
200            sts,out = utils.run(cmd, passwordObj, "Need authentication to get %s service status"%service_name)
201            if sts ==0 and 'is running' in out:
202                ret_Val = True
203            else:
204                log.error("service command not found, please start cups service manually.")
205        else:
206            log.error("Fail to start %s service, please start %s service manually."%(service_name,service_name))
207
208    return ret_Val
209
210
211def run_systray():
212    path = utils.which('hp-systray')
213    if path:
214        path = os.path.join(path, 'hp-systray')
215    else:
216        path = os.path.join(prop.home_dir, 'systray.py')
217
218    if not os.path.exists(path):
219        log.warn("Unable to start hp-systray")
220
221    log.debug("Running hp-systray: %s --force-startup" % path)
222    os.spawnlp(os.P_NOWAIT, path, 'hp-systray', '--force-startup', "--ignore-update-firsttime")
223    log.debug("Waiting for hp-systray to start...")
224    time.sleep(1)
225
226def disable_SmartInstall():
227    path = utils.which('hp-SIDisable',True)
228    if path:
229        param = '-'
230        sicmd = "%s %s" % (path,param)
231        if run_hp_tools(sicmd):
232            log.debug("Smart Install is disabled\n")
233        else:
234            log.error("Smart Install could not be disabled\n")
235    else:
236        try:
237            from . import pkit
238            plugin = PLUGIN_REQUIRED
239            plugin_reason = PLUGIN_REASON_NONE
240            ok, sudo_ok = pkit.run_plugin_command(plugin == PLUGIN_REQUIRED, plugin_reason)
241            if not ok or not sudo_ok:
242                log.error("Failed to install plug-in.")
243        except ImportError:
244            log.warn("Import error\n")
245
246
247def close_running_hp_processes():
248    # check systray is running?
249    status,output = utils.Is_Process_Running('hp-systray')
250    if status is True:
251        ok,choice = tui.enter_choice("\nSome HPLIP applications are running. Press 'y' to close applications or press 'n' to quit upgrade(y=yes*, n=no):",['y','n'],'y')
252        if not ok or choice =='n':
253            log.info("Manually close HPLIP applications and run hp-upgrade again.")
254            return False
255
256        try:
257        # dBus
258            from dbus import SystemBus, lowlevel
259        except ImportError:
260            log.error("Unable to load DBus.")
261            pass
262        else:
263            try:
264                args = ['', '', EVENT_SYSTEMTRAY_EXIT, prop.username, 0, '', '']
265                msg = lowlevel.SignalMessage('/', 'com.hplip.StatusService', 'Event')
266                msg.append(signature='ssisiss', *args)
267                log.debug("Sending close message to hp-systray ...")
268                SystemBus().send_message(msg)
269                time.sleep(0.5)
270            except:
271                log.error("Failed to send DBus message to hp-systray/hp-toolbox.")
272                pass
273
274    toolbox_status,output = utils.Is_Process_Running('hp-toolbox')
275
276    if toolbox_status is True:
277        log.error("Failed to close either HP-Toolbox/HP-Systray. Manually close and run hp-upgrade again.")
278        return False
279
280    return True
281