Implement ulock
This commit is contained in:
parent
8fac573efc
commit
aff9ec19a2
11 changed files with 851 additions and 4 deletions
|
@ -1,12 +1,41 @@
|
||||||
project(ULOCK C)
|
project(ULOCK C)
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH ${ULOCK_SOURCE_DIR})
|
||||||
|
|
||||||
|
find_package(Gettext REQUIRED)
|
||||||
|
|
||||||
|
find_package(PAM REQUIRED)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(GTK3 REQUIRED gtk+-x11-3.0)
|
pkg_check_modules(GTK3 REQUIRED gtk+-x11-3.0)
|
||||||
|
pkg_check_modules(GDK3 REQUIRED gdk-x11-3.0)
|
||||||
|
pkg_check_modules(X11 REQUIRED x11)
|
||||||
|
|
||||||
include_directories(${GTK3_INCLUDE_DIRS})
|
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||||
|
find_package(Threads)
|
||||||
|
if(NOT CMAKE_USE_PTHREADS_INIT)
|
||||||
|
MESSAGE(FATAL_ERROR "No pthread support found.")
|
||||||
|
endif(NOT CMAKE_USE_PTHREADS_INIT)
|
||||||
|
|
||||||
|
|
||||||
|
set(CONFIG_DIR "/etc" CACHE STRING "Path to install ulock's configuration file to")
|
||||||
|
set(DATA_DIR "share/ulock" CACHE STRING "Path to install ulock's data files to")
|
||||||
|
|
||||||
|
|
||||||
|
include_directories(${ULOCK_BINARY_DIR} ${GTK3_INCLUDE_DIRS} ${GDK3_INCLUDE_DIRS} ${X11_INCLUDE_DIRS} ${PAM_INCLUDE_DIR})
|
||||||
|
|
||||||
|
configure_file(${ULOCK_SOURCE_DIR}/config.h.in ${ULOCK_BINARY_DIR}/config.h)
|
||||||
|
|
||||||
add_executable(ulock ulock.c)
|
add_executable(ulock ulock.c)
|
||||||
set_property(TARGET ulock PROPERTY COMPILE_FLAGS "-Wall ${GTK3_CFLAGS_OTHER}")
|
set_property(TARGET ulock PROPERTY COMPILE_FLAGS "-Wall -pthread ${GTK3_CFLAGS_OTHER} ${GDK3_CFLAGS_OTHER} ${X11_CFLAGS_OTHER}")
|
||||||
set_property(TARGET ulock PROPERTY LINK_FLAGS "${GTK3_LDFLAGS_OTHER}")
|
set_property(TARGET ulock PROPERTY LINK_FLAGS "-pthread ${GTK3_LDFLAGS_OTHER} ${GDK3_LDFLAGS_OTHER} ${X11_LDFLAGS_OTHER}")
|
||||||
target_link_libraries(ulock ${GTK3_LIBRARIES})
|
target_link_libraries(ulock ${GTK3_LIBRARIES} ${GDK3_LIBRARIES} ${X11_LIBRARIES} ${PAM_LIBRARY})
|
||||||
|
|
||||||
|
GETTEXT_PROCESS_PO_FILES(de ALL PO_FILES po/de.po)
|
||||||
|
|
||||||
|
install(TARGETS ulock RUNTIME DESTINATION bin)
|
||||||
|
install(DIRECTORY data/ DESTINATION ${DATA_DIR})
|
||||||
|
install(FILES etc/ulock.conf DESTINATION ${CONFIG_DIR})
|
||||||
|
|
||||||
|
install(FILES ${ULOCK_BINARY_DIR}/de.gmo DESTINATION share/locale/de/LC_MESSAGES RENAME ulock.mo)
|
||||||
|
|
16
FindPAM.cmake
Normal file
16
FindPAM.cmake
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
FIND_PATH(PAM_INCLUDE_DIR security/pam_appl.h)
|
||||||
|
FIND_LIBRARY(PAM_LIBRARY NAMES pam)
|
||||||
|
|
||||||
|
IF (PAM_INCLUDE_DIR AND PAM_LIBRARY)
|
||||||
|
SET(PAM_FOUND TRUE)
|
||||||
|
ENDIF (PAM_INCLUDE_DIR AND PAM_LIBRARY)
|
||||||
|
|
||||||
|
IF (PAM_FOUND)
|
||||||
|
IF (NOT PAM_FIND_QUIETLY)
|
||||||
|
MESSAGE(STATUS "Found PAM: ${PAM_LIBRARY}; include path: ${PAM_INCLUDE_DIR}")
|
||||||
|
ENDIF (NOT PAM_FIND_QUIETLY)
|
||||||
|
ELSE (PAM_FOUND)
|
||||||
|
IF (PAM_FIND_REQUIRED)
|
||||||
|
MESSAGE(FATAL_ERROR "Could not find PAM")
|
||||||
|
ENDIF (PAM_FIND_REQUIRED)
|
||||||
|
ENDIF (PAM_FOUND)
|
8
config.h.in
Normal file
8
config.h.in
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef _ULOCK_CONFIG_H_
|
||||||
|
#define _ULOCK_CONFIG_H_
|
||||||
|
|
||||||
|
#define CONFIG_FILE "@CONFIG_DIR@/ulock.conf"
|
||||||
|
#define PREFIX "@CMAKE_INSTALL_PREFIX@"
|
||||||
|
#define DATA_DIR "@CMAKE_INSTALL_PREFIX@/@DATA_DIR@"
|
||||||
|
|
||||||
|
#endif /* _ULOCK_CONFIG_H_ */
|
208
data/bg.svg
Normal file
208
data/bg.svg
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
width="1680"
|
||||||
|
height="1050"
|
||||||
|
viewBox="0 0 1680 1050"
|
||||||
|
id="svg2"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="0.48.2 r9819"
|
||||||
|
sodipodi:docname="bg.svg"><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1280"
|
||||||
|
inkscape:window-height="776"
|
||||||
|
id="namedview3016"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.23166667"
|
||||||
|
inkscape:cx="349.5177"
|
||||||
|
inkscape:cy="787.53453"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="24"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="layer1" /><metadata
|
||||||
|
id="metadata129"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs127">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
x1="960.00049"
|
||||||
|
y1="878.5"
|
||||||
|
x2="960.00049"
|
||||||
|
y2="291.50049"
|
||||||
|
id="linearGradient3223"
|
||||||
|
xlink:href="#SVGID_1_"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#SVGID_1_"
|
||||||
|
id="linearGradient3811"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="960.00049"
|
||||||
|
y1="878.5"
|
||||||
|
x2="960.00049"
|
||||||
|
y2="291.50049" />
|
||||||
|
<linearGradient
|
||||||
|
x1="960.00049"
|
||||||
|
y1="878.5"
|
||||||
|
x2="960.00049"
|
||||||
|
y2="291.50049"
|
||||||
|
id="SVGID_1_"
|
||||||
|
gradientUnits="userSpaceOnUse">
|
||||||
|
<stop
|
||||||
|
id="stop20"
|
||||||
|
style="stop-color:#50acc5;stop-opacity:0.80000001"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop22"
|
||||||
|
style="stop-color:#388da2;stop-opacity:0.81980002"
|
||||||
|
offset="0.0148" />
|
||||||
|
<stop
|
||||||
|
id="stop24"
|
||||||
|
style="stop-color:#247385;stop-opacity:0.84420002"
|
||||||
|
offset="0.0331" />
|
||||||
|
<stop
|
||||||
|
id="stop26"
|
||||||
|
style="stop-color:#166071;stop-opacity:0.87110001"
|
||||||
|
offset="0.0533" />
|
||||||
|
<stop
|
||||||
|
id="stop28"
|
||||||
|
style="stop-color:#0b5363;stop-opacity:0.9016"
|
||||||
|
offset="0.0762" />
|
||||||
|
<stop
|
||||||
|
id="stop30"
|
||||||
|
style="stop-color:#044d5c;stop-opacity:0.93849999"
|
||||||
|
offset="0.1039" />
|
||||||
|
<stop
|
||||||
|
id="stop32"
|
||||||
|
style="stop-color:#104b5a;stop-opacity:1;"
|
||||||
|
offset="0.15000001" />
|
||||||
|
<stop
|
||||||
|
id="stop34"
|
||||||
|
style="stop-color:#104b5a;stop-opacity:1;"
|
||||||
|
offset="0.85000002" />
|
||||||
|
<stop
|
||||||
|
id="stop36"
|
||||||
|
style="stop-color:#044d5c;stop-opacity:0.93529999"
|
||||||
|
offset="0.89859998" />
|
||||||
|
<stop
|
||||||
|
id="stop38"
|
||||||
|
style="stop-color:#0b5363;stop-opacity:0.8987"
|
||||||
|
offset="0.926" />
|
||||||
|
<stop
|
||||||
|
id="stop40"
|
||||||
|
style="stop-color:#165f70;stop-opacity:0.86919999"
|
||||||
|
offset="0.94809997" />
|
||||||
|
<stop
|
||||||
|
id="stop42"
|
||||||
|
style="stop-color:#237184;stop-opacity:0.84350002"
|
||||||
|
offset="0.96740001" />
|
||||||
|
<stop
|
||||||
|
id="stop44"
|
||||||
|
style="stop-color:#368ba0;stop-opacity:0.8204"
|
||||||
|
offset="0.98470002" />
|
||||||
|
<stop
|
||||||
|
id="stop46"
|
||||||
|
style="stop-color:#50acc5;stop-opacity:0.80000001"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#SVGID_1_"
|
||||||
|
id="linearGradient3830"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="960.00049"
|
||||||
|
y1="878.5"
|
||||||
|
x2="960.00049"
|
||||||
|
y2="291.50049"
|
||||||
|
gradientTransform="matrix(1.1474185,0,0,0.85490494,-261.52174,174.07496)" /></defs>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<g
|
||||||
|
id="Hilfslinien_Center"
|
||||||
|
style="display:none"
|
||||||
|
transform="translate(0,-150)">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer"
|
||||||
|
transform="translate(0,-150)"><rect
|
||||||
|
style="fill:#104b5a;fill-opacity:1"
|
||||||
|
id="rect5"
|
||||||
|
y="150"
|
||||||
|
x="0"
|
||||||
|
height="1050"
|
||||||
|
width="1680" /><path
|
||||||
|
d="m 1326.2174,920.83442 c 0,2.35099 -2.5816,4.27453 -5.7371,4.27453 H 359.51967 c -3.1554,0 -5.73709,-1.92354 -5.73709,-4.27453 V 427.55427 c 0,-2.35098 2.58169,-4.27452 5.73709,-4.27452 h 960.96063 c 3.1555,0 5.7371,1.92354 5.7371,4.27452 v 493.28015 z"
|
||||||
|
id="path48"
|
||||||
|
style="opacity:0.5;fill:url(#linearGradient3830)"
|
||||||
|
inkscape:connector-curvature="0" /><path
|
||||||
|
d="m 1326.2174,920.83442 c 0,2.35099 -2.5816,4.27453 -5.7371,4.27453 H 359.51967 c -3.1554,0 -5.73709,-1.92354 -5.73709,-4.27453 V 427.55427 c 0,-2.35098 2.58169,-4.27452 5.73709,-4.27452 h 960.96063 c 3.1555,0 5.7371,1.92354 5.7371,4.27452 v 493.28015 z"
|
||||||
|
id="path50"
|
||||||
|
style="fill:none;stroke:#50acc5;stroke-width:0.4952105;stroke-linejoin:round;stroke-miterlimit:10"
|
||||||
|
inkscape:connector-curvature="0" /><g
|
||||||
|
id="Hilfslinien_Login"
|
||||||
|
transform="translate(-120,75)">
|
||||||
|
</g><text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:14px;font-style:normal;font-weight:normal;line-height:129.99999523%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
|
||||||
|
x="839.86035"
|
||||||
|
y="1006.295"
|
||||||
|
id="text3011"
|
||||||
|
sodipodi:linespacing="130%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3013"
|
||||||
|
x="839.86035"
|
||||||
|
y="1006.295"
|
||||||
|
style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:129.99999523%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold">Bei Problemen melden Sie sich bitte per E-Mail an</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="839.86035"
|
||||||
|
y="1034.895"
|
||||||
|
id="tspan3015"
|
||||||
|
style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:129.99999523%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="839.86035"
|
||||||
|
y="1063.495"
|
||||||
|
id="tspan3017"
|
||||||
|
style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:129.99999523%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold">pool-hotline@itsc.uni-luebeck.de</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="839.86035"
|
||||||
|
y="1092.095"
|
||||||
|
id="tspan3019"
|
||||||
|
style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:129.99999523%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="839.86035"
|
||||||
|
y="1120.6949"
|
||||||
|
id="tspan3021"
|
||||||
|
style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:129.99999523%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold">oder telefonisch unter der</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="839.86035"
|
||||||
|
y="1149.2949"
|
||||||
|
id="tspan3023"
|
||||||
|
style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:129.99999523%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold">internen Nummer 5004.</tspan></text>
|
||||||
|
|
||||||
|
</g></svg>
|
After Width: | Height: | Size: 7.2 KiB |
BIN
data/siegel.png
Normal file
BIN
data/siegel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
166
data/unlock.ui
Normal file
166
data/unlock.ui
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="2.24"/>
|
||||||
|
<object class="GtkNotebook" id="unlock_window">
|
||||||
|
<property name="width_request">700</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="show_tabs">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkHBox" id="box1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="spacing">40</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage" id="image1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="pixbuf">siegel.png</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkVBox" id="vbox2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="border_width">12</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="lock_label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" comments="This is a placeholder string and will be replaced with the hostname of the system">[lock]</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkVBox" id="login_box">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkHBox" id="prompt_box">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="prompt_label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Password:</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="prompt_entry">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="visibility">False</property>
|
||||||
|
<property name="invisible_char">•</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
<property name="primary_icon_activatable">False</property>
|
||||||
|
<property name="secondary_icon_activatable">False</property>
|
||||||
|
<signal name="activate" handler="login_cb" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="message_label">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="yalign">0</property>
|
||||||
|
<property name="label" comments="This is a placeholder string and will be replaced with a message from PAM">[message]</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkHBox" id="hbox2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="spacing">20</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="unlock_button">
|
||||||
|
<property name="label" translatable="yes">Unlock</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="logout_button">
|
||||||
|
<property name="label" translatable="yes">Logout</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">3</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child type="tab">
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
4
etc/ulock.conf
Normal file
4
etc/ulock.conf
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[ulock]
|
||||||
|
#theme=Adwaita
|
||||||
|
#logout_timeout=600
|
||||||
|
#logout_command=xfce4-session-logout -l
|
3
po/POTFILES.in
Normal file
3
po/POTFILES.in
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[encoding: UTF-8]
|
||||||
|
pylock.c
|
||||||
|
[type: gettext/glade]data/unlock.ui
|
49
po/de.po
Normal file
49
po/de.po
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
# ulock german translation
|
||||||
|
# Copyright (C) 2013 Matthias Schiffer
|
||||||
|
# This file is distributed under the same license as the ulock package.
|
||||||
|
# Matthias Schiffer <mschiffer@universe-factory.net>, 2013.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: pylock 0.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2013-09-19 18:53+0200\n"
|
||||||
|
"PO-Revision-Date: 2012-02-01 19:30+0100\n"
|
||||||
|
"Last-Translator: Matthias Schiffer <mschiffer@universe-factory.net>\n"
|
||||||
|
"Language-Team: German <de@li.org>\n"
|
||||||
|
"Language: de\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: data/unlock.ui:125
|
||||||
|
msgid "Logout"
|
||||||
|
msgstr "Ausloggen"
|
||||||
|
|
||||||
|
#: data/unlock.ui:58
|
||||||
|
msgid "Password:"
|
||||||
|
msgstr "Passwort:"
|
||||||
|
|
||||||
|
#: ulock.c:88
|
||||||
|
msgid "This computer is currently locked by the user <i>%s</i>."
|
||||||
|
msgstr "Dieser Computer ist zur Zeit vom Benutzer <i>%s</i> gesperrt."
|
||||||
|
|
||||||
|
#: ulock.c:92
|
||||||
|
msgid ""
|
||||||
|
"This computer is currently locked by the user <i>%s</i>.\n"
|
||||||
|
"The user can be logged out in %02u:%02u minutes."
|
||||||
|
msgstr ""
|
||||||
|
"Dieser Computer ist zur Zeit vom Benutzer <i>%s</i> gesperrt.\n"
|
||||||
|
"Der Benutzer kann in %02u:%02u Minuten ausgeloggt werden."
|
||||||
|
|
||||||
|
#: ulock.c:98
|
||||||
|
msgid ""
|
||||||
|
"This computer is currently locked by the user <i>%s</i>.\n"
|
||||||
|
"The user can be logged out now."
|
||||||
|
msgstr ""
|
||||||
|
"Dieser Computer ist zur Zeit vom Benutzer <i>%s</i> gesperrt.\n"
|
||||||
|
"Der Benutzer kann jetzt ausgeloggt werden."
|
||||||
|
|
||||||
|
#: data/unlock.ui:109
|
||||||
|
msgid "Unlock"
|
||||||
|
msgstr "Entsperren"
|
49
po/ulock.pot
Normal file
49
po/ulock.pot
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2013-09-19 18:53+0200\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: ulock.c:88
|
||||||
|
#, c-format
|
||||||
|
msgid "This computer is currently locked by the user <i>%s</i>."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ulock.c:92
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"This computer is currently locked by the user <i>%s</i>.\n"
|
||||||
|
"The user can be logged out in %02u:%02u minutes."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ulock.c:98
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"This computer is currently locked by the user <i>%s</i>.\n"
|
||||||
|
"The user can be logged out now."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: data/unlock.ui:58
|
||||||
|
msgid "Password:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: data/unlock.ui:109
|
||||||
|
msgid "Unlock"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: data/unlock.ui:125
|
||||||
|
msgid "Logout"
|
||||||
|
msgstr ""
|
315
ulock.c
315
ulock.c
|
@ -0,0 +1,315 @@
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <locale.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <security/pam_appl.h>
|
||||||
|
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define _(s) gettext(s)
|
||||||
|
#define DEBUG(args...) syslog(LOG_NOTICE, args)
|
||||||
|
|
||||||
|
|
||||||
|
enum lock_state {
|
||||||
|
LOCKED, UNLOCKING, LOGOUT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static enum lock_state state = LOCKED;
|
||||||
|
|
||||||
|
static GtkWidget *window, *unlockWindow, *lockLabel, *promptEntry, *messageLabel, *logoutButton, *unlockButton;
|
||||||
|
static gboolean enablePromptEntry = TRUE, enableLogoutButton = FALSE, enableUnlockButton = TRUE;
|
||||||
|
|
||||||
|
static char *username;
|
||||||
|
static char *logoutCommand = NULL;
|
||||||
|
static int logoutTime = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean do_grab_devices(gpointer user_data) {
|
||||||
|
DEBUG("do_grab_devices");
|
||||||
|
|
||||||
|
gtk_window_present(GTK_WINDOW(window));
|
||||||
|
|
||||||
|
GdkDeviceManager *deviceManager = gdk_display_get_device_manager(gdk_display_get_default());
|
||||||
|
GList *devices = gdk_device_manager_list_devices(deviceManager, GDK_DEVICE_TYPE_MASTER);
|
||||||
|
|
||||||
|
gboolean error = FALSE;
|
||||||
|
|
||||||
|
for (; devices; devices = g_list_next(devices)) {
|
||||||
|
GdkDevice *device = devices->data;
|
||||||
|
|
||||||
|
if (gdk_device_grab(device, gtk_widget_get_window(window), GDK_OWNERSHIP_APPLICATION, TRUE, GDK_ALL_EVENTS_MASK, NULL, GDK_CURRENT_TIME) != GDK_GRAB_SUCCESS)
|
||||||
|
error = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free(devices);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void grab_devices(void) {
|
||||||
|
if (do_grab_devices(NULL))
|
||||||
|
g_timeout_add_seconds(1, do_grab_devices, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update(void) {
|
||||||
|
gboolean locked = (state == LOCKED);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive(promptEntry, enablePromptEntry && locked);
|
||||||
|
gtk_widget_set_sensitive(logoutButton, enableLogoutButton && locked);
|
||||||
|
gtk_widget_set_sensitive(unlockButton, enableUnlockButton && locked);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean do_update_logout_time(gpointer user_data) {
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
char *escaped_username = g_markup_escape_text(username, -1);
|
||||||
|
char *message;
|
||||||
|
|
||||||
|
if (!logoutCommand) {
|
||||||
|
message = g_strdup_printf(_("This computer is currently locked by the user <i>%s</i>."), escaped_username);
|
||||||
|
enableLogoutButton = FALSE;
|
||||||
|
}
|
||||||
|
else if (logoutTime > 0) {
|
||||||
|
message = g_strdup_printf(_("This computer is currently locked by the user <i>%s</i>.\nThe user can be logged out in %02u:%02u minutes."), escaped_username, logoutTime/60, logoutTime%60);
|
||||||
|
enableLogoutButton = FALSE;
|
||||||
|
ret = TRUE;
|
||||||
|
logoutTime--;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
message = g_strdup_printf(_("This computer is currently locked by the user <i>%s</i>.\nThe user can be logged out now."), escaped_username);
|
||||||
|
enableLogoutButton = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_label_set_markup(GTK_LABEL(lockLabel), message);
|
||||||
|
g_free(message);
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_logout_time() {
|
||||||
|
if (do_update_logout_time(NULL))
|
||||||
|
g_timeout_add_seconds(1, do_update_logout_time, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lock(void) {
|
||||||
|
if (state != LOCKED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DEBUG("lock");
|
||||||
|
|
||||||
|
update();
|
||||||
|
grab_devices();
|
||||||
|
gtk_widget_grab_focus(promptEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ulock_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) {
|
||||||
|
char *password = appdata_ptr;
|
||||||
|
|
||||||
|
*resp = calloc(num_msg, sizeof(struct pam_response));
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < num_msg; i++) {
|
||||||
|
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF)
|
||||||
|
resp[i]->resp = strdup(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean try_unlock_return(gpointer message) {
|
||||||
|
DEBUG("try_unlock_return");
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
state = LOCKED;
|
||||||
|
gtk_entry_set_text(GTK_ENTRY(promptEntry), "");
|
||||||
|
gtk_label_set_label(GTK_LABEL(messageLabel), message);
|
||||||
|
lock();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gtk_main_quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this thread must not access any GTK resources */
|
||||||
|
static void* try_unlock_thread(void *arg) {
|
||||||
|
const struct pam_conv conv = {.conv = ulock_conv, .appdata_ptr = arg};
|
||||||
|
|
||||||
|
pam_handle_t *handle = NULL;
|
||||||
|
int ret = pam_start("login", username, &conv, &handle);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
ret = pam_authenticate(handle, 0);
|
||||||
|
|
||||||
|
const char *message = NULL;
|
||||||
|
if (ret)
|
||||||
|
message = pam_strerror(handle, ret);
|
||||||
|
|
||||||
|
pam_end(handle, ret);
|
||||||
|
|
||||||
|
g_idle_add(try_unlock_return, (gpointer)message);
|
||||||
|
|
||||||
|
free(arg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void try_unlock(void) {
|
||||||
|
if (state != LOCKED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DEBUG("try_unlock");
|
||||||
|
|
||||||
|
state = UNLOCKING;
|
||||||
|
update();
|
||||||
|
gtk_label_set_label(GTK_LABEL(messageLabel), "");
|
||||||
|
|
||||||
|
pthread_t thread;
|
||||||
|
pthread_create(&thread, NULL, try_unlock_thread, strdup((char*)gtk_entry_get_text(GTK_ENTRY(promptEntry))));
|
||||||
|
pthread_detach(thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void logout(void) {
|
||||||
|
if (state != LOCKED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!logoutCommand)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (logoutTime > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DEBUG("logout");
|
||||||
|
|
||||||
|
state = LOGOUT;
|
||||||
|
update();
|
||||||
|
|
||||||
|
system(logoutCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkFilterReturn xevent_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data) {
|
||||||
|
XEvent *ev = xevent;
|
||||||
|
|
||||||
|
switch (ev->xany.type) {
|
||||||
|
case MapNotify:
|
||||||
|
case ConfigureNotify:
|
||||||
|
if (ev->xany.window != gdk_x11_window_get_xid(gtk_widget_get_window(window)))
|
||||||
|
gtk_window_present(GTK_WINDOW(window));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GDK_FILTER_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void create_lock_window(void) {
|
||||||
|
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
|
|
||||||
|
gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
|
||||||
|
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window), TRUE);
|
||||||
|
gtk_window_set_skip_pager_hint(GTK_WINDOW(window), TRUE);
|
||||||
|
gtk_window_set_keep_above(GTK_WINDOW(window), TRUE);
|
||||||
|
gtk_window_fullscreen(GTK_WINDOW(window));
|
||||||
|
|
||||||
|
GtkWidget *overlay = gtk_overlay_new();
|
||||||
|
gtk_container_add(GTK_CONTAINER(window), overlay);
|
||||||
|
|
||||||
|
GtkWidget *bg = gtk_image_new_from_file(DATA_DIR "/bg.svg");
|
||||||
|
gtk_container_add(GTK_CONTAINER(overlay), bg);
|
||||||
|
|
||||||
|
GtkBuilder *builder = gtk_builder_new();
|
||||||
|
|
||||||
|
if (!gtk_builder_add_from_file(builder, DATA_DIR "/unlock.ui", NULL))
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
unlockWindow = GTK_WIDGET(gtk_builder_get_object(builder, "unlock_window"));
|
||||||
|
lockLabel = GTK_WIDGET(gtk_builder_get_object(builder, "lock_label"));
|
||||||
|
promptEntry = GTK_WIDGET(gtk_builder_get_object(builder, "prompt_entry"));
|
||||||
|
messageLabel = GTK_WIDGET(gtk_builder_get_object(builder, "message_label"));
|
||||||
|
logoutButton = GTK_WIDGET(gtk_builder_get_object(builder, "logout_button"));
|
||||||
|
unlockButton = GTK_WIDGET(gtk_builder_get_object(builder, "unlock_button"));
|
||||||
|
|
||||||
|
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), unlockWindow);
|
||||||
|
|
||||||
|
gtk_widget_show_all(overlay);
|
||||||
|
|
||||||
|
gtk_entry_set_text(GTK_ENTRY(promptEntry), "");
|
||||||
|
gtk_label_set_label(GTK_LABEL(messageLabel), "");
|
||||||
|
|
||||||
|
g_signal_connect(promptEntry, "activate", G_CALLBACK(try_unlock), NULL);
|
||||||
|
g_signal_connect(unlockButton, "clicked", G_CALLBACK(try_unlock), NULL);
|
||||||
|
g_signal_connect(logoutButton, "clicked", G_CALLBACK(logout), NULL);
|
||||||
|
g_signal_connect(window, "map-event", G_CALLBACK(lock), NULL);
|
||||||
|
g_signal_connect(window, "delete-event", G_CALLBACK(gtk_true), NULL);
|
||||||
|
|
||||||
|
XSelectInput(gdk_x11_get_default_xdisplay(), gdk_x11_get_default_root_xwindow(), SubstructureNotifyMask);
|
||||||
|
gdk_window_add_filter(NULL, (GdkFilterFunc)xevent_filter, NULL);
|
||||||
|
|
||||||
|
update_logout_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_username(void) {
|
||||||
|
struct passwd *passwd = getpwuid(getuid());
|
||||||
|
if (!passwd)
|
||||||
|
exit(2);
|
||||||
|
|
||||||
|
username = strdup(passwd->pw_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_config(void) {
|
||||||
|
GKeyFile *keyFile = g_key_file_new();
|
||||||
|
if (!g_key_file_load_from_file(keyFile, CONFIG_FILE, G_KEY_FILE_NONE, NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gchar *theme = g_key_file_get_string(keyFile, "ulock", "theme", NULL);
|
||||||
|
if (theme)
|
||||||
|
gtk_settings_set_string_property(gtk_settings_get_default(), "gtk-theme-name", theme, "ulock");
|
||||||
|
|
||||||
|
logoutTime = g_key_file_get_integer(keyFile, "ulock", "logout_timeout", NULL);
|
||||||
|
|
||||||
|
gchar *logoutCommandConfig = g_key_file_get_string(keyFile, "ulock", "logout_string", NULL);
|
||||||
|
if (logoutCommandConfig)
|
||||||
|
logoutCommand = strdup(logoutCommandConfig);
|
||||||
|
|
||||||
|
g_key_file_free(keyFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
get_username();
|
||||||
|
logoutCommand = strdup("echo foo");
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
bindtextdomain("ulock", PREFIX "/share/locale");
|
||||||
|
textdomain("ulock");
|
||||||
|
|
||||||
|
openlog("ulock", LOG_PID, LOG_DAEMON);
|
||||||
|
|
||||||
|
gtk_init(&argc, &argv);
|
||||||
|
load_config();
|
||||||
|
|
||||||
|
create_lock_window();
|
||||||
|
gtk_widget_show(window);
|
||||||
|
|
||||||
|
gtk_main();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in a new issue