This file is indexed.

/usr/share/awesome/lib/bashets.lua is in awesome-extra 2017110501.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
------------------------------------------------------------------------
-- Bashets - use your shellscript's output in Awesome3 widgets
--
-- @author Anton Lobov <ahmad200512@yandex.ru>
-- @copyright 2010-2012 Anton Lobov
--
-- @contributor Victor Unegbu (fixed issue with formatting)
--
-- @license GPLv3
-- @release 0.6.3 
------------------------------------------------------------------------

-- Grab only needed enviroment
local awful = require("awful")
local string = string
local io = io
local table = table
local pairs = pairs
local timer = timer
local type = type
local image = image
local capi = {oocairo = oocairo, timer = timer, dbus = dbus}
local tonumber = tonumber
local print = print
local error = error

--- Bashets module
local bashets = {}

-- Default paths
local script_path = "/usr/share/awesome/bashets/"
local tmp_folder = "/tmp/"

-- Utility functions table
local util = {}

-- Timer data
local timerdata = {}
local timers = {}

-- External mode data
local ewidgets = {}

-- Some default values
local defaults = {}
defaults.update_time = 1
defaults.file_update_time = 2
defaults.format_string = "$1"
defaults.separator = " "
defaults.updater = "runner.sh"

-- State variable
local is_running = false

-- # Utility functions

--- Split string by separator into table
-- @param str String to split
-- @param sep Separator to use
function util.split(str, sep)
	if sep == nil then
		return {str}
	end

	local parts = {} --parts array
	local first = 1
	local ostart, oend = string.find(str, sep, first, true) --regexp disabled search

	while ostart do
		local part = string.sub(str, first, ostart - 1)
		table.insert(parts, part)
		first = oend + 1
		ostart, oend = string.find(str, sep, first, true)
	end

	local part = string.sub(str, first)
	table.insert(parts, part)

	return parts
end

function util.tmpkey(script)
	-- Replace all slashes with empty string so that /home/user1/script.sh 
	-- and /home/user2/script.sh will have different temporary files
	local tmpname = string.gsub(script, '/', '')

	-- Replace all spaces with dots so that "script.sh arg1"
	-- and "script.sh arg2" will have different temporary files
	tmpname = string.gsub(tmpname, '%s+', '.')

	return tmpname
end

function util.tmpname(script)
	-- Generated script-parameter unique temporary file path
	local file = tmp_folder .. util.tmpkey(script) .. '.bashets.out'

	return file
end

function util.fullpath(script)
	if string.find(script, '^/') == nil then
		script = script_path .. script
	end

	return script
end

--- Execute a command and write it's output to temporary file
-- @param script Script to execute
-- @param file File for script output
function util.execfile(script, file)
	-- Spawn command and redirect it's output to file
	awful.util.spawn_with_shell(script .. " > " .. file)
end


function util.readstring(str, sep)
	if sep == nil then
		return str
	else
		parts = util.split(str, sep);
		return parts
	end
end

--- Read temporary file to a table or string
-- @param file File to be read
-- @param israw If true, return raw string, not table
function util.readfile(file, sep)
	local fh = io.input(file)
	local str = fh:read("*all");
	io.close(fh)

	return util.readstring(str, sep)
end

--- Read script output to a table or string
-- @param script Script to execute
-- @param israw If true, return raw string, not table
function util.readshell(script, sep)
	local str = awful.util.pread(script)

	return util.readstring(str, sep)
end

--- Format script output with user defined format string
-- @param output sep-separated string of values
-- @param format Format string
-- @param sep Separator of values in string
function util.format(parts, format, sep)
	-- For each part with number "k" replace corresponding "$k" variable in format string
	for k,part in pairs(parts) do
		local part = string.gsub(part, "%%", "%1%1") --percent fix for next gsub (bug found in Wicked)
		part = awful.util.escape(part) --escape XML entities for correct Pango markup
		format = string.gsub(format, "$" .. k, part)
	end

	return format
end

--- Add function to corresponding timer object (Awesome >= 3.4 timer API)
-- @param updtime Update time for widget, also dispatch time for timer
-- @param func Function to dispatch
function util.add_to_timings(updtime, func, force_new)
	local found = false

	-- Search for an existing timer at the same period
	for k,tmr in pairs(timerdata) do
		if tmr[1] == updtime and (force_new == nil or force_new == false) then
			table.insert(timerdata[k][2], func)
			found = true
		end
	end

	-- Add a new timer for period if not found
	if not found then
		table.insert(timerdata, {updtime, {func}})
	end
end

--- Create timer table to define timers for multiple widget updates
function util.create_timers_table()
	-- Parse table with timer data
	for _,tmr in pairs(timerdata) do
		-- Create timer for the period
		local t
		if capi.timer ~= nil then
			t = capi.timer {timeout = tmr[1]}
		else
			t = timer {timeout = tmr[1]}
		end
		-- Function to call all dispatched functions
		local f = function()
			for _, func in pairs(tmr[2]) do
				func()
			end
		end
		
		if t.add_signal ~= nil then
			t:add_signal("timeout", f)
		else
			t:connect_signal("timeout", f)
		end
		table.insert(timers, t)
	end
end

function util.update_widget_field(widget, valuess)
--	print(widget.type)
	if widget.type == "imagebox" then				--imagebox (old API)
		widget["image"] = image(valuess)
	elseif widget.set_image ~= nil then				--imagebox (new API)
		--widget["image"] = capi.oocairo.image_surface_create_from_png(valuess)
		--widget:set_image(capi.oocairo.image_surface_create_from_png(valuess))
		widget:set_image(valuess)
	elseif widget.type == "textbox" then				--textbox (old API)
		widget["text"] = valuess
	elseif widget.set_markup ~= nil then				--textbox (new API)
		widget:set_markup(valuess)
	--elseif widget["widget"] ~= nil then
		elseif widget.set_value ~= nil then				--progressbar
			widget:set_value(tonumber(valuess))
		elseif widget.add_value ~= nil then			--graph
			widget:add_value(tonumber(valuess))
		end
	--end
end

--- Update widget from values
function util.update_widget(widget, values, format)
	if widget ~= nil then
		if type(values) == "table" then
			util.update_widget_field(widget, util.format(values, format))			
		else
			util.update_widget_field(widget, values)
		end
	end
end

-- # Setter functions

--- Set path for scripts
-- @param path Path to set
function bashets.set_script_path(path)
	script_path = path
end

--- Set path for temporary files
-- @param path Path to set
function bashets.set_temporary_path(path)
	tmp_folder = path
end

--- Set default values
-- @param defs Table with defaults
function bashets.set_defaults(defs)
	if type(defs) == "table" then
		if defs.update_time ~= nil then
			defaults.update_time = defs.update_time
		end 
		if defs.file_update_time ~= nil then
			defaults.file_update_time = defs.file_update_time
		end 
		if defs.format_string ~= nil then
			defaults.format_string = defs.format_string
		end
		if defs.updater ~= nil then
			defaults.updater = defs.updater
		end 

		defaults.separator = defs.separator --now could be nil
	end
end


-- # Acting functions

--- Start widget updates
function bashets.start()
	-- Create timers table if not initialized or empty
	if (not timers) or table.maxn(timers) == 0 then
		util.create_timers_table()
	end
	-- Start all timers
	for _, tmr in pairs(timers) do
		tmr:start()
	end

	-- Kill all externals (if some were here from previous launch)
	--awful.util.spawn_with_shell('killall ' .. defaults.updater)

	-- Run all externals
	for _, wgt in pairs(ewidgets) do
		awful.util.spawn_with_shell(wgt.cmd)
	end
	is_running = true
end

--- Stop widget updates
function bashets.stop()
	-- Stop all timers
	for _, tmr in pairs(timers) do
		tmr:stop()
	end

	-- Kill all externals
	awful.util.spawn_with_shell('killall ' .. defaults.updater)

	is_running = false
end

--- Check whether updates are running
function bashets.get_running()
	return is_running
end

--- Toggle updates
function bashets.toggle()
	if is_running then
		bashets.start()
	else
		bashets.stop()
	end
end

--- Shedule function for timed execution
-- @param func Function to run
-- @param updatime Update time (optional)
function bashets.schedule(func, updtime)
	updtime = updtime or defaults.update_time
	if func ~= nil then
		util.add_to_timings(updtime, func)
	end
end

-- # Widget registration functions

--- General widget-callback registration function. For internal use, but if you need it, feel free to call it :)
-- @param data_provider Function that returns table of values
-- @param widget Widget to update, if null, nothing is updated
-- @param callback Callback to call after the update of values, if null, nothing is called
-- @param format Format string for widget //N.B.: it is not checked for null
function bashets.schedule_w(data_provider, widget, callback, format, updtime)
	if callback ~= nil and type(callback) == "function" then
		if widget ~= nil then
			bashets.schedule(function()
				local data = data_provider()
				util.update_widget(widget, data, format)
				callback(data)
			end, updtime)
		else
			bashets.schedule(function()
				local data = data_provider()
				callback(data)
			end, updtime)
		end
	elseif widget ~= nil then
		bashets.schedule(function()
			local data = data_provider()
			util.update_widget(widget, data, format)
		end, updtime)
	end
end

--- External script registration. Script will pass data by calling external_w through dbus
function bashets.schedule_e(script, widget, callback, format, updtime, sep)
	local ascript = util.fullpath(script)
	local key = util.tmpkey(ascript)

	ewidgets[key] = {}
	ewidgets[key].widget = widget
	ewidgets[key].callback = callback
	ewidgets[key].format = format
	ewidgets[key].separator = sep
	ewidgets[key].cmd = util.fullpath(defaults.updater) .. " \"" .. ascript .. "\" " .. key .. " " ..updtime
	--print(ewidgets[key].cmd)
	
--	awful.util.spawn_with_shell()
end

function bashets.external_w(raw_data, key)

	local callback = ewidgets[key].callback or nil
	local widget = ewidgets[key].widget or nil
	local format = ewidgets[key].format or defaults.format_string
	local data = util.readstring(raw_data, ewidgets[key].separator)

	if callback ~= nil and type(callback) == "function" then
		if widget ~= nil then
			util.update_widget(widget, data, format)
			callback(data)
		else
			callback(data)
		end
	elseif widget ~= nil then
		util.update_widget(widget, data, format)
	end
end

function bashets.register_d(bus, iface, widget, callback, format)
	if capi.dbus then
		bus = bus or "session"
		capi.dbus.add_match(bus, "interface='" .. iface .. "'")
		
		capi.dbus.connect_signal(iface, function (...) 
			local argums = {...}
			local data = {}
			for _,v in pairs(argums) do
				if type(v) == "table" then
					for _,iv in pairs(v) do
						table.insert(data, iv)
					end
				else
					table.insert(data, v)
				end
			end

			if callback ~= nil and type(callback) == "function" then
				if widget ~= nil then
					util.update_widget(widget, data, format)
					callback(data)
				else
					callback(data)
				end
			elseif widget ~= nil then
				util.update_widget(widget, data, format)
			end
		end)
	else
		error("bashets: You are trying to employ dbus, but no dbus api detected in your build of awesome")
	end
end



--- Register script for text widget
-- @param object Object to be a data provider (function or string with a path to file/shellscript)
-- @param options Options table with following content (all fields are optional):
--
-- 	widget Widget to update
-- 	callback Function to execute after the update (should have a single parameter which represents table with data)
--  NOTE: you can use the widget without a callback, the callback without a widget, or both
--
-- 	update_time Widget update time (in seconds)
-- 	separator Output separator (string, could be null)
-- 	format User-defined format string (any valid Pango markup with variables)
--
-- 	async Perform script execution through a temporary file (true/false)
-- 	file_update_time Temporary file content update time (in seconds)
--
-- 	read_file Read file instead of executing it
function bashets.register(object, options)
	-- Set optional variables
	options = options or {}
	local updtime = options.update_time or defaults.update_time
	local fltime = options.file_update_time or defaults.file_update_time
	local format = options.format or defaults.format_string
	local sep = options.separator or defaults.separator
	local callback = options.callback
	local async = options.async or false
	local isdbus = options.dbus or false
	local busname = options.busname or "session"
	local readfile = options.read_file or false
	local widget = options.widget
	local external = options.external or false

	if type(object) == "function" then		--We have a function as a data provider
		-- Do it first time
		local data = func()
		util.update_widget(widget, data, format)
		
		-- Schedule it for timed execution
		bashets.schedule_w(func, widget, callback, format, updtime)

	elseif readfile	then				--We have a text file as a data provider
		-- Do it first time
		local data = util.readfile(object, sep)
		util.update_widget(widget, data, format)

		-- Schedule it for timed execution
		bashets.schedule_w(function() return util.readfile(object, sep) end, widget, callback, format, updtime)

	elseif async then				--Script could hang Awesome, we need to run it
		local script = util.fullpath(object)		--through a temporary file
		local tmpfile = util.tmpname(script)

		-- Create temporary file if not exists
		fl = io.open(tmpfile, "w")
		io.close(fl)

		-- Do it first time
		util.execfile(script, tmpfile)
		local data = util.readfile(tmpfile, sep)
		util.update_widget(widget, data, format)

		-- Schedule it for timed execution
		bashets.schedule(function() util.execfile(script, tmpfile) end, fltime)
		bashets.schedule_w(function() return util.readfile(tmpfile, sep) end, widget, callback, format, updtime)

	elseif external then		-- Script provides external data through dbus
		local script = util.fullpath(object)
		bashets.schedule_e(script, widget, callback, format, updtime, sep)
	elseif isdbus then			-- Data is fetched through a message bus
		bashets.register_d(busname, object, widget, callback, format)
		--print("registered with bus name \"" .. busname .. "\" and object \"" .. object .. "\"")
	else						-- Fast script that can be read through pread
		local script = util.fullpath(object)

		-- Do it first time
		local data = util.readshell(script, sep)
		util.update_widget(widget, data, format)

		-- Schedule it for timed execution
		bashets.schedule_w(function() return util.readshell(script, sep) end, widget, callback, format, updtime)
	end

end

return bashets