qasim 0.1.11.dev.2014102811

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +31 -0
  3. data/Gemfile +7 -0
  4. data/LICENSE-GPL-3 +674 -0
  5. data/Makefile +180 -0
  6. data/README.md +81 -0
  7. data/Rakefile +1 -0
  8. data/TODO.md +28 -0
  9. data/bin/qasim-cli +89 -0
  10. data/bin/qasim-gui +300 -0
  11. data/conf/config +2 -0
  12. data/conf/default.map +32 -0
  13. data/conf/qasim.desktop +13 -0
  14. data/data/icons/qasim.128.png +0 -0
  15. data/data/icons/qasim.16.png +0 -0
  16. data/data/icons/qasim.256.png +0 -0
  17. data/data/icons/qasim.32.png +0 -0
  18. data/data/icons/qasim.64.png +0 -0
  19. data/data/icons/qasim.png +0 -0
  20. data/data/icons/qasim.svg +192 -0
  21. data/data/text/authors.html +7 -0
  22. data/data/text/gpl-3.0-standalone.html +694 -0
  23. data/data/text/thanks.html +0 -0
  24. data/debian/changelog +73 -0
  25. data/debian/compat +1 -0
  26. data/debian/control +13 -0
  27. data/debian/copyright +38 -0
  28. data/debian/dirs +3 -0
  29. data/debian/docs +0 -0
  30. data/debian/rules +80 -0
  31. data/debian/source/format +1 -0
  32. data/demo.map +29 -0
  33. data/examples/config +2 -0
  34. data/examples/default.map +32 -0
  35. data/lib/qasim.rb +11 -0
  36. data/lib/qasim/config.rb +56 -0
  37. data/lib/qasim/configold.rb +123 -0
  38. data/lib/qasim/constants.rb +11 -0
  39. data/lib/qasim/map.rb +225 -0
  40. data/lib/qasim/qasim.qrc +8 -0
  41. data/lib/qasim/ui.rb +7 -0
  42. data/lib/qasim/ui/about.rb +58 -0
  43. data/lib/qasim/ui/about.ui +192 -0
  44. data/lib/qasim/ui/listmaps.ui +59 -0
  45. data/lib/qasim/ui/preferences.rb +12 -0
  46. data/lib/qasim/ui/preferences.ui +90 -0
  47. data/lib/qasim/version.rb +5 -0
  48. data/man/qasim-cli.1 +98 -0
  49. data/man/qasim-gui.1 +98 -0
  50. data/man/sshfs-mapper.1 +98 -0
  51. data/mapparser.y +155 -0
  52. data/qasim.gemspec +34 -0
  53. data/sshfs-mapper.completion +24 -0
  54. data/sshfs-mapper.sh +253 -0
  55. metadata +147 -0
data/Makefile ADDED
@@ -0,0 +1,180 @@
1
+
2
+ NAME=qasim
3
+ DESTDIR=
4
+ DEV_DESTDIR=tmp
5
+ CONFDIR=$(DESTDIR)/etc
6
+ BINDIR=$(DESTDIR)/usr/bin
7
+ MANDIR=$(DESTDIR)/usr/share/man
8
+ DOCDIR=$(DESTDIR)/usr/share/doc
9
+ SHAREDIR=$(DESTDIR)/usr/share
10
+
11
+ RUBYVERSION=2.0
12
+ RDOC=rdoc$(RUBYVERSION)
13
+
14
+ all: \
15
+ build \
16
+ install
17
+
18
+ clean: \
19
+ clean-ui \
20
+ clean-qrc \
21
+ clean-bin \
22
+ clean-lib \
23
+ clean-data \
24
+ clean-doc
25
+
26
+ build: \
27
+ build-ui \
28
+ build-qrc \
29
+ build-bin \
30
+ build-lib \
31
+ build-data
32
+
33
+ doc: build-doc
34
+
35
+ install: \
36
+ install-ui \
37
+ install-qrc \
38
+ install-bin \
39
+ install-lib \
40
+ install-data
41
+
42
+ ## DOC SECTION
43
+
44
+ .PHONY: build-doc
45
+
46
+ clean-doc:
47
+ rm -fr doc
48
+
49
+ build-doc: clean-doc
50
+ $(RDOC) \
51
+ --promiscuous \
52
+ --inline-source \
53
+ --line-numbers \
54
+ -o doc lib/$(NAME)/ \
55
+ bin/
56
+ # --diagram
57
+
58
+ install-doc:
59
+ # # install documentation
60
+ rm -fr $(DOCDIR)/$(NAME)
61
+ mkdir -p $(DOCDIR)/$(NAME)
62
+ cp -a doc $(DOCDIR)/$(NAME)
63
+
64
+
65
+ ## QRC -> QRC_RB SECTION
66
+
67
+ QRC_FILES=$(wildcard lib/$(NAME)/*.qrc)
68
+ RBQRC_FILES=$(patsubst %.qrc,%_qrc.rb,$(QRC_FILES))
69
+
70
+ clean-qrc:
71
+ rm -f $(RBQRC_FILES)
72
+
73
+ build-qrc: $(RBQRC_FILES)
74
+ echo $(RBQRC_FILES)
75
+
76
+ install-qrc: $(RBQRC_FILES)
77
+ # FIXME install qrc
78
+
79
+ %_qrc.rb: %.qrc
80
+ rbrcc $< -o $@
81
+
82
+ ## UI -> UI_RB SECTION
83
+
84
+ UI_FILES=$(wildcard lib/$(NAME)/ui/*.ui)
85
+ RBUI_FILES=$(patsubst %.ui,%_ui.rb,$(UI_FILES))
86
+
87
+ clean-ui:
88
+ rm -f $(RBUI_FILES)
89
+
90
+ build-ui: $(RBUI_FILES)
91
+ echo $(RBUI_FILES)
92
+
93
+ install-ui: $(RBUI_FILES)
94
+ # FIXME install
95
+
96
+ %_ui.rb: %.ui
97
+ rbuic4 $< -o $@
98
+ sed -e '/^module Ui/,/^end # module Ui/d' \
99
+ -i $@
100
+
101
+
102
+ ## BINARY SECTION
103
+
104
+ clean-bin:
105
+ # remove external packages
106
+ rm -fr vendor/bundle
107
+
108
+ build-bin:
109
+
110
+ install-bin:
111
+ env |sort
112
+ mkdir -p $(BINDIR)
113
+ for binfile in bin/*.rb ; do \
114
+ BINFILE=`basename $$binfile |sed -e 's/.rb$$//'`; \
115
+ install -D -o root -g root -m 755 $$binfile $(BINDIR)/$$BINFILE; \
116
+ sed -i -e 's|^QASIM_INCLUDE_DIR.*|QASIM_INCLUDE_DIR = "$(SHAREDIR)/$(NAME)/lib"|' $(BINDIR)/$$BINFILE; \
117
+ sed -i -e 's|^QASIM_DATA_DIR.*|QASIM_DATA_DIR = "$(SHAREDIR)/$(NAME)"|' $(BINDIR)/$$BINFILE; \
118
+ done
119
+ #install -D -o root -g root -m 755 $(CURDIR)/bin/$(NAME)-gui.rb $(BINDIR)/$(NAME)-gui
120
+
121
+ ## LIB SECTION
122
+
123
+ clean-lib:
124
+
125
+ build-lib:
126
+
127
+ install-lib:
128
+ IFS="" find lib -name '*.rb' | while read libfile ; do \
129
+ install -D -o root -g root -m 644 $$libfile $(SHAREDIR)/$(NAME)/$$libfile; \
130
+ done
131
+
132
+
133
+ ## DATA SECTION
134
+
135
+ clean-data:
136
+
137
+ build-data:
138
+
139
+ install-data:
140
+ ## Install man pages
141
+ mkdir -p $(MANDIR)/man1
142
+ for binfile in bin/*.rb ; do \
143
+ BINFILE=`basename $$binfile |sed -e 's/.rb$$//'`; \
144
+ cat man/$${BINFILE}.1 | gzip > $(MANDIR)/man1/$${BINFILE}.1.gz ; \
145
+ done
146
+ #
147
+ ## Install icons
148
+ mkdir -p $(SHAREDIR)/$(NAME)/icons
149
+ install -D -o root -g root -m 644 $(CURDIR)/data/icons/$(NAME).svg \
150
+ $(SHAREDIR)/$(NAME)/icons/$(NAME).svg
151
+ #
152
+ ## Install completion file
153
+ # install -D -o root -g root -m 644 $(CURDIR)/$(NAME).completion $(DESTDIR)/etc/bash_completion.d/$(NAME)
154
+ #
155
+ ## Install configuration files
156
+ mkdir -p $(CONFDIR)/xdg/autostart
157
+ install -D -o root -g root -m 644 $(CURDIR)/conf/$(NAME).desktop \
158
+ $(CONFDIR)/xdg/autostart/$(NAME).desktop
159
+ install -D -o root -g root -m 644 $(CURDIR)/conf/$(NAME).desktop \
160
+ $(SHAREDIR)/applications/$(NAME).desktop
161
+ mkdir -p $(CONFDIR)/$(NAME)
162
+ install -D -o root -g root -m 644 $(CURDIR)/conf/config \
163
+ $(CONFDIR)/$(NAME)/config
164
+ install -D -o root -g root -m 644 $(CURDIR)/conf/default.map \
165
+ $(CONFDIR)/$(NAME)/default.map
166
+ #
167
+ # Install examples
168
+ mkdir -p $(DOCDIR)/$(NAME)/examples
169
+ for f in `ls examples`; do \
170
+ cat examples/$$f | gzip -f9 > $(DOCDIR)/$(NAME)/examples/$$f.gz ; \
171
+ done
172
+
173
+
174
+ ## OTHER
175
+
176
+ .PHONY: destdir
177
+ dev-install:
178
+ rm -fr $(DEV_DESTDIR)
179
+ fakeroot $(MAKE) install DESTDIR=$(DEV_DESTDIR)
180
+
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ README
2
+ ======
3
+
4
+ Requirements
5
+ ------------
6
+
7
+ First, make sure your ruby was compiled with the --enable-shared options.
8
+ If not, reinstall it (let's say version 1.9.3-p392) with with :
9
+
10
+ CONFIGURE_OPTS="--enable-shared" rbenv install 1.9.3-p392
11
+
12
+ Install the following gems
13
+
14
+ qtbindings
15
+
16
+ Those could also be provided by your linux distribution and installable
17
+ with
18
+
19
+ apt-get install libqt4-ruby
20
+
21
+ or
22
+
23
+ apt-get install ruby-qt4
24
+
25
+
26
+ Installation
27
+ ------------
28
+
29
+ Add this line to your application's Gemfile:
30
+
31
+ gem 'qasim'
32
+
33
+ And then execute:
34
+
35
+ $ bundle
36
+
37
+ Or install it yourself as:
38
+
39
+ $ gem install qasim
40
+
41
+
42
+ Usage
43
+ -----
44
+
45
+ TODO: Write usage instructions here
46
+
47
+
48
+ Contributing
49
+ ------------
50
+
51
+ 1. Fork it ( http://github.com/glenux/qasim/fork )
52
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
53
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
54
+ 4. Push to the branch (`git push origin my-new-feature`)
55
+ 5. Create new Pull Request
56
+
57
+
58
+ Copyright & License
59
+ -------------------
60
+
61
+ Copyright (C) 2010-2012 Glenn Y. Rolland
62
+
63
+ This program is free software: you can redistribute it and/or modify
64
+ it under the terms of the GNU General Public License as published by
65
+ the Free Software Foundation, either version 3 of the License, or
66
+ (at your option) any later version.
67
+
68
+ This program is distributed in the hope that it will be useful,
69
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
70
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71
+ GNU General Public License for more details.
72
+
73
+ You should have received a copy of the GNU General Public License
74
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
75
+
76
+
77
+ Alternatives
78
+ ------------
79
+
80
+ * [Mountoid](http://kde-apps.org/content/show.php/Mountoid?content=115943)
81
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/TODO.md ADDED
@@ -0,0 +1,28 @@
1
+ Global Qasim parameters
2
+
3
+ * Default local cache directory
4
+ * Default mount point directory
5
+
6
+ * AutoSSH (disable if not installed)
7
+ * autossh executable path
8
+ * use autossh (default: yes)
9
+ * Unison (disable if not installed)
10
+ * unison executable path
11
+ * use unison (default: yes)
12
+ * sync interval (0=none, ...) in hours
13
+
14
+ Global SSHFS Options
15
+
16
+ * reconnect (default: yes)
17
+ * compress (default: yes)
18
+ * transform_symlinks (default: yes)
19
+ * ServerAliveInterval (default: 30)
20
+ * ServerAliveCountMax (default: 30)
21
+
22
+ ssh_command='autossh -M 0'
23
+
24
+
25
+ Fixes
26
+
27
+ Use Rakefile
28
+ ex: https://github.com/ryanmelt/qtbindings/blob/master/Rakefile
data/bin/qasim-cli ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $DEBUG = true
4
+ $VERBOSE = true
5
+
6
+ QASIM_INCLUDE_DIR = "lib"
7
+ QASIM_DATA_DIR = "."
8
+
9
+ $:.push QASIM_INCLUDE_DIR
10
+ p $:.inspect
11
+
12
+ #
13
+ # external libraries
14
+ #
15
+ require 'bundler/setup'
16
+ require 'pp'
17
+ #require 'thor'
18
+
19
+ #
20
+ # project libraries
21
+ #
22
+ require 'qasim'
23
+
24
+ module Qasim
25
+
26
+ class QasimCli
27
+ #
28
+ #
29
+ #
30
+ def initialize
31
+ @all_maps = nil
32
+ @active_maps = nil
33
+
34
+ puts "-- sshfs-mapper --"
35
+ @config = Config.new
36
+ @config.parse_cmd_line ARGV
37
+ @config.parse_file
38
+
39
+ @all_maps = {}
40
+ pp @config
41
+ end
42
+
43
+
44
+ # create default map for each selected map
45
+ # or default.map if none selected
46
+ def run_init
47
+ end
48
+
49
+ def run_mount
50
+
51
+ # asynchronous mount
52
+ selected_maps = @config.maps.select do |map|
53
+ pp map
54
+ map.online?
55
+ # if map.available? then
56
+ # map.connect!
57
+ # end
58
+ end
59
+
60
+ end
61
+
62
+ def run_umount
63
+ end
64
+
65
+ #
66
+ #
67
+ #
68
+ def run
69
+ case @config.action
70
+ when Config::ACTION_INIT
71
+ run_init
72
+ when Config::ACTION_MOUNT
73
+ run_mount
74
+ when Config::ACTION_UMOUNT
75
+ run_umount
76
+ else
77
+ raise RuntimeError, "Unknown action"
78
+ end
79
+
80
+ puts "--run"
81
+ end
82
+
83
+ end
84
+ end
85
+
86
+ app = Qasim::Qasim.new
87
+ app.run
88
+
89
+
data/bin/qasim-gui ADDED
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'Qt4'
4
+
5
+ $DEBUG = true
6
+ $VERBOSE = true
7
+
8
+ require 'pp'
9
+ require 'set'
10
+ require 'fcntl'
11
+ require 'pathname'
12
+
13
+ QASIM_INCLUDE_DIR = Pathname.new(File.dirname(__FILE__)).parent + "lib"
14
+ QASIM_DATA_DIR = Pathname.new(File.dirname(__FILE__)).parent + "data"
15
+
16
+ $:.push QASIM_INCLUDE_DIR
17
+
18
+ require 'qasim'
19
+ require 'qasim/qasim_qrc'
20
+
21
+ # QaSiM // Qt Sshfs Mapper
22
+
23
+ def _ str
24
+ Qt::Object.tr(str)
25
+ end
26
+
27
+
28
+ module Qasim
29
+ class QasimApp
30
+ def initialize
31
+ end
32
+ end
33
+
34
+ class QasimGui < QasimApp
35
+
36
+ class LockError < RuntimeError ; end
37
+
38
+ def initialize
39
+ @config = Config.new
40
+ #@config.parse_cmd_line ARGV
41
+
42
+ @map_menu = nil
43
+ @context_menu = nil
44
+ @connect_error = {}
45
+ @connect_running = {}
46
+ end
47
+
48
+ def dbus_notify title, body, icon
49
+ bus = Qt::DBusConnection.sessionBus
50
+ if !bus.connected?
51
+ $stderr.puts("Cannot connect to the D-BUS session bus.\n" \
52
+ "To start it, run:\n" \
53
+ "\teval `dbus-launch --auto-syntax`\n")
54
+ exit 1
55
+ end
56
+ msg = Qt::DBusMessage.create_method_call( 'org.freedesktop.Notifications',
57
+ '/org/freedesktop/Notifications',
58
+ 'org.freedesktop.Notifications',
59
+ 'Notify' )
60
+ msg.arguments = [ APP_NAME, Qt::Variant.from_value( 0, "unsigned int" ),
61
+ icon, title, body, [], {}, -1 ]
62
+ rep = bus.call( msg )
63
+ # if rep.type == Qt::DBusMessage
64
+
65
+ # si.showMessage("Qasim",
66
+ # "Sorry dude", 2, 5000 )
67
+ end
68
+
69
+
70
+ #
71
+ # Rebuild map menu
72
+ #
73
+ def build_map_menu
74
+ # reload maps dynamically
75
+ @config.parse_maps
76
+ if @map_menu.nil? then
77
+ @map_menu = Qt::Menu.new
78
+ else
79
+ @map_menu.clear
80
+ end
81
+
82
+ previous_host = nil
83
+ @config.maps.sort do |mx,my|
84
+ mx.host <=> my.host
85
+ end.each do |map|
86
+ if map.host != previous_host and not previous_host.nil? then
87
+ @map_menu.addSeparator
88
+ end
89
+ itemx = Qt::Action.new(map.name, @map_menu)
90
+ itemx.setCheckable true;
91
+ if map.connected? then
92
+ itemx.setChecked true
93
+ end
94
+ itemx.connect(SIGNAL(:triggered)) do
95
+ action_trigger_map_item map, itemx
96
+ end
97
+ @map_menu.addAction itemx;
98
+ previous_host = map.host
99
+ end
100
+ end
101
+
102
+ #
103
+ # Action when map item triggered
104
+ #
105
+ def action_trigger_map_item map, item
106
+ @connect_error[map.path] = Set.new
107
+ @connect_running[map.path] = 0
108
+ method = if map.connected? then :disconnect
109
+ else :connect
110
+ end
111
+
112
+ begin
113
+ map.send(method) do |linkname,cmd,cmd_args|
114
+ process = Qt::Process.new
115
+ process.connect(SIGNAL('finished(int, QProcess::ExitStatus)')) do |exitcode,exitstatus|
116
+ #puts "exitcode = %s, exitstatus = %s" % [exitcode, exitstatus]
117
+ @connect_running[map.path] -= 1
118
+ if exitcode != 0 then
119
+ @connect_error[map.path].add linkname
120
+ else
121
+ end
122
+ if @connect_running[map.path] == 0 then
123
+ # display someting
124
+ if @connect_error[map.path].empty? then
125
+
126
+ dbus_notify "%s (%s)" % [APP_NAME, map.name],
127
+ ("<b>Map %sed successfully<b>" % method.to_s),
128
+ 'dialog-information'
129
+ else
130
+ erroneous = @connect_error[map.path].to_a.join(', ')
131
+ dbus_notify "%s (%s)" % [APP_NAME, map.name],
132
+ ("<b>Unable to %s map</b><br>" % method.to_s) +
133
+ ("Broken link(s): %s" % erroneous),
134
+ 'dialog-error'
135
+ end
136
+ end
137
+ end
138
+ @connect_running[map.path] += 1
139
+ process.start cmd, cmd_args
140
+ end
141
+
142
+ rescue Map::ConnectError => e
143
+ puts e.inspect
144
+ end
145
+ end
146
+
147
+ #
148
+ #
149
+ #
150
+ def build_context_menu
151
+ @context_menu = Qt::Menu.new
152
+
153
+ act_pref = Qt::Action.new _('&Preferences'), @context_menu
154
+ act_pref.setIcon( Qt::Icon::fromTheme("configure") ) rescue nil
155
+ act_pref.setIconVisibleInMenu true
156
+ act_pref.setEnabled false
157
+ act_pref.connect(SIGNAL(:triggered)) do
158
+ res = @pref_dialog.show
159
+ end
160
+ @context_menu.addAction act_pref;
161
+
162
+ act_about = Qt::Action.new '&About', @context_menu
163
+ act_about.setIcon( Qt::Icon::fromTheme("help-about") ) rescue nil
164
+ act_about.setIconVisibleInMenu true
165
+ #act_about.setEnabled true
166
+ act_about.connect(SIGNAL(:triggered)) do
167
+ res = @about_dialog.show
168
+ end
169
+ @context_menu.addAction act_about;
170
+
171
+ @context_menu.addSeparator
172
+
173
+ act_quit = Qt::Action.new _('Quit'), @context_menu
174
+ act_quit.setIcon( Qt::Icon::fromTheme("application-exit") ) rescue nil
175
+ act_quit.setIconVisibleInMenu true
176
+ act_quit.connect(SIGNAL(:triggered)) { @app.quit }
177
+ @context_menu.addAction act_quit
178
+ end
179
+
180
+
181
+ #
182
+ #
183
+ #
184
+ def build_interface
185
+
186
+ @app = Qt::Application.new(ARGV)
187
+ #Qt.debug_level = Qt::DebugLevel::High
188
+ #Qt.debug_level = Qt::DebugLevel::Extensive
189
+ @app.setQuitOnLastWindowClosed false
190
+
191
+ @main_win = Qt::MainWindow.new
192
+ @systray = Qt::SystemTrayIcon.new @main_win
193
+ @about_dialog = Qasim::Ui::About.new @main_win
194
+ @pref_dialog = Qasim::Ui::Preferences.new @main_win
195
+
196
+ std_icon = Qt::Icon.new( ":/qasim/qasim-icon" )
197
+ alt_icon = Qt::Icon.new
198
+ blinking = false
199
+
200
+ @systray.icon = std_icon
201
+ @systray.show
202
+
203
+
204
+ @systray.setToolTip("Qasim %s" % APP_VERSION);
205
+
206
+ build_map_menu
207
+ build_context_menu
208
+
209
+ @systray.contextMenu = @context_menu
210
+
211
+ @systray.connect(SIGNAL('activated(QSystemTrayIcon::ActivationReason)')) do |reason|
212
+ case reason
213
+ when Qt::SystemTrayIcon::Trigger then
214
+ build_map_menu
215
+ @map_menu.popup(Qt::Cursor::pos())
216
+ #blinking = !blinking
217
+ #si.icon = blinking ? alt_icon : std_icon
218
+ when Qt::SystemTrayIcon::MiddleClick then
219
+ #
220
+ when Qt::SystemTrayIcon::Context then
221
+ #
222
+ when Qt::SystemTrayIcon::DoubleClick then
223
+ #
224
+ end
225
+ end
226
+ end
227
+
228
+
229
+ def lock_set
230
+ begin
231
+ # create an exclusive lock file
232
+ have_lock = true
233
+
234
+ FileUtils.mkdir_p APP_CONFIG_DIR unless File.exist? APP_CONFIG_DIR
235
+ lockfname = File.join APP_CONFIG_DIR, "lock"
236
+ fd = IO::sysopen( lockfname,
237
+ Fcntl::O_WRONLY | Fcntl::O_EXCL | Fcntl::O_CREAT)
238
+ f = IO.open(fd)
239
+ f.syswrite( "#{Process.pid}\n" )
240
+ f.close
241
+ rescue Errno::EEXIST => e
242
+ # test if the other process still exist
243
+ masterpid = File.read(lockfname).strip
244
+ other_path = "/proc/#{masterpid.to_i}"
245
+ STDERR.puts "testing %s" % other_path
246
+ if File.exist? other_path then
247
+ cmdline = File.read( File.join( other_path, 'cmdline' ) )
248
+ if cmdline =~ /qasim/ then
249
+ raise LockError, "Another instance of %s is already running." % APP_NAME
250
+ end
251
+ end
252
+ fd = IO::sysopen( lockfname,
253
+ Fcntl::O_WRONLY | Fcntl::O_EXCL )
254
+ f = IO.open(fd)
255
+ f.syswrite( "#{Process.pid}\n" )
256
+ f.close
257
+ end
258
+ end
259
+
260
+ def lock_unset
261
+ # remove lock if it exists
262
+ lockfname = File.join APP_CONFIG_DIR, "lock"
263
+ return unless File.exist? lockfname
264
+ masterpid = File.read(lockfname).strip
265
+ if masterpid.to_i == Process.pid then
266
+ FileUtils.rm lockfname
267
+ end
268
+ end
269
+
270
+ #
271
+ #
272
+ #
273
+ def run
274
+ Process.daemon(true) #FIXME: add foreground mode too
275
+ lock_set
276
+ @app.exec
277
+ exit 0
278
+ rescue LockError
279
+ STDERR.puts "Error: %s is already running" % APP_NAME
280
+ exit 1
281
+ ensure
282
+ lock_unset
283
+ end
284
+
285
+
286
+ #
287
+ #
288
+ #
289
+ def self.main
290
+ qasim = QasimGui.new
291
+ qasim.build_interface
292
+ qasim.run
293
+ end
294
+
295
+ end
296
+
297
+ end
298
+
299
+ Qasim::QasimGui::main
300
+