commit e8fa223631a8af20e73200b6e4b1b579c20769d1 Author: Michael BOUCHAUD Date: Thu Aug 9 20:15:30 2012 +0000 entrance: Re welcome to entrance. The code comes from my previous project elsa. I hope not annoy anyone if I use this name. SVN revision: 75061 diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 0000000..47d5e39 --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,625 @@ +Notes on the Free Translation Project +************************************* + + Free software is going international! The Free Translation Project +is a way to get maintainers of free software, translators, and users all +together, so that will gradually become able to speak many languages. +A few packages already provide translations for their messages. + + If you found this `ABOUT-NLS' file inside a distribution, you may +assume that the distributed package does use GNU `gettext' internally, +itself available at your nearest GNU archive site. But you do _not_ +need to install GNU `gettext' prior to configuring, installing or using +this package with messages translated. + + Installers will find here some useful hints. These notes also +explain how users should proceed for getting the programs to use the +available translations. They tell how people wanting to contribute and +work at translations should contact the appropriate team. + + When reporting bugs in the `intl/' directory or bugs which may be +related to internationalization, you should tell about the version of +`gettext' which is used. The information can be found in the +`intl/VERSION' file, in internationalized packages. + +Quick configuration advice +========================== + + If you want to exploit the full power of internationalization, you +should configure it using + + ./configure --with-included-gettext + +to force usage of internationalizing routines provided within this +package, despite the existence of internationalizing capabilities in the +operating system where this package is being installed. So far, only +the `gettext' implementation in the GNU C library version 2 provides as +many features (such as locale alias, message inheritance, automatic +charset conversion or plural form handling) as the implementation here. +It is also not possible to offer this additional functionality on top +of a `catgets' implementation. Future versions of GNU `gettext' will +very likely convey even more functionality. So it might be a good idea +to change to GNU `gettext' as soon as possible. + + So you need _not_ provide this option if you are using GNU libc 2 or +you have installed a recent copy of the GNU gettext package with the +included `libintl'. + +INSTALL Matters +=============== + + Some packages are "localizable" when properly installed; the +programs they contain can be made to speak your own native language. +Most such packages use GNU `gettext'. Other packages have their own +ways to internationalization, predating GNU `gettext'. + + By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system already +provides the GNU `gettext' functions. If not, the GNU `gettext' own +library will be used. This library is wholly contained within this +package, usually in the `intl/' subdirectory, so prior installation of +the GNU `gettext' package is _not_ required. Installers may use +special options at configuration time for changing the default +behaviour. The commands: + + ./configure --with-included-gettext + ./configure --disable-nls + +will respectively bypass any pre-existing `gettext' to use the +internationalizing routines provided within this package, or else, +_totally_ disable translation of messages. + + When you already have GNU `gettext' installed on your system and run +configure without an option for your new package, `configure' will +probably detect the previously built and installed `libintl.a' file and +will decide to use this. This might be not what is desirable. You +should use the more recent version of the GNU `gettext' library. I.e. +if the file `intl/VERSION' shows that the library which comes with this +package is more recent, you should use + + ./configure --with-included-gettext + +to prevent auto-detection. + + The configuration process will not test for the `catgets' function +and therefore it will not be used. The reason is that even an +emulation of `gettext' on top of `catgets' could not provide all the +extensions of the GNU `gettext' library. + + Internationalized packages have usually many `po/LL.po' files, where +LL gives an ISO 639 two-letter code identifying the language. Unless +translations have been forbidden at `configure' time by using the +`--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable `LINGUAS' +may be set, prior to configuration, to limit the installed set. +`LINGUAS' should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +Using This Package +================== + + As a user, if your language has been installed for this package, you +only have to set the `LANG' environment variable to the appropriate +`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, +and `CC' is an ISO 3166 two-letter country code. For example, let's +suppose that you speak German and live in Germany. At the shell +prompt, merely execute `setenv LANG de_DE' (in `csh'), +`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). +This can be done from your `.login' or `.profile' file, once and for +all. + + You might think that the country code specification is redundant. +But in fact, some languages have dialects in different countries. For +example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The +country code serves to distinguish the dialects. + + The locale naming convention of `LL_CC', with `LL' denoting the +language and `CC' denoting the country, is the one use on systems based +on GNU libc. On other systems, some variations of this scheme are +used, such as `LL' or `LL_CC.ENCODING'. You can get the list of +locales supported by your system for your country by running the command +`locale -a | grep '^LL''. + + Not all programs have translations for all languages. By default, an +English message is shown in place of a nonexistent translation. If you +understand other languages, you can set up a priority list of languages. +This is done through a different environment variable, called +`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' +for the purpose of message handling, but you still need to have `LANG' +set to the primary language; this is required by other parts of the +system libraries. For example, some Swedish users who would rather +read translations in German than English for when Swedish is not +available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. + + In the `LANGUAGE' environment variable, but not in the `LANG' +environment variable, `LL_CC' combinations can be abbreviated as `LL' +to denote the language's main dialect. For example, `de' is equivalent +to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' +(Portuguese as spoken in Portugal) in this context. + +Translating Teams +================= + + For the Free Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list. The up-to-date list of +teams can be found at the Free Translation Project's homepage, +`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" +area. + + If you'd like to volunteer to _work_ at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is _not_ the same as the list itself, it has +`-request' appended. For example, speakers of Swedish can send a +message to `sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate +_actively_ in translations, or at solving translational difficulties, +rather than merely lurking around. If your team does not exist yet and +you want to start one, or if you are unsure about what to do or how to +get started, please write to `translation@iro.umontreal.ca' to reach the +coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing +the terminology in use. Proven linguistic skill are praised more than +programming skill, here. + +Available Packages +================== + + Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of May 2003. +The matrix shows, in regard of each package, for which languages PO +files have been submitted to translation coordination, with a +translation percentage of at least 50%. + + Ready PO files am az be bg ca cs da de el en en_GB eo es + +-------------------------------------------+ + a2ps | [] [] [] [] | + aegis | () | + anubis | | + ap-utils | | + bash | [] [] [] | + batchelor | | + bfd | [] [] | + binutils | [] [] | + bison | [] [] [] | + bluez-pin | [] [] | + clisp | | + clisp | [] [] [] | + coreutils | [] [] [] [] | + cpio | [] [] [] | + darkstat | () [] | + diffutils | [] [] [] [] [] [] [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] | + error | [] [] [] [] [] | + fetchmail | [] () [] [] [] [] | + fileutils | [] [] [] | + findutils | [] [] [] [] [] [] | + flex | [] [] [] [] | + gas | [] | + gawk | [] [] [] [] | + gcal | [] | + gcc | [] [] | + gettext | [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] | + gettext-tools | [] [] | + gimp-print | [] [] [] [] [] | + gliv | | + glunarclock | [] [] [] | + gnucash | () [] | + gnucash-glossary | [] () [] | + gnupg | [] () [] [] [] [] | + gpe-calendar | [] | + gpe-conf | [] | + gpe-contacts | [] | + gpe-edit | | + gpe-login | [] | + gpe-ownerinfo | [] | + gpe-sketchbook | [] | + gpe-timesheet | | + gpe-today | [] | + gpe-todo | [] | + gphoto2 | [] [] [] [] | + gprof | [] [] | + gpsdrive | () () () | + grep | [] [] [] [] [] | + gretl | [] | + hello | [] [] [] [] [] [] | + id-utils | [] [] | + indent | [] [] [] [] | + jpilot | [] [] [] [] | + jwhois | [] | + kbd | [] [] [] [] [] | + ld | [] [] | + libc | [] [] [] [] [] [] | + libgpewidget | [] | + libiconv | [] [] [] [] [] | + lifelines | [] () | + lilypond | [] | + lingoteach | | + lingoteach_lessons | () () | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailutils | [] [] | + make | [] [] [] | + man-db | [] () [] [] () | + mysecretdiary | [] [] [] | + nano | [] () [] [] [] | + nano_1_0 | [] () [] [] [] | + opcodes | [] [] | + parted | [] [] [] [] [] | + ptx | [] [] [] [] [] | + python | | + radius | | + recode | [] [] [] [] [] [] | + screem | | + sed | [] [] [] [] [] | + sh-utils | [] [] [] | + sharutils | [] [] [] [] [] [] | + sketch | [] () [] | + soundtracker | [] [] [] | + sp | [] | + tar | [] [] [] [] | + texinfo | [] [] [] [] | + textutils | [] [] [] [] | + tin | () () | + util-linux | [] [] [] [] [] | + vorbis-tools | [] [] [] | + wastesedge | () | + wdiff | [] [] [] [] | + wget | [] [] [] [] [] [] [] | + xchat | [] [] [] | + xpad | | + +-------------------------------------------+ + am az be bg ca cs da de el en en_GB eo es + 0 1 4 2 31 17 54 60 14 1 4 12 56 + + et fa fi fr ga gl he hr hu id it ja ko + +----------------------------------------+ + a2ps | [] [] [] () () | + aegis | | + anubis | [] | + ap-utils | [] | + bash | [] [] | + batchelor | [] | + bfd | [] [] | + binutils | [] [] | + bison | [] [] [] [] | + bluez-pin | [] [] [] [] | + clisp | | + clisp | [] | + coreutils | [] [] [] [] | + cpio | [] [] [] [] | + darkstat | () [] [] [] | + diffutils | [] [] [] [] [] [] [] | + e2fsprogs | | + enscript | [] [] | + error | [] [] [] [] | + fetchmail | [] | + fileutils | [] [] [] [] [] | + findutils | [] [] [] [] [] [] [] [] [] [] [] | + flex | [] [] | + gas | [] | + gawk | [] [] | + gcal | [] | + gcc | [] | + gettext | [] [] [] | + gettext-runtime | [] [] [] [] | + gettext-tools | [] | + gimp-print | [] [] | + gliv | () | + glunarclock | [] [] [] [] | + gnucash | [] | + gnucash-glossary | [] | + gnupg | [] [] [] [] [] [] [] | + gpe-calendar | [] | + gpe-conf | | + gpe-contacts | [] | + gpe-edit | [] [] | + gpe-login | [] | + gpe-ownerinfo | [] [] [] | + gpe-sketchbook | [] | + gpe-timesheet | [] [] [] | + gpe-today | [] [] | + gpe-todo | [] [] | + gphoto2 | [] [] [] | + gprof | [] [] | + gpsdrive | () [] () () | + grep | [] [] [] [] [] [] [] [] [] [] [] | + gretl | [] | + hello | [] [] [] [] [] [] [] [] [] [] [] [] [] | + id-utils | [] [] [] | + indent | [] [] [] [] [] [] [] [] | + jpilot | [] () | + jwhois | [] [] [] [] | + kbd | [] | + ld | [] | + libc | [] [] [] [] [] [] | + libgpewidget | [] [] [] | + libiconv | [] [] [] [] [] [] [] [] | + lifelines | () | + lilypond | [] | + lingoteach | [] [] | + lingoteach_lessons | | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailutils | | + make | [] [] [] [] [] [] | + man-db | [] () () | + mysecretdiary | [] [] | + nano | [] [] [] [] | + nano_1_0 | [] [] [] [] | + opcodes | [] [] | + parted | [] [] [] | + ptx | [] [] [] [] [] [] [] | + python | | + radius | | + recode | [] [] [] [] [] [] | + screem | | + sed | [] [] [] [] [] [] [] [] | + sh-utils | [] [] [] [] [] [] | + sharutils | [] [] [] [] [] | + sketch | [] | + soundtracker | [] [] [] | + sp | [] () | + tar | [] [] [] [] [] [] [] [] [] | + texinfo | [] [] [] [] | + textutils | [] [] [] [] [] | + tin | [] () | + util-linux | [] [] [] [] () [] | + vorbis-tools | [] | + wastesedge | () | + wdiff | [] [] [] [] [] | + wget | [] [] [] [] [] [] [] [] | + xchat | [] [] [] | + xpad | | + +----------------------------------------+ + et fa fi fr ga gl he hr hu id it ja ko + 20 1 15 73 14 24 8 10 30 31 19 31 9 + + lg lt lv ms nb nl nn no pl pt pt_BR ro + +----------------------------------------+ + a2ps | [] [] () () () [] [] | + aegis | () | + anubis | [] [] | + ap-utils | () | + bash | [] | + batchelor | | + bfd | | + binutils | | + bison | [] [] [] [] | + bluez-pin | [] | + clisp | | + clisp | [] | + coreutils | [] | + cpio | [] [] [] | + darkstat | [] [] [] [] | + diffutils | [] [] [] | + e2fsprogs | | + enscript | [] [] | + error | [] [] | + fetchmail | () () | + fileutils | [] | + findutils | [] [] [] [] | + flex | [] | + gas | | + gawk | [] | + gcal | | + gcc | | + gettext | [] | + gettext-runtime | [] | + gettext-tools | | + gimp-print | [] | + gliv | [] | + glunarclock | [] | + gnucash | | + gnucash-glossary | [] [] | + gnupg | | + gpe-calendar | [] [] | + gpe-conf | [] [] | + gpe-contacts | [] | + gpe-edit | [] [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] | + gpe-sketchbook | [] [] | + gpe-timesheet | [] [] | + gpe-today | [] [] | + gpe-todo | [] [] | + gphoto2 | | + gprof | [] | + gpsdrive | () () () | + grep | [] [] [] [] | + gretl | | + hello | [] [] [] [] [] [] [] [] [] | + id-utils | [] [] [] | + indent | [] [] [] | + jpilot | () () | + jwhois | [] [] [] | + kbd | | + ld | | + libc | [] [] [] [] | + libgpewidget | [] [] | + libiconv | [] [] | + lifelines | | + lilypond | [] | + lingoteach | | + lingoteach_lessons | | + lynx | [] [] | + m4 | [] [] [] [] | + mailutils | | + make | [] [] | + man-db | [] | + mysecretdiary | [] | + nano | [] [] [] [] | + nano_1_0 | [] [] [] [] | + opcodes | [] [] [] | + parted | [] [] [] | + ptx | [] [] [] [] [] [] [] | + python | | + radius | | + recode | [] [] [] | + screem | | + sed | [] [] | + sh-utils | [] | + sharutils | [] | + sketch | [] | + soundtracker | | + sp | | + tar | [] [] [] [] [] [] | + texinfo | [] | + textutils | [] | + tin | | + util-linux | [] [] | + vorbis-tools | [] [] | + wastesedge | | + wdiff | [] [] [] [] | + wget | [] [] [] | + xchat | [] [] | + xpad | [] | + +----------------------------------------+ + lg lt lv ms nb nl nn no pl pt pt_BR ro + 0 0 2 11 7 26 3 4 18 15 34 34 + + ru sk sl sr sv ta tr uk vi wa zh_CN zh_TW + +-------------------------------------------+ + a2ps | [] [] [] [] [] | 16 + aegis | () | 0 + anubis | [] [] | 5 + ap-utils | () | 1 + bash | [] | 7 + batchelor | | 1 + bfd | [] [] [] | 7 + binutils | [] [] [] | 7 + bison | [] [] | 13 + bluez-pin | | 7 + clisp | | 0 + clisp | | 5 + coreutils | [] [] [] [] [] | 14 + cpio | [] [] [] | 13 + darkstat | [] () () | 9 + diffutils | [] [] [] [] | 21 + e2fsprogs | [] | 3 + enscript | [] [] [] | 11 + error | [] [] [] | 14 + fetchmail | [] | 7 + fileutils | [] [] [] [] [] [] | 15 + findutils | [] [] [] [] [] [] | 27 + flex | [] [] [] | 10 + gas | [] | 3 + gawk | [] [] | 9 + gcal | [] [] | 4 + gcc | [] | 4 + gettext | [] [] [] [] [] [] | 15 + gettext-runtime | [] [] [] [] [] [] | 16 + gettext-tools | [] [] | 5 + gimp-print | [] [] | 10 + gliv | | 1 + glunarclock | [] [] [] | 11 + gnucash | [] [] | 4 + gnucash-glossary | [] [] [] | 8 + gnupg | [] [] [] [] | 16 + gpe-calendar | [] | 5 + gpe-conf | | 3 + gpe-contacts | [] | 4 + gpe-edit | [] | 5 + gpe-login | [] | 5 + gpe-ownerinfo | [] | 7 + gpe-sketchbook | [] | 5 + gpe-timesheet | [] | 6 + gpe-today | [] | 6 + gpe-todo | [] | 6 + gphoto2 | [] [] | 9 + gprof | [] [] | 7 + gpsdrive | [] [] | 3 + grep | [] [] [] [] | 24 + gretl | | 2 + hello | [] [] [] [] [] | 33 + id-utils | [] [] [] | 11 + indent | [] [] [] [] | 19 + jpilot | [] [] [] [] [] | 10 + jwhois | () () [] [] | 10 + kbd | [] [] | 8 + ld | [] [] | 5 + libc | [] [] [] [] | 20 + libgpewidget | | 6 + libiconv | [] [] [] [] [] [] | 21 + lifelines | [] | 2 + lilypond | [] | 4 + lingoteach | | 2 + lingoteach_lessons | () | 0 + lynx | [] [] [] [] | 14 + m4 | [] [] [] | 15 + mailutils | | 2 + make | [] [] [] [] | 15 + man-db | [] | 6 + mysecretdiary | [] [] | 8 + nano | [] [] [] | 15 + nano_1_0 | [] [] [] | 15 + opcodes | [] [] | 9 + parted | [] [] | 13 + ptx | [] [] [] | 22 + python | | 0 + radius | | 0 + recode | [] [] [] [] | 19 + screem | [] | 1 + sed | [] [] [] [] [] | 20 + sh-utils | [] [] [] | 13 + sharutils | [] [] [] [] | 16 + sketch | [] | 5 + soundtracker | [] | 7 + sp | [] | 3 + tar | [] [] [] [] [] | 24 + texinfo | [] [] [] [] | 13 + textutils | [] [] [] [] [] | 15 + tin | | 1 + util-linux | [] [] | 14 + vorbis-tools | [] | 7 + wastesedge | | 0 + wdiff | [] [] [] [] | 17 + wget | [] [] [] [] [] [] [] | 25 + xchat | [] [] [] | 11 + xpad | | 1 + +-------------------------------------------+ + 50 teams ru sk sl sr sv ta tr uk vi wa zh_CN zh_TW + 97 domains 32 19 16 0 56 0 48 10 1 1 12 23 913 + + Some counters in the preceding matrix are higher than the number of +visible blocks let us expect. This is because a few extra PO files are +used for implementing regional variants of languages, or language +dialects. + + For a PO file in the matrix above to be effective, the package to +which it applies should also have been internationalized and +distributed as such by its maintainer. There might be an observable +lag between the mere existence a PO file and its wide availability in a +distribution. + + If May 2003 seems to be old, you may fetch a more recent copy of +this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date +matrix with full percentage details can be found at +`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. + +Using `gettext' in new packages +=============================== + + If you are writing a freely available program and want to +internationalize it you are welcome to use GNU `gettext' in your +package. Of course you have to respect the GNU Library General Public +License which covers the use of the GNU `gettext' library. This means +in particular that even non-free programs can use `libintl' as a shared +library, whereas only free software can use `libintl' as a static +library or use modified versions of `libintl'. + + Once the sources are changed appropriately and the setup can handle +the use of `gettext' the only thing missing are the translations. The +Free Translation Project is also available for packages which are not +developed inside the GNU project. Therefore the information given above +applies also for every other Free Software Project. Contact +`translation@iro.umontreal.ca' to make the `.pot' files available to +the translation teams. + diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..09df4f6 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Michael Bouchaud alias yoz +Carsten Haitzler diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..7f482d7 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,19 @@ +0.0.4 - + * users list + * user icon + * action suspend reboot shutdown ... + * new default theme + * grub2 compliant + +0.0.3 - + * minimize ressources whend logged + * correct the problem with event in session (we use xcb to take the + display) + +0.0.2 - + * client for user login with gui + * server with no gui aspect (lighter when logged) + * fix open session with pam + +0.0.1 - + * Initial version of entrance diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..812990b --- /dev/null +++ b/Makefile.am @@ -0,0 +1,18 @@ + +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = src data + +MAINTAINERCLEANFILES = \ +Makefile.in \ +config.guess \ +config.h.in \ +aclocal.m4 \ +config.h.in~ \ +config.sub \ +configure \ +depcomp \ +install-sh \ +missing \ +config.rpath \ +mkinstalldirs diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..f693d2b --- /dev/null +++ b/README @@ -0,0 +1,19 @@ +What entrance do: +open session with pam +User can choose the WM to open +Admin can make a script who are called to open session (/etc/X11/xinit/xinitrc) +Everything can be configured in elsa.conf + +You could put an customized icon for your user in /var/cache/elsa/users/(username).edj with groupname "elsa/user/icon" + +to enable grub2 reboot feature use --enable-grub2 on configure. But you need to +add this line 'GRUB_DEFAULT=saved' to /etc/default/grub + +build and install: +./autogen.sh --sysconfdir=/etc --prefix=/usr +make +make install + +on debian (ubuntu) you need to overide the pam file. +cp data/entrance.debian /etc/pam.d/entrance + diff --git a/TODO b/TODO new file mode 100644 index 0000000..1ee5454 --- /dev/null +++ b/TODO @@ -0,0 +1,14 @@ ++++enhance log ++++add some timers for error case ++++theme for cursor +++Make a very simple theme, to make a new theme easily +++Catch more Pam error on login (too many wrong password ...) ++Make a theme switcher on the fly with preview ++multisession ++authentification with fingerprint and others ++support Xephyr +Study possibility to use it with wayland so we can have transition when switching from one terminal to another. +white and black users list +virtual keyboard support + + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..c175198 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +rm -rf autom4te.cache +rm -f aclocal.m4 ltmain.sh + +autoreconf -f -i + +if [ -z "$NOCONFIGURE" ]; then + ./configure -C "$@" +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..8fc174a --- /dev/null +++ b/configure.ac @@ -0,0 +1,195 @@ +AC_INIT([entrance], [0.0.4], [enlightenment-devel@lists.sourceforge.net]) +AC_PREREQ([2.59]) +AC_CONFIG_SRCDIR([configure.ac]) +AC_CONFIG_MACRO_DIR([m4]) + +AC_CANONICAL_HOST + +AM_INIT_AUTOMAKE([1.6 dist-bzip2]) +AM_CONFIG_HEADER([config.h]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# m4_ifdef([AM_GNU_GETTEXT_VERSION], [ +# AM_GNU_GETTEXT_VERSION([0.12.1]) +# ]) + +# m4_ifdef([AM_GNU_GETTEXT], [ +# AM_GNU_GETTEXT([external]) +# po_makefile_in=po/Makefile.in +# AM_CONDITIONAL([HAVE_PO], [true]) +# ],[ +# AM_CONDITIONAL([HAVE_PO], [false]) +# ]) +# AC_SUBST(LTLIBINTL) + + +### Needed information + +# Set the localedir var for gettext +AC_DEFINE([LOCALEDIR], ["/usr/share/locale/"], ["locales"]) + + +### Additional options to configure + +# Pam +AC_ARG_ENABLE([pam], + [AC_HELP_STRING([--disable-pam], [disable pam support. @<:@default=enabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + enable_pam="yes" + else + enable_pam="no" + fi + ], + [enable_pam="yes"]) +AC_MSG_CHECKING([whether to support pam]) +AC_MSG_RESULT([${enable_pam}]) + +# Grub2 +AC_ARG_ENABLE([grub2], + [AC_HELP_STRING([--enable-gru2b], [enable grub2 support. @<:@default=disabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + enable_grub2="yes" + else + enable_grub2="no" + fi + ], + [enable_grub2="no"]) +AC_MSG_CHECKING([whether to support grub2 reboot features]) +AC_MSG_RESULT([${enable_grub2}]) + +if test "x${enable_grub2}" = "xyes" ; then + AC_DEFINE([HAVE_GRUB2], [1], [Set to 1 if grub is enabled.]) +fi + +# consolekit +AC_ARG_ENABLE([consolekit], + [AC_HELP_STRING([--disable-consolekit], [disable consolekit support. @<:@default=enabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + enable_consolekit="yes" + else + enable_consolekit="no" + fi + ], + [enable_consolekit="yes"]) +AC_MSG_CHECKING([whether to support consolekit login]) +AC_MSG_RESULT([${enable_consolekit}]) + + +# Set edje_cc path +AC_ARG_WITH([edje-cc], + [AC_HELP_STRING([ --with-edje-cc=PATH], [specify a specific path to edje_cc])], + [ + v=$withval; + edje_cc=$v + echo " Enlightenment edje_cc explicitly set to "$edje_cc; + ], + [edje_cc=$(pkg-config --variable=prefix edje)/bin/edje_cc]) +AC_SUBST(edje_cc) + +### Checks for programs +AC_PROG_CC + +### Checks for compiler characteristics +AC_USE_SYSTEM_EXTENSIONS +AC_ISC_POSIX +AC_PROG_CC_STDC +AC_HEADER_STDC +AC_C_CONST +AC_C___ATTRIBUTE__ + +### Checks for libraries + +PKG_CHECK_MODULES([ENTRANCE], [efreet >= 1.0.0 eina >= 1.0.0 eet >= 1.4.0 ecore-con >= 1.0.0 ecore >= 1.0.0 ecore-file >= 1.0.0 xcb >= 1.0.0]) +PKG_CHECK_MODULES([ENTRANCE_CLIENT], [eet >= 1.4.0 edje >= 1.0.0 elementary >= 0.5.0.0 ecore-evas >= 1.0.0 evas >= 1.0.0 ecore-con >= 1.0.0 ecore >= 1.0.0 ecore-x >= 1.0.0 eina >= 1.0.0]) + +# Consolekit +if test "x${enable_consolekit}" = "xyes" ; then + PKG_CHECK_MODULES([ENTRANCE_CK], [dbus-1 ck-connector], [enable_consolekit="yes"], [enable_consolekit="no"]) +fi + +AM_CONDITIONAL(HAVE_CONSOLEKIT, [test "x${enable_consolekit}" = "xyes"]) +if test "x${enable_consolekit}" = "xyes" ; then + AC_DEFINE([HAVE_CONSOLEKIT], [1], [Set to 1 if consolekit is enabled.]) +fi + +# Pam +if test "x${enable_pam}" = "xyes" ; then + AC_CHECK_LIB([pam], [pam_start], + [have_pam="yes"], + [have_pam="no"]) +fi + + +### Checks for header files + +# Pam +if test "x${have_pam}" = "xyes" ; then + AC_CHECK_HEADER([security/pam_appl.h], + [AC_DEFINE([HAVE_PAM], [1], [Set to 1 if pam is installed.])], + [have_pam="no"]) +else + have_pam="no" +fi + +AM_CONDITIONAL(HAVE_PAM, [test "x${have_pam}" = "xyes"]) + +### Checks for types + + +### Checks for structures +EFL_COMPILER_FLAG([-Wall]) +EFL_COMPILER_FLAG([-W]) +EFL_COMPILER_FLAG([-Wshadow]) +EFL_COMPILER_FLAG([-Wmissing-declarations]) + + +### Checks for linker characteristics + + +### Checks for library functions +AC_FUNC_MALLOC +AC_CHECK_FUNCS(strndup) + + +AC_OUTPUT([ +Makefile +src/Makefile +src/bin/Makefile +src/daemon/Makefile +data/Makefile +data/themes/Makefile +data/themes/old/Makefile +data/themes/beaumonts/Makefile +]) + + +##################################################################### +## Info + +echo +echo +echo +echo "------------------------------------------------------------------------" +echo "$PACKAGE_NAME $PACKAGE_VERSION" +echo "------------------------------------------------------------------------" +echo +echo "Configuration Options Summary:" +echo +echo " pam..................: ${have_pam}" +echo " grub2................: ${enable_grub2}" +echo " consolekit...........: ${enable_consolekit}" +echo +echo " edje_cc..............: ${edje_cc}" +echo +echo "Compilation............: make (or gmake)" +echo " CPPFLAGS.............: $CPPFLAGS" +echo " CFLAGS...............: $CFLAGS" +echo " LDFLAGS..............: $LDFLAGS" +echo +echo "Installation...........: make install (as root if needed, with 'su' or 'sudo')" +echo " prefix...............: $prefix" +echo + diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 0000000..8f65a68 --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,12 @@ + +MAINTAINERCLEANFILES = Makefile.in + +SUBDIRS = themes + +pamdir = $(sysconfdir)/pam.d/ +pam_DATA = entrance + +confdir = $(sysconfdir) +conf_DATA = entrance.conf + +EXTRA_DIST = entrance entrance.conf entrance.debian diff --git a/data/entrance b/data/entrance new file mode 100644 index 0000000..872c83d --- /dev/null +++ b/data/entrance @@ -0,0 +1,4 @@ +auth include system-auth +account include system-auth +password include system-auth +session include system-auth diff --git a/data/entrance.conf b/data/entrance.conf new file mode 100644 index 0000000..6a4d155 --- /dev/null +++ b/data/entrance.conf @@ -0,0 +1,59 @@ +group "Entrance_Config" struct { + value "session_path" string: "/bin:/usr/bin:/usr/local/bin"; + + /* X server path */ + value "xinit_path" string: "/usr/bin/X"; + /* X server args */ + value "xinit_args" string: "-nolisten tcp -br vt7"; + + /* xauth path binary */ + value "xauth_path" string: "/usr/bin/xauth"; + /* xauth file for server */ + value "xauth_file" string: "/var/run/entrance.auth"; + + + /* Commands executed when starting a session */ + value "session_start" string: "/usr/bin/sessreg -a -l :0.0"; + /* Command executed when login. Warning xsession must be set to 0 */ + value "session_login" string: "/bin/bash -login /etc/X11/xinit/xinitrc"; + /* Commands executed when exiting a session */ + value "session_stop" string: "/usr/bin/sessreg -d -l :0.0"; + + + /* Commands executed to shutdown */ + value "shutdown" string: "/sbin/shutdown -h now"; + /* Command executed to reboot */ + value "reboot" string: "/sbin/shutdown -r now"; + /* Command executed to suspend */ + value "suspend" string: "/usr/sbin/pm-suspend"; + + + /** Start in daemon mode. This can be overriden by the command line + * 1 = True, 0 = False */ + value "daemonize" uchar: 1; + + /* Enable numlock */ + value "numlock" uchar: 1; + + /** Bool to determine if entrance must login user with the session_login command + * or use xdg desktop and determine the command to use + * 1 = desktop_file_cmd, 0 = session_login */ + value "xsessions" uchar: 1; + + /** Bool to determine if entrance must autologin user when X start + * 1 = autologin enabled, 0 = autologin disabled */ + value "autologin" uchar: 0; + + /* The name of the user to use when autologin are enabled */ + value "userlogin" string: "myusername"; + + + /* Lock file */ + value "lockfile" string: "/var/run/entrance.pid"; + + /* Log file */ + value "logfile" string: "/var/log/entrance.log"; + + /* Theme to use */ + value "theme" string: "default"; +} diff --git a/data/entrance.debian b/data/entrance.debian new file mode 100644 index 0000000..a9fdae8 --- /dev/null +++ b/data/entrance.debian @@ -0,0 +1,12 @@ +#%PAM-1.0 +auth requisite pam_nologin.so +auth required pam_env.so readenv=1 +auth required pam_env.so readenv=1 envfile=/etc/default/locale +@include common-auth +auth optional pam_gnome_keyring.so +@include common-account +session required pam_limits.so +@include common-session +session optional pam_gnome_keyring.so auto_start +@include common-password + diff --git a/data/themes/Makefile.am b/data/themes/Makefile.am new file mode 100644 index 0000000..ca8d44b --- /dev/null +++ b/data/themes/Makefile.am @@ -0,0 +1,4 @@ +MAINTAINERCLEANFILES = Makefile.in + +SUBDIRS = beaumonts old + diff --git a/data/themes/beaumonts/Makefile.am b/data/themes/beaumonts/Makefile.am new file mode 100644 index 0000000..5431a6e --- /dev/null +++ b/data/themes/beaumonts/Makefile.am @@ -0,0 +1,36 @@ +AUTOMAKE_OPTIONS = 1.4 foreign +MAINTAINERCLEANFILES = Makefile.in + +EDJE_CC = @edje_cc@ +EDJE_FLAGS = -v -id $(top_srcdir)/data/themes/beaumonts -fd $(top_srcdir)/data/themes/beaumonts + +filesdir = $(datadir)/entrance/themes/ +files_DATA = default.edj + +EXTRA_DIST = \ +beaumonts.edc \ +entrance_background.jpg \ +entrance_foreground.png \ +box_login.png \ +box_login_shine.png \ +login_box.png \ +check.png \ +arrow_left.png \ +logo_b.png \ +logo_w.png \ +star.png \ +user.png \ +password.png \ +moon.png \ +xsession.png \ +silhouette.png + + +default.edj: Makefile $(EXTRA_DIST) + $(EDJE_CC) $(EDJE_FLAGS) \ + $(top_srcdir)/data/themes/beaumonts/beaumonts.edc \ + $(top_builddir)/data/themes/beaumonts/default.edj + +clean-local: + rm -f *.edj + diff --git a/data/themes/beaumonts/arrow_left.png b/data/themes/beaumonts/arrow_left.png new file mode 100644 index 0000000..fbe0795eaa Binary files /dev/null and b/data/themes/beaumonts/arrow_left.png differ diff --git a/data/themes/beaumonts/beaumonts.edc b/data/themes/beaumonts/beaumonts.edc new file mode 100644 index 0000000..2d10f98 --- /dev/null +++ b/data/themes/beaumonts/beaumonts.edc @@ -0,0 +1,942 @@ +/* + * Beaumonts theme for Elsa + * By Philippe Caseiro, Michael Bouchaud + * Licence CC-By-Sa + * Photo by Philippe Caseiro + * Licence CC-By-Sa + */ + +externals { + external: "elm"; +} + +collections { + group { + name : "entrance"; + + images { + image: "entrance_background.jpg" LOSSY 90; + image: "login_box.png" COMP; + image: "logo_b.png" COMP; + image: "user.png" COMP; + image: "password.png" COMP; + image: "xsession.png" COMP; + image: "box_login.png" COMP; + image: "box_login_shine.png" COMP; + image: "check.png" COMP; + image: "arrow_left.png" COMP; + } + + script { + public valid; + } + + parts { + part { + name: "background"; + mouse_events: 0; + type: IMAGE; + description { + min: 1024 600; + state: "default" 0.0; + image.normal: "entrance_background.jpg"; + visible: 1; + } + } + + part { name: "welcome"; + type: TEXT; + mouse_events: 0; + effect: SHADOW; + scale: 1; + description { state: "default" 0.0; + fixed: 1 1; + rel1.relative: 0.5 0.0; + rel1.offset: 0 150; + rel2.relative: 0.5 0.0; + rel2.offset: 0 150; + text { + text: "Welcome on board"; + font: "Sans"; + size: 18; + min: 1 1; + align: 0.5 0.5; + } + } + } + part { name: "clip"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + color: 255 255 255 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + color: 255 255 255 255; + } + } + + + part { + name: "box_login"; + type: RECT; + clip_to: "clip"; + mouse_events: 0; + description { + state: "default" 0.0; + rel1.relative: 0.1 0.1; + rel1.to: "background"; + max: 400 400; + rel2.relative: 0.9 0.9; + rel2.to: "background"; + visible: 1; + } + } + + part { name: "clip_password"; + type: RECT; + clip_to: "clip"; + description { state: "default" 0.0; + rel1.to_x: "bg_box_login"; + rel1.to_y: "hostname"; + rel1.offset: 30 1; + rel1.relative: 0.0 1.0; + rel2.to: "bg_box_login"; + rel2.offset: -31 -31; + } + } + part { name: "clip_xsession"; + type: RECT; + clip_to: "clip"; + description { state: "default" 0.0; + rel1.to_x: "bg_box_login"; + rel1.to_y: "password"; + rel1.offset: 0 1; + rel1.relative: 0.0 1.0; + rel2.to: "bg_box_login"; + } + } + part { name: "clip_button"; + type: RECT; + clip_to: "clip"; + description { state: "default" 0.0; + rel1.to_x: "bg_box_login"; + rel1.to_y: "xsessions"; + rel1.relative: 0.0 1.0; + rel2.to: "bg_box_login"; + } + } + + part { + name: "bg_box_login"; + type: IMAGE; + clip_to: "clip"; + mouse_events: 0; + description { + state: "default" 0.0; + image.normal: "login_box.png"; + rel1.to: "box_login"; + rel2.to: "box_login"; + aspect : 1.0 1.0; + aspect_preference : BOTH; + visible: 1; + } + } + + part { + name: "logo"; + type: IMAGE; + clip_to: "box_login"; + description { + state: "default" 0.0; + image.normal: "logo_b.png"; + max: 90 90; + rel1.to: "box_login"; + /*rel1.relative: 0.1 0.1;*/ + rel2.to: "box_login"; + /*rel2.relative: 0.9 0.35;*/ + align: 0.5 0.25; + aspect: 1.0 1.0; + aspect_preference: BOTH; + } + } + part { name: "entrance_users"; + type: EXTERNAL; + clip_to: "clip_password"; +// source: "elm/list"; +// source: "elm/genlist"; + source: "elm/gengrid"; + description { state: "default" 0.0; + rel1.to: "clip_password"; + rel2.to: "clip_password"; + visible: 1; + params { + bool: "horizontal" 0; + double: "vertical page relative" 0.0; + int: "horizontal item size" 96; + int: "vertical item size" 120; + } + } + description { state: "auth" 0.0; + inherit: "default" 0.0; + rel1.relative: 0.0 1.0; + rel2.relative: 1.0 2.0; + } + } + + + part { name: "button_valid"; + clip_to: "clip_button"; + type: IMAGE; + description { state: "default" 0.0; + rel1.to: "valid"; + rel1.offset: -5 -10; + rel2.to: "valid"; + rel2.offset: 4 4; + image { + normal: "box_login.png"; + border: 15 15 15 15; + } + fill.smooth: 0; + } + } + + part { name: "valid"; + clip_to: "clip_button"; + type: IMAGE; + repeat_events: 0; + description { state: "default" 0.0; + min: 32 32; + max: 32 32; + rel1.to: "background_xsession"; + rel2.to: "background_xsession"; + align: 0.9 1.0; + image.normal: "check.png"; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + rel2.offset: 0 28; + } + } + + + part { name: "button_cancel"; + type: IMAGE; + clip_to: "clip_button"; + description { state: "default" 0.0; + rel1.to: "cancel"; + rel1.offset: -5 -10; + rel2.to: "cancel"; + rel2.offset: 4 4; + image { + normal: "box_login.png"; + border: 15 15 15 15; + } + fill.smooth: 0; + } + } + + part { name: "cancel"; + type: IMAGE; + clip_to: "clip_button"; + repeat_events: 0; + description { state: "default" 0.0; + min: 32 32; + max: 32 32; + rel1.to: "background_xsession"; + rel2.to: "background_xsession"; + align: 0.1 1.0; + image.normal: "arrow_left.png"; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + rel2.offset: -6 28; + } + } + + + + part { name: "background_xsession"; + type: IMAGE; + clip_to: "clip_xsession"; + mouse_events: 0; + description { state: "default" 0.0; + rel1 { + to_y: "xsessions"; + to_x: "box_login"; + offset: 50 -7; + } + rel2 { + to_y: "xsessions"; + to_x: "box_login"; + offset: -51 7; + } + image { + normal: "box_login.png"; + border: 15 15 15 15; + } + fill.smooth: 0; + } + } + + + part { name: "background_xsession_shine"; + type: IMAGE; + clip_to: "clip_xsession"; + mouse_events: 0; + description { state: "default" 0.0; + rel1 { + to: "background_xsession"; + relative: 0.0 0.0; + offset: 7 3; + } + rel2 { + to: "background_xsession"; + relative: 1.0 1.0; + offset: -4 -6; + } + image { + normal: "box_login_shine.png"; + border: 8 8 8 0; + } + } + } + + part { name: "xsessions"; + type: EXTERNAL; + clip_to: "clip_xsession"; + repeat_events: 0; + source: "elm/hoversel"; + description { state: "default" 0.0; + visible: 0; + min: 140 30; + rel1.to_y: "hostname"; + rel1.relative: 0.5 1.0; + rel2.to_y: "hostname"; + rel2.relative: 0.5 1.0; + align: 0.5 1.0; + visible: 1; + } + description { state: "auth" 0.0; + visible: 1; + min: 140 30; + rel1.to_y: "hostname"; + rel2.to_y: "hostname"; + inherit: "default" 0.0; + rel1.relative: 0.5 2.0; + rel2.relative: 0.5 2.0; + rel1.offset: 0 20; + rel2.offset: -1 21; + align: 0.5 0.0; + visible: 1; + } + description { state: "auth" 0.1; + inherit: "auth" 0.0; + rel1.offset: 0 13; + rel2.offset: -1 14; + } + description { state: "auth" 0.2; + inherit: "auth" 0.0; + } + description { state: "auth" 0.3; + inherit: "auth" 0.0; + rel1.offset: 0 16; + rel2.offset: -1 17; + } + description { state: "auth" 0.4; + inherit: "auth" 0.0; + } + description { state: "auth" 0.5; + inherit: "auth" 0.0; + rel1.offset: 0 18; + rel2.offset: -1 19; + } + description { state: "auth" 0.6; + inherit: "auth" 0.0; + } + } + part { + name: "logo_xsession"; + type: IMAGE; + clip_to: "clip_xsession"; + mouse_events: 0; + description { + state: "default" 0.0; + image.normal: "xsession.png"; + max: 29 29; + rel1.to: "xsessions"; + rel2.to: "xsessions"; + rel1.offset: -35 0; + align: 0.0 0.5; + visible: 1; + } + } + + + part { name: "background_password"; + type: IMAGE; + clip_to: "clip_password"; + mouse_events: 0; + description { state: "default" 0.0; + rel1 { + to_y: "password"; + to_x: "box_login"; + offset: 50 -7; + } + rel2 { + to_y: "password"; + to_x: "box_login"; + offset: -51 7; + } + image { + normal: "box_login.png"; + border: 15 15 15 15; + } + fill.smooth: 0; + } + } + + part { name: "background_password_shine"; + type: IMAGE; + clip_to: "clip_password"; + mouse_events: 0; + description { state: "default" 0.0; + rel1 { + to: "background_password"; + relative: 0.0 0.0; + offset: 7 3; + } + rel2 { + to: "background_password"; + relative: 1.0 1.0; + offset: -4 -6; + } + image { + normal: "box_login_shine.png"; + border: 8 8 8 0; + } + } + } + + part { + name: "password"; + clip_to: "clip_password"; + type: EXTERNAL; + repeat_events: 0; + source: "elm/entry"; + description { + state: "default" 0.0; + min: 140 30; + rel1.to_y: "hostname"; + rel1.relative: 0.5 0.9; + rel2.to_y: "hostname"; + rel2.relative: 0.5 0.9; + align: 0.5 1.0; + visible: 1; + params { + bool: "single line" 1; + bool: "editable" 1; + bool: "password" 1; + bool: "scrollable" 1; + } + } + description { state: "auth" 0.0; + inherit: "default" 0.0; + rel1.relative: 0.5 1.0; + rel1.offset: 0 10; + rel2.relative: 0.5 1.0; + rel2.offset: -1 11; + align: 0.5 0.0; + } + description { state: "auth" 0.1; + inherit: "default" 0.0; + rel1.relative: 0.5 1.0; + rel1.offset: 0 3; + rel2.relative: 0.5 1.0; + rel2.offset: -1 4; + align: 0.5 0.0; + } + description { state: "auth" 0.2; + inherit: "default" 0.0; + rel1.relative: 0.5 1.0; + rel1.offset: 0 10; + rel2.relative: 0.5 1.0; + rel2.offset: -1 11; + align: 0.5 0.0; + } + description { state: "auth" 0.3; + inherit: "default" 0.0; + rel1.relative: 0.5 1.0; + rel1.offset: 0 5; + rel2.relative: 0.5 1.0; + rel2.offset: -1 6; + align: 0.5 0.0; + } + description { state: "auth" 0.4; + inherit: "default" 0.0; + rel1.relative: 0.5 1.0; + rel1.offset: 0 10; + rel2.relative: 0.5 1.0; + rel2.offset: -1 11; + align: 0.5 0.0; + } + description { state: "auth" 0.5; + inherit: "default" 0.0; + rel1.relative: 0.5 1.0; + rel1.offset: 0 7; + rel2.relative: 0.5 1.0; + rel2.offset: -1 8; + align: 0.5 0.0; + } + description { state: "auth" 0.6; + inherit: "default" 0.0; + rel1.relative: 0.5 1.0; + rel1.offset: 0 10; + rel2.relative: 0.5 1.0; + rel2.offset: -1 11; + align: 0.5 0.0; + } + } + + part { + name: "logo_password"; + clip_to: "clip_password"; + type: IMAGE; + mouse_events: 0; + description { + state: "default" 0.0; + image.normal: "password.png"; + max: 29 29; + rel1.to: "password"; + rel2.to: "password"; + rel1.offset: -35 0; + align: 0.0 0.5; + visible: 1; + } + } + + part { name: "background_login"; + clip_to: "clip"; + type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + rel1 { + to_y: "hostname"; + to_x: "box_login"; + offset: 50 -7; + } + rel2 { + to_y: "hostname"; + to_x: "box_login"; + offset: -51 7; + } + image { + normal: "box_login.png"; + border: 15 15 15 15; + } + fill.smooth: 0; + } + } + + part { name: "background_login_shine"; + clip_to: "clip"; + type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + rel1 { + to: "background_login"; + relative: 0.0 0.0; + offset: 7 3; + } + rel2 { + to: "background_login"; + relative: 1.0 1.0; + offset: -4 -6; + } + image { + normal: "box_login_shine.png"; + border: 8 8 8 0; + } + } + } + + part { + name: "hostname"; + clip_to: "clip"; + type: EXTERNAL; + repeat_events: 0; + source: "elm/entry"; + description { + state: "default" 0.0; + min: 140 0; +// max: 140 30; + align: 0.5 0.0; + rel1.to_y: "logo"; + rel1.relative: 0.5 1.0; + rel2.to_y: "logo"; + rel2.relative: 0.5 1.0; + rel2.offset: -1 0; +// rel1.offset: 28 20; + visible: 1; + params { + bool: "single line" 1; + bool: "editable" 1; + bool: "scrollable" 1; + } + } + } + + part { + name: "logo_login"; + type: IMAGE; + clip_to: "clip"; + mouse_events: 0; + description { + state: "default" 0.0; + image.normal: "user.png"; + max: 29 29; + rel1.to: "hostname"; + rel2.to: "hostname"; + rel1.offset: -35 0; + align: 0.0 0.5; + visible: 1; + } + } + + part { name: "actions"; + type: EXTERNAL; + repeat_events: 0; + source: "elm/hoversel"; + description { state: "default" 0.0; + visible: 0; + min: 140 30; + max: 140 30; + align: 0.75 1.0; + } + description { state: "enabled" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + part { + name: "clock"; + type: EXTERNAL; + source: "elm/clock"; + mouse_events: 0; + description { + min: 40 10; + max: 80 20; + align: 0.5 0.90; + params { + bool: "show seconds" "1"; + } + } + } + + part { name: "error"; + type: TEXT; + mouse_events: 0; + effect: SOFT_SHADOW; + scale: 1; + description { state: "default" 0.0; + color: 255 255 255 0; + fixed: 1 1; + rel1.to: "box_login"; + rel1.relative: 0.5 1.0; + rel2.to: "box_login"; + rel2.relative: 0.5 1.0; + text { + text: "Error on login ! Maybee wrong password ?"; + font: "Sans"; + size: 18; + min: 1 1; + align: 0.5 0.5; + } + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + rel1.offset: 0 50; + rel2.offset: 0 50; + color: 255 255 255 255; + } + } + } + + /* + * + * PROGRAMS + * + */ + + programs { + program { + name: "init"; + signal: "load"; + source: ""; + script { + set_int(valid, 0); + } + } + program { + name: "show"; + signal: "show"; + source: ""; + action: STATE_SET "visible" 0.0; + transition: LINEAR 0.8; + target: "clip"; + } + program { + name: "login_error"; + signal: "entrance.auth.error"; + source: ""; + action: STATE_SET "visible" 0.0; + transition: DECELERATE 0.2; + target: "error"; + } + program { + name: "login_change"; + signal: "entrance.auth.change"; + source: ""; + action: STATE_SET "default" 0.0; + transition: ACCELERATE 0.4; + target: "error"; + } + program { + name: "go_to_auth"; + signal: "entrance.auth.enable"; + source: ""; + action: STATE_SET "auth" 0.0; + transition: ACCELERATE 0.4444; + target: "password"; + after: "go_to_auth1"; + after: "init"; + after: "show_cancel"; + after: "hide_valid_script"; + } + program { name: "go_to_auth1"; + action: STATE_SET "auth" 0.1; + transition: SINUSOIDAL 0.22; + target: "password"; + after: "go_to_auth2"; + } + program { name: "go_to_auth2"; + action: STATE_SET "auth" 0.2; + transition: ACCELERATE 0.17; + target: "password"; + after: "go_to_auth3"; + } + program { name: "go_to_auth3"; + action: STATE_SET "auth" 0.3; + transition: SINUSOIDAL 0.15; + target: "password"; + after: "go_to_auth4"; + } + program { name: "go_to_auth4"; + action: STATE_SET "auth" 0.4; + transition: ACCELERATE 0.13; + target: "password"; + after: "go_to_auth5"; + } + program { name: "go_to_auth5"; + action: STATE_SET "auth" 0.5; + transition: SINUSOIDAL 0.11; + target: "password"; + after: "go_to_auth6"; + } + program { name: "go_to_auth6"; + action: STATE_SET "auth" 0.6; + transition: ACCELERATE 0.1; + target: "password"; + } + program { + name: "go1_to_auth"; + signal: "entrance.auth.enable"; + source: ""; + action: STATE_SET "auth" 0.0; + transition: ACCELERATE 0.8; + target: "xsessions"; + target: "entrance_users"; + after: "go1_to_auth1"; + } + program { name: "go1_to_auth1"; + action: STATE_SET "auth" 0.1; + transition: SINUSOIDAL 0.3; + target: "xsessions"; + after: "go1_to_auth2"; + } + program { name: "go1_to_auth2"; + action: STATE_SET "auth" 0.2; + transition: ACCELERATE 0.2; + target: "xsessions"; + after: "go1_to_auth3"; + } + program { name: "go1_to_auth3"; + action: STATE_SET "auth" 0.3; + transition: SINUSOIDAL 0.17; + target: "xsessions"; + after: "go1_to_auth4"; + } + program { name: "go1_to_auth4"; + action: STATE_SET "auth" 0.4; + transition: ACCELERATE 0.13; + target: "xsessions"; + after: "go1_to_auth5"; + } + program { name: "go1_to_auth5"; + action: STATE_SET "auth" 0.5; + transition: SINUSOIDAL 0.11; + target: "xsessions"; + after: "go1_to_auth6"; + } + program { name: "go1_to_auth6"; + action: STATE_SET "auth" 0.6; + transition: ACCELERATE 0.1; + target: "xsessions"; + } + program { + name: "go_to_start"; + signal: "entrance.auth.disable"; + source: ""; + action: STATE_SET "default" 0.0; + transition: LINEAR 0.5; +// target: "hostname"; + target: "password"; + target: "xsessions"; + target: "entrance_users"; + after: "hide_cancel"; + after: "hide_valid_script"; + } + program { + name: "login"; + signal: "entrance.auth.valid"; + source: ""; + action: STATE_SET "default" 0.0; + transition: LINEAR 0.7; + target: "clip"; + } + program { + name: "show_cancel"; + action: STATE_SET "visible" 0.0; + transition: SINUSOIDAL 0.6; + target: "cancel"; + } + program { + name: "hide_cancel"; + action: STATE_SET "default" 0.0; + transition: ACCELERATE 0.4; + target: "cancel"; + } + program { + name: "login_cancel"; + signal: "mouse,down,*"; + source: "cancel"; + action: SIGNAL_EMIT "entrance.auth.cancel" ""; + after: "hide_cancel"; + } + program { + name: "show_valid_script"; + signal: "cursor,changed"; + source: "*"; + script { + new val; + val = get_int(valid); + if (val == 0) { + run_program(PROGRAM:"show_valid"); + set_int(valid, 1); + } + } + } + program { name: "hide_valid_script"; + script { + set_int(valid, 0); + run_program(PROGRAM:"hide_valid"); + } + } + program { + name: "show_valid"; + action: STATE_SET "visible" 0.0; + transition: SINUSOIDAL 0.8; + target: "valid"; + } + program { + name: "hide_valid"; + action: STATE_SET "default" 0.0; + transition: ACCELERATE 0.4; + target: "valid"; + } + program { + name: "login_valid"; + signal: "mouse,down,*"; + source: "valid"; + action: SIGNAL_EMIT "entrance.auth.request" ""; + } + + program { + name: "xsession_enabled"; + signal: "entrance.xsession.enabled"; + source: ""; + action: STATE_SET "enabled" 0.0; + target: "xsessions"; + } + program { + name: "xsession_disabled"; + signal: "entrance.xsession.disabled"; + source: ""; + action: STATE_SET "default" 0.0; + target: "xsessions"; + } + program { + name: "action_enabled"; + signal: "entrance.action.enabled"; + source: ""; + action: STATE_SET "enabled" 0.0; + target: "actions"; + } + program { + name: "action_disabled"; + signal: "entrance.action.disabled"; + source: ""; + action: STATE_SET "default" 0.0; + target: "actions"; + } + program { + name: "user_enabled"; + signal: "entrance.users.enabled"; + source: ""; + action: STATE_SET "enabled" 0.0; + target: "entrance_users"; + } + program { + name: "user_disabled"; + signal: "entrance.users.disabled"; + source: ""; + action: STATE_SET "default" 0.0; + target: "entrance_users"; + } + } + } + + group { name: "entrance/user/default"; + images { + image: "silhouette.png" COMP; + } + + parts { + part { + name: "icon"; + type: IMAGE; + mouse_events: 0; + description { + state: "default" 0.0; + image { + normal: "silhouette.png"; + scale_hint: STATIC; + } + aspect : 1.0 1.0; + aspect_preference : BOTH; + } + } + } + } +} + diff --git a/data/themes/beaumonts/box_login.png b/data/themes/beaumonts/box_login.png new file mode 100644 index 0000000..e1fbb28 Binary files /dev/null and b/data/themes/beaumonts/box_login.png differ diff --git a/data/themes/beaumonts/box_login_shine.png b/data/themes/beaumonts/box_login_shine.png new file mode 100644 index 0000000..db66166 Binary files /dev/null and b/data/themes/beaumonts/box_login_shine.png differ diff --git a/data/themes/beaumonts/check.png b/data/themes/beaumonts/check.png new file mode 100644 index 0000000..7d58e85 Binary files /dev/null and b/data/themes/beaumonts/check.png differ diff --git a/data/themes/beaumonts/entrance_background-ori.jpg b/data/themes/beaumonts/entrance_background-ori.jpg new file mode 100644 index 0000000..2c4b97c Binary files /dev/null and b/data/themes/beaumonts/entrance_background-ori.jpg differ diff --git a/data/themes/beaumonts/entrance_background.jpg b/data/themes/beaumonts/entrance_background.jpg new file mode 100644 index 0000000..5b45883 Binary files /dev/null and b/data/themes/beaumonts/entrance_background.jpg differ diff --git a/data/themes/beaumonts/entrance_foreground.png b/data/themes/beaumonts/entrance_foreground.png new file mode 100644 index 0000000..5470e0c Binary files /dev/null and b/data/themes/beaumonts/entrance_foreground.png differ diff --git a/data/themes/beaumonts/login_box.png b/data/themes/beaumonts/login_box.png new file mode 100644 index 0000000..69a3b53 Binary files /dev/null and b/data/themes/beaumonts/login_box.png differ diff --git a/data/themes/beaumonts/logo_b.png b/data/themes/beaumonts/logo_b.png new file mode 100644 index 0000000..0b79b69 Binary files /dev/null and b/data/themes/beaumonts/logo_b.png differ diff --git a/data/themes/beaumonts/logo_w.png b/data/themes/beaumonts/logo_w.png new file mode 100644 index 0000000..9f0c7a7 Binary files /dev/null and b/data/themes/beaumonts/logo_w.png differ diff --git a/data/themes/beaumonts/moon.png b/data/themes/beaumonts/moon.png new file mode 100644 index 0000000..0ac9eb4 Binary files /dev/null and b/data/themes/beaumonts/moon.png differ diff --git a/data/themes/beaumonts/password.png b/data/themes/beaumonts/password.png new file mode 100644 index 0000000..13348fa Binary files /dev/null and b/data/themes/beaumonts/password.png differ diff --git a/data/themes/beaumonts/silhouette.png b/data/themes/beaumonts/silhouette.png new file mode 100644 index 0000000..cdc95b7 Binary files /dev/null and b/data/themes/beaumonts/silhouette.png differ diff --git a/data/themes/beaumonts/star.png b/data/themes/beaumonts/star.png new file mode 100644 index 0000000..d16ce3f Binary files /dev/null and b/data/themes/beaumonts/star.png differ diff --git a/data/themes/beaumonts/user.png b/data/themes/beaumonts/user.png new file mode 100644 index 0000000..0586b78 Binary files /dev/null and b/data/themes/beaumonts/user.png differ diff --git a/data/themes/beaumonts/user_box.svg b/data/themes/beaumonts/user_box.svg new file mode 100644 index 0000000..35178d6 --- /dev/null +++ b/data/themes/beaumonts/user_box.svg @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/data/themes/beaumonts/xsession.png b/data/themes/beaumonts/xsession.png new file mode 100644 index 0000000..e1b23b2 Binary files /dev/null and b/data/themes/beaumonts/xsession.png differ diff --git a/data/themes/old/Makefile.am b/data/themes/old/Makefile.am new file mode 100644 index 0000000..e27c796 --- /dev/null +++ b/data/themes/old/Makefile.am @@ -0,0 +1,31 @@ +AUTOMAKE_OPTIONS = 1.4 foreign +MAINTAINERCLEANFILES = Makefile.in + +EDJE_CC = @edje_cc@ +EDJE_FLAGS = -v -id $(top_srcdir)/data/themes/old -fd $(top_srcdir)/data/themes/old + +filesdir = $(datadir)/entrance/themes/old +files_DATA = old.edj + +EXTRA_DIST = \ +default.edc \ +entrance_background.jpg \ +entrance_foreground.png \ +box_login.png \ +box_login_shine.png \ +check.png \ +arrow_left.png \ +logo_b.png \ +logo_w.png \ +star.png \ +moon.png + + +old.edj: Makefile $(EXTRA_DIST) + $(EDJE_CC) $(EDJE_FLAGS) \ + $(top_srcdir)/data/themes/old/default.edc \ + $(top_builddir)/data/themes/old/old.edj + +clean-local: + rm -f *.edj + diff --git a/data/themes/old/arrow_left.png b/data/themes/old/arrow_left.png new file mode 100644 index 0000000..fbe0795eaa Binary files /dev/null and b/data/themes/old/arrow_left.png differ diff --git a/data/themes/old/box_login.png b/data/themes/old/box_login.png new file mode 100644 index 0000000..e1fbb28 Binary files /dev/null and b/data/themes/old/box_login.png differ diff --git a/data/themes/old/box_login_shine.png b/data/themes/old/box_login_shine.png new file mode 100644 index 0000000..db66166 Binary files /dev/null and b/data/themes/old/box_login_shine.png differ diff --git a/data/themes/old/check.png b/data/themes/old/check.png new file mode 100644 index 0000000..7d58e85 Binary files /dev/null and b/data/themes/old/check.png differ diff --git a/data/themes/old/default.edc b/data/themes/old/default.edc new file mode 100644 index 0000000..d9d0950 --- /dev/null +++ b/data/themes/old/default.edc @@ -0,0 +1,867 @@ +externals { +external: "elm"; +} + + +collections { + group { name: "entrance"; + images { + image: "box_login.png" COMP; + image: "box_login_shine.png" COMP; + image: "check.png" COMP; + image: "arrow_left.png" COMP; + } + script { + public valid; + } + + parts { + part { name: "base"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + visible: 1; + color: 0 0 0 255; + } + } + + part { name: "wall"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + color: 255 255 255 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + color: 255 255 255 255; + } + } + + part { name: "wallpaper"; + clip_to: "wall"; + type: GROUP; + mouse_events: 0; + source: "entrance/background"; + description { state: "default" 0.0; + visible: 1; + } + } + + part { name: "button_cancel"; + type: IMAGE; + clip_to: "clip_button"; + description { state: "default" 0.0; + rel1.to: "cancel"; + rel1.offset: -5 -10; + rel2.to: "cancel"; + rel2.offset: 4 4; + image { + normal: "box_login.png"; + border: 15 15 15 15; + } + fill.smooth: 0; + } + } + + part { name: "cancel"; + type: IMAGE; + repeat_events: 0; + clip_to: "clip_button"; + description { state: "default" 0.0; + min: 32 32; + max: 32 32; + rel1.to: "background_login"; + rel2.to: "background_login"; + rel2.offset: -6 -10; + align: 0.1 1.0; + image.normal: "arrow_left.png"; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + rel2.offset: -6 28; + } + } + + part { name: "button_valid"; + type: IMAGE; + clip_to: "clip_button"; + description { state: "default" 0.0; + rel1.to: "valid"; + rel1.offset: -5 -10; + rel2.to: "valid"; + rel2.offset: 4 4; + image { + normal: "box_login.png"; + border: 15 15 15 15; + } + fill.smooth: 0; + } + } + + part { name: "valid"; + type: IMAGE; + repeat_events: 0; + clip_to: "clip_button"; + description { state: "default" 0.0; + min: 32 32; + max: 32 32; + rel1.to: "background_login"; + rel2.to: "background_login"; + rel2.offset: -6 -10; + align: 0.9 1.0; + image.normal: "check.png"; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + rel2.offset: -6 28; + } + } + + part { name: "box_login"; + type: RECT; + description { state: "default" 0.0; + rel1.relative: 0.3 0.57; + rel2.relative: 0.7 0.77; + visible: 0; + } + } + + part { name: "clip_button"; + type: RECT; + clip_to: "wall"; + description { state: "default" 0.0; + rel1 { + to_y: "background_login"; + relative: 0.0 1.0; + offset: -5 -5; + } + color: 255 255 255 255; + } + } + + part { name: "background_login"; + type: IMAGE; + mouse_events: 0; + clip_to: "wall"; + description { state: "default" 0.0; + rel1 { + to_y: "hostname"; + relative: 0.3 0.0; + offset: -9 -7; + } + rel2 { + to_y: "hostname"; + relative: 0.7 1.0; + offset: 7 7; + } + image { + normal: "box_login.png"; + border: 15 15 15 15; + } + fill.smooth: 0; + } + } + + part { name: "background_login_shine"; + type: IMAGE; + mouse_events: 0; + clip_to: "wall"; + description { state: "default" 0.0; + rel1 { + to: "background_login"; + relative: 0.0 0.0; + offset: 7 3; + } + rel2 { + to: "background_login"; + relative: 1.0 1.0; + offset: -4 -6; + } + image { + normal: "box_login_shine.png"; + border: 8 8 8 0; + } + } + } + + part { name: "clip_login"; + type: RECT; + mouse_events: 0; + clip_to: "wall"; + description { state: "default" 0.0; + rel1 { + to: "box_login"; + offset: 5 5; + } + rel2 { + to: "box_login"; + offset: -6 -6; + } + + color: 255 255 255 255; + } + } + + part { name: "label"; + type: TEXT; + mouse_events: 0; + effect: SOFT_SHADOW; + scale: 1; + clip_to: "wall"; + description { state: "default" 0.0; + fixed: 1 1; + rel1.relative: 0.5 0.0; + rel1.offset: 0 50; + rel2.relative: 0.5 0.0; + rel2.offset: 0 50; + text { + text: "Welcome"; + font: "Sans"; + size: 18; + min: 1 1; + align: 0.5 0.5; + } + } + } + + part { name: "error"; + type: TEXT; + mouse_events: 0; + effect: SOFT_SHADOW; + scale: 1; + clip_to: "wall"; + description { state: "default" 0.0; + color: 255 255 255 0; + fixed: 1 1; + rel1.to: "box_login"; + rel1.relative: 0.5 1.0; + rel2.to: "box_login"; + rel2.relative: 0.5 1.0; + text { + text: "Error on login ! Maybee wrong password ?"; + font: "Sans"; + size: 18; + min: 1 1; + align: 0.5 0.5; + } + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + rel1.offset: 0 50; + rel2.offset: 0 50; + color: 255 255 255 255; + } + } + + part { name: "xsessions"; + type: EXTERNAL; + repeat_events: 0; + clip_to: "wall"; + source: "elm/hoversel"; + description { state: "default" 0.0; + visible: 0; + min: 170 40; + max: 170 40; + align: 0.1 1.0; + } + description { state: "enabled" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + + part { name: "clock"; + type: EXTERNAL; + source: "elm/clock"; + mouse_events: 0; + clip_to: "wall"; + description { + min: 80 20; + max: 80 20; + align: 0.0 0.0; + params { + bool: "show seconds" "1"; + } + } + } + + part { name: "box_hostname"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + rel1.to: "box_login"; + rel2.to: "box_login"; + visible: 0; + } + description { state: "auth" 0.0; + inherit: "default" 0.0; + rel1.relative: -1.0 0.0; + rel2.relative: 0.0 1.0; + } + } + + part { name: "lbl_hostname"; + type: TEXT; + mouse_events: 0; + scale: 1; + effect: SOFT_SHADOW; + clip_to: "clip_login"; + description { state: "default" 0.0; + fixed: 1 1; + rel1.to: "box_hostname"; + rel2.to: "box_hostname"; + rel2.relative: 0.2 1.0; + align: 0.0 0.5; + text { + font: "Sans"; + size: 18; + text: "Login :"; + min: 1 1; + } + } + } + + part { name: "hostname"; + type: EXTERNAL; + repeat_events: 0; + clip_to: "clip_login"; + source: "elm/entry"; + description { state: "default" 0.0; + min: 160 20; + rel1 { + to: "lbl_hostname"; + relative: 1.0 0.0; + } + rel2 { + to_x: "box_hostname"; + to_y: "lbl_hostname"; + } + params { + bool: "single line" 1; + bool: "editable" 1; + bool: "scrollable" 1; + } + } + } + + + part { name: "box_password"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + rel1 { + to: "box_login"; + relative: 1.0 0.0; + } + rel2 { + to: "box_login"; + relative: 2.0 1.0; + } + visible: 0; + } + description { state: "auth" 0.0; + inherit: "default" 0.0; + rel1.relative: 0.0 0.0; + rel2.relative: 1.0 1.0; + } + } + + part { name: "lbl_password"; + type: TEXT; + mouse_events: 0; + scale: 1; + clip_to: "clip_login"; + effect: SOFT_SHADOW; + description { state: "default" 0.0; + fixed: 1 1; + rel1.to: "box_password"; + rel2.to: "box_password"; + rel2.relative: 0.2 1.0; + align: 0.0 0.5; + text { + font: "Sans"; + size: 18; + text: "Password :"; + min: 1 1; + } + } + } + + part { name: "password"; + type: EXTERNAL; + repeat_events: 0; + clip_to: "clip_login"; + source: "elm/entry"; + description { state: "default" 0.0; + min: 160 20; + rel1 { + to: "lbl_password"; + relative: 1.0 0.0; + } + rel2 { + to_x: "box_password"; + to_y: "lbl_password"; + } + params { + bool: "single line" 1; + bool: "editable" 1; + bool: "password" 1; + bool: "scrollable" 1; + } + } + description { state: "auth" 0.0; + inherit: "default" 0.0; + rel1.relative: 0.0 0.0; + rel2.relative: 1.0 1.0; + } + } + } + + programs { + program { name: "init"; + signal: "load"; + source: ""; + script { + set_int(valid, 0); + } + } + program { name: "show"; + signal: "show"; + source: ""; + action: STATE_SET "visible" 0.0; + transition: LINEAR 0.8; + target: "wall"; + } + program { name: "login_error"; + signal: "entrance.auth.error"; + source: ""; + action: STATE_SET "visible" 0.0; + transition: DECELERATE 0.2; + target: "error"; + } + program { name: "login_change"; + signal: "entrance.auth.change"; + source: ""; + action: STATE_SET "default" 0.0; + transition: ACCELERATE 0.4; + target: "error"; + } + program { name: "go_to_auth"; + signal: "entrance.auth.enable"; + source: ""; + action: STATE_SET "auth" 0.0; + transition: LINEAR 0.5; + target: "box_hostname"; + target: "box_password"; + after: "init"; + after: "show_cancel"; + after: "hide_valid"; + } + program { name: "go_to_start"; + signal: "entrance.auth.disable"; + source: ""; + action: STATE_SET "default" 0.0; + transition: LINEAR 0.5; + target: "box_hostname"; + target: "box_password"; + after: "init"; + after: "hide_cancel"; + after: "hide_valid"; + } + program { name: "login"; + signal: "entrance.auth.valid"; + source: ""; + action: STATE_SET "default" 0.0; + transition: LINEAR 0.7; + target: "wall"; + after: "close"; + } + program { name: "show_cancel"; + action: STATE_SET "visible" 0.0; + transition: SINUSOIDAL 0.6; + target: "cancel"; + } + program { name: "hide_cancel"; + action: STATE_SET "default" 0.0; + transition: ACCELERATE 0.4; + target: "cancel"; + } + program { name: "login_cancel"; + signal: "mouse,down,*"; + source: "cancel"; + action: SIGNAL_EMIT "entrance.auth.cancel" ""; + after: "hide_cancel"; + } + program { name: "show_valid_script"; + signal: "cursor,changed"; + source: "*"; + script { + new val; + val = get_int(valid); + if (val == 0) { + run_program(PROGRAM:"show_valid"); + set_int(valid, 1); + } + } + } + program { name: "show_valid"; + action: STATE_SET "visible" 0.0; + transition: SINUSOIDAL 0.8; + target: "valid"; + } + program { name: "hide_valid"; + action: STATE_SET "default" 0.0; + transition: ACCELERATE 0.4; + target: "valid"; + } + program { name: "login_valid"; + signal: "mouse,down,*"; + source: "valid"; + action: SIGNAL_EMIT "entrance.auth.request" ""; + } + program { name: "close"; + action: SIGNAL_EMIT "entrance.auth.end" ""; + } + program { name: "xsession_enabled"; + signal: "entrance.xsession.enabled"; + source: ""; + action: STATE_SET "enabled" 0.0; + target: "xsessions"; + } + program { name: "xsession_disabled"; + signal: "entrance.xsession.disabled"; + source: ""; + action: STATE_SET "default" 0.0; + target: "xsessions"; + } + } + } + + group { name: "entrance/background"; + images { + image: "logo_b.png" COMP; + image: "logo_w.png" COMP; + image: "entrance_background.jpg" COMP; + image: "entrance_foreground.png" COMP; + image: "moon.png" COMP; + } + parts { + part { name: "background"; + type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + image.normal: "entrance_background.jpg"; + } + } + + part { name: "logo"; + type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + image.normal: "logo_b.png"; + aspect: 1.0 1.0; + aspect_preference: BOTH; + align: 0.5 1.0; + rel1 { + to_x: "moon"; + to_y: "background"; + relative: 0.0 -1.0; + } + rel2 { + to_x: "moon"; + to_y: "background"; + relative: 1.0 0.0; + } + } + + description { state: "down" 0.0; + inherit: "default" 0.0; + align: 0.5 0.5; + rel1.to: "moon"; + rel1.relative: 0.0 0.0; + rel2.to: "moon"; + rel2.relative: 1.0 1.0; + } + + description { state: "bounce1" 0.0; + inherit: "default" 0.0; + align: 0.5 0.5; + rel1 { + to: "moon"; + relative: 0.0 0.0; + offset: 0 11; + } + rel2 { + to: "moon"; + offset: -1 10; + relative: 1.0 1.0; + } + } + description { state: "bounce2" 0.0; + inherit: "default" 0.0; + align: 0.5 0.5; + rel1 { + to: "moon"; + relative: 0.0 0.0; + offset: 0 -8; + } + rel2 { + to: "moon"; + offset: -1 -9; + relative: 1.0 1.0; + } + } + description { state: "bounce3" 0.0; + inherit: "default" 0.0; + align: 0.5 0.5; + rel1 { + to: "moon"; + relative: 0.0 0.0; + offset: 0 6; + } + rel2 { + to: "moon"; + offset: -1 5; + relative: 1.0 1.0; + } + } + description { state: "bounce4" 0.0; + inherit: "default" 0.0; + align: 0.5 0.5; + rel1 { + to: "moon"; + relative: 0.0 0.0; + offset: 0 -4; + } + rel2 { + to: "moon"; + offset: -1 -3; + relative: 1.0 1.0; + } + } + description { state: "bounce5" 0.0; + inherit: "default" 0.0; + align: 0.5 0.5; + rel1 { + to: "moon"; + relative: 0.0 0.0; + offset: 0 2; + } + rel2 { + to: "moon"; + offset: -1 1; + relative: 1.0 1.0; + } + } + } + part { name: "moon"; + type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + rel1 { + to: "background"; + relative: 0.5 0.3; + } + rel2 { + to: "background"; + relative: 0.6 0.4; + } + image.normal: "moon.png"; + } + } + + part { name: "moon2"; + mouse_events: 0; + type: RECT; + description { state: "defaault" 0.0; + rel1.to: "moon"; + rel2.to: "moon"; + } + } + part { name : "logo2"; + type :IMAGE; + mouse_events: 0; + clip_to: "moon2"; + description { state: "default" 0.0; + rel1.to: "logo"; + rel2.to: "logo"; + image.normal: "logo_w.png"; + color: 255 255 255 48; + } + } + + part { name: "star"; + type: GROUP; + mouse_events: 0; + source: "entrance/star"; + description { state: "default" 0.0; + rel1.relative: 0.5 0.2; + rel2.relative: 0.5 0.2; + visible: 1; + } + } + part { name: "star2"; + type: GROUP; + mouse_events: 0; + source: "entrance/star"; + description { state: "default" 0.0; + rel1.relative: 0.4567 0.2345; + rel2.relative: 0.4567 0.2345; + visible: 1; + } + } + part { name: "star3"; + type: GROUP; + mouse_events: 0; + source: "entrance/star"; + description { state: "default" 0.0; + rel1.relative: 0.4 0.4; + rel2.relative: 0.4 0.4; + } + } + part { name: "star4"; + type: GROUP; + mouse_events: 0; + source: "entrance/star"; + description { state: "default" 0.0; + rel1.relative: 0.6543 0.333; + rel2.relative: 0.6543 0.333; + } + } + part { name: "star5"; + type: GROUP; + mouse_events: 0; + source: "entrance/star"; + description { state: "default" 0.0; + rel1.relative: 0.76 0.1543; + rel2.relative: 0.76 0.1543; + } + } + part { name: "star6"; + type: GROUP; + mouse_events: 0; + source: "entrance/star"; + description { state: "default" 0.0; + rel1.relative: 0.06 0.2; + rel2.relative: 0.06 0.2; + } + } + part { name: "star7"; + type: GROUP; + mouse_events: 0; + source: "entrance/star"; + description { state: "default" 0.0; + rel1.relative: 0.1234 0.3532; + rel2.relative: 0.1234 0.3532; + } + } + part { name: "star8"; + type: GROUP; + mouse_events: 0; + source: "entrance/star"; + description { state: "default" 0.0; + rel1.relative: 0.252 0.2987; + rel2.relative: 0.252 0.2987; + } + } + part { name: "foreground"; + type: IMAGE; + mouse_events: 0; + description { state: "default" 0.0; + rel1 { + relative: 0.0 0.7; + } + rel2.offset: 0 0; + image.normal: "entrance_foreground.png"; + } + } + } + programs { + program { + name: "icon_go_down"; + in: 1 0; + signal: "show"; + source: ""; + action: STATE_SET "down" 0.0; + transition: ACCELERATE 0.8; + target: "logo"; + after: "icon_bounce1"; + } + program { name: "icon_bounce1"; + action: STATE_SET "bounce1" 0.0; + transition: DECELERATE 0.2; + target: "logo"; + after: "icon_bounce2"; + } + program { name: "icon_bounce2"; + action: STATE_SET "bounce2" 0.0; + transition: SINUSOIDAL 0.3; + target: "logo"; + after: "icon_bounce3"; + } + program { name: "icon_bounce3"; + action: STATE_SET "bounce3" 0.0; + transition: SINUSOIDAL 0.2; + target: "logo"; + after: "icon_bounce4"; + } + program { name: "icon_bounce4"; + action: STATE_SET "bounce4" 0.0; + transition: SINUSOIDAL 0.2; + target: "logo"; + after: "icon_bounce5"; + } + program { name: "icon_bounce5"; + action: STATE_SET "bounce5" 0.0; + transition: SINUSOIDAL 0.2; + target: "logo"; + after: "down"; + } + program { name: "down"; + action: STATE_SET "down" 0.0; + transition: ACCELERATE 0.1; + target: "logo"; + } + } + } + group { name: "entrance/star"; + images { + image: "star.png" COMP; + } + parts { + part { name: "star"; + type: IMAGE; + description { state: "default" 0.0; + min: 2 2; + image.normal: "star.png"; + color: 255 255 255 32; + } + } + } + programs { + program { + in: 2 3; + name: "update_shine"; + signal: "show"; + source: ""; + script { + new a; + a = round(sin(randf()) * 224) + 31; + custom_state(PART:"star", "default", 0.0); + set_state_val(PART:"star", STATE_COLOR, 255, 255, 255, a); + } + after: "shine"; + } + program { + name: "shine"; + transition: ACCELERATE 1.2; + action: STATE_SET "custom" 0.0; + target: "star"; + after: "update_shine"; + } + } + } +} + diff --git a/data/themes/old/entrance_background.jpg b/data/themes/old/entrance_background.jpg new file mode 100644 index 0000000..2c4b97c Binary files /dev/null and b/data/themes/old/entrance_background.jpg differ diff --git a/data/themes/old/entrance_foreground.png b/data/themes/old/entrance_foreground.png new file mode 100644 index 0000000..5470e0c Binary files /dev/null and b/data/themes/old/entrance_foreground.png differ diff --git a/data/themes/old/logo_b.png b/data/themes/old/logo_b.png new file mode 100644 index 0000000..0b79b69 Binary files /dev/null and b/data/themes/old/logo_b.png differ diff --git a/data/themes/old/logo_w.png b/data/themes/old/logo_w.png new file mode 100644 index 0000000..9f0c7a7 Binary files /dev/null and b/data/themes/old/logo_w.png differ diff --git a/data/themes/old/moon.png b/data/themes/old/moon.png new file mode 100644 index 0000000..0ac9eb4 Binary files /dev/null and b/data/themes/old/moon.png differ diff --git a/data/themes/old/star.png b/data/themes/old/star.png new file mode 100644 index 0000000..d16ce3f Binary files /dev/null and b/data/themes/old/star.png differ diff --git a/m4/ac_attribute.m4 b/m4/ac_attribute.m4 new file mode 100644 index 0000000..23479a9 --- /dev/null +++ b/m4/ac_attribute.m4 @@ -0,0 +1,47 @@ +dnl Copyright (C) 2004-2008 Kim Woelders +dnl Copyright (C) 2008 Vincent Torri +dnl That code is public domain and can be freely used or copied. +dnl Originally snatched from somewhere... + +dnl Macro for checking if the compiler supports __attribute__ + +dnl Usage: AC_C___ATTRIBUTE__ +dnl call AC_DEFINE for HAVE___ATTRIBUTE__ and __UNUSED__ +dnl if the compiler supports __attribute__, HAVE___ATTRIBUTE__ is +dnl defined to 1 and __UNUSED__ is defined to __attribute__((unused)) +dnl otherwise, HAVE___ATTRIBUTE__ is not defined and __UNUSED__ is +dnl defined to nothing. + +AC_DEFUN([AC_C___ATTRIBUTE__], +[ + +AC_MSG_CHECKING([for __attribute__]) + +AC_CACHE_VAL([ac_cv___attribute__], + [AC_TRY_COMPILE( + [ +#include + +int func(int x); +int foo(int x __attribute__ ((unused))) +{ + exit(1); +} + ], + [], + [ac_cv___attribute__="yes"], + [ac_cv___attribute__="no"] + )]) + +AC_MSG_RESULT($ac_cv___attribute__) + +if test "x${ac_cv___attribute__}" = "xyes" ; then + AC_DEFINE([HAVE___ATTRIBUTE__], [1], [Define to 1 if your compiler has __attribute__]) + AC_DEFINE([__UNUSED__], [__attribute__((unused))], [Macro declaring a function argument to be unused]) + else + AC_DEFINE([__UNUSED__], [], [Macro declaring a function argument to be unused]) +fi + +]) + +dnl End of ac_attribute.m4 diff --git a/m4/efl_compiler_flag.m4 b/m4/efl_compiler_flag.m4 new file mode 100644 index 0000000..618c6a6 --- /dev/null +++ b/m4/efl_compiler_flag.m4 @@ -0,0 +1,57 @@ +dnl Copyright (C) 2010 Vincent Torri +dnl and Albin Tonnerre +dnl That code is public domain and can be freely used or copied. + +dnl Macro that checks if a compiler flag is supported by the compiler. + +dnl Usage: EFL_COMPILER_FLAG(flag) +dnl flag is added to CFLAGS if supported. + +AC_DEFUN([EFL_COMPILER_FLAG], +[ + +CFLAGS_save="${CFLAGS}" +CFLAGS="${CFLAGS} $1" + +AC_LANG_PUSH([C]) +AC_MSG_CHECKING([whether the compiler supports $1]) + +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[]])], + [have_flag="yes"], + [have_flag="no"]) +AC_MSG_RESULT([${have_flag}]) + +if test "x${have_flag}" = "xno" ; then + CFLAGS="${CFLAGS_save}" +fi +AC_LANG_POP([C]) + +]) + +dnl Macro that checks if a linker flag is supported by the compiler. + +dnl Usage: EFL_LINKER_FLAG(flag) +dnl flag is added to CFLAGS if supported (will be passed to ld anyway). + +AC_DEFUN([EFL_LINKER_FLAG], +[ + +CFLAGS_save="${CFLAGS}" +CFLAGS="${CFLAGS} $1" + +AC_LANG_PUSH([C]) +AC_MSG_CHECKING([whether the compiler supports $1]) + +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[]])], + [have_flag="yes"], + [have_flag="no"]) +AC_MSG_RESULT([${have_flag}]) + +if test "x${have_flag}" = "xno" ; then + CFLAGS="${CFLAGS_save}" +fi +AC_LANG_POP([C]) + +]) diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..d7c9551 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = bin daemon + +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am new file mode 100644 index 0000000..2bc88ad --- /dev/null +++ b/src/bin/Makefile.am @@ -0,0 +1,27 @@ + +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir)/src/bin \ +-I$(top_builddir)/src/bin \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +-DSYSTEM_CONFIG_DIR=\"$(sysconfdir)\" \ +@ENTRANCE_CLIENT_CFLAGS@ + +internal_bindir=$(libdir)/entrance +internal_bin_PROGRAMS = entrance_client + +entrance_client_SOURCES = \ +../event/entrance_event.h \ +../event/entrance_event.c \ +entrance_client.h \ +entrance_client.c \ +entrance_connect.h \ +entrance_connect.c \ +entrance_gui.h \ +entrance_gui.c + + +entrance_client_LDFLAGS = +entrance_client_LDADD = @ENTRANCE_CLIENT_LIBS@ + diff --git a/src/bin/entrance_client.c b/src/bin/entrance_client.c new file mode 100644 index 0000000..b68fd6d --- /dev/null +++ b/src/bin/entrance_client.c @@ -0,0 +1,77 @@ +#include "entrance_client.h" +#include +#include +#include + +static const Ecore_Getopt options = +{ + "entrance_client", + "%prog [options]", + VERSION, + "(C) 2011 Enlightenment, see AUTHORS.", + "GPL, see COPYING", + "Launch gui client.", + EINA_TRUE, + { + ECORE_GETOPT_STORE_STR('d', "display", "specify the display to use"), + ECORE_GETOPT_STORE_STR('t', "theme", "specify the theme to use"), + ECORE_GETOPT_HELP ('h', "help"), + ECORE_GETOPT_VERSION('V', "version"), + ECORE_GETOPT_COPYRIGHT('R', "copyright"), + ECORE_GETOPT_LICENSE('L', "license"), + ECORE_GETOPT_SENTINEL + } +}; + +int +entrance_client_main(const char *theme) +{ + fprintf(stderr, PACKAGE"_client: client init\n"); + if (entrance_gui_init(theme)) return EXIT_FAILURE; + fprintf(stderr, PACKAGE"_client: client run\n"); + entrance_connect_init(); + elm_run(); + entrance_connect_shutdown(); + fprintf(stderr, PACKAGE"_client: client shutdown\n"); + entrance_gui_shutdown(); + return EXIT_SUCCESS; +} + +int +main(int argc, char **argv) +{ + int args; + unsigned char quit_option = 0; + char *display = NULL; + char *theme = NULL; + + Ecore_Getopt_Value values[] = + { + ECORE_GETOPT_VALUE_STR(display), + ECORE_GETOPT_VALUE_STR(theme), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option) + }; + args = ecore_getopt_parse(&options, values, argc, argv); + if (args < 0) + return EXIT_FAILURE; + if (quit_option) + return EXIT_SUCCESS; + if (!display) + { + printf("A display is required!\n"); + return EXIT_FAILURE; + } + eina_init(); + ecore_init(); + ecore_x_init(NULL); + elm_init(argc, argv); + entrance_client_main(theme); + elm_shutdown(); + ecore_x_shutdown(); + ecore_shutdown(); + eina_shutdown(); + return EXIT_SUCCESS; +} diff --git a/src/bin/entrance_client.h b/src/bin/entrance_client.h new file mode 100644 index 0000000..16ba07b --- /dev/null +++ b/src/bin/entrance_client.h @@ -0,0 +1,20 @@ +#ifndef ENTRANCE_H_ +#define ENTRANCE_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "entrance_gui.h" +#include "entrance_connect.h" +#include "entrance_client.h" +#include "entrance_gui.h" +#include "../event/entrance_event.h" + +int entrance_client_main(); + +#endif /* ENTRANCE_H_ */ diff --git a/src/bin/entrance_connect.c b/src/bin/entrance_connect.c new file mode 100644 index 0000000..98b0e83 --- /dev/null +++ b/src/bin/entrance_connect.c @@ -0,0 +1,124 @@ +#include +#include "entrance_client.h" + +Ecore_Con_Server *_entrance_connect; +Eina_List *_handlers; + +static Eina_Bool _entrance_connect_add(void *data, int type, void *event); +static Eina_Bool _entrance_connect_del(void *data, int type, void *event); +static Eina_Bool _entrance_connect_data(void *data, int type, void *event); + + + +static Eina_Bool +_entrance_connect_add(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Con_Event_Server_Add *ev; + ev = event; + fprintf(stderr, PACKAGE": client connected\n"); + + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_entrance_connect_del(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Con_Event_Server_Del *ev; + ev = event; + fprintf(stderr, PACKAGE": client disconnected\n"); + _entrance_connect = NULL; + + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_entrance_connect_data(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Con_Event_Server_Data *ev; + Entrance_Event *eev; + ev = event; + + eev = entrance_event_decode(ev->data, ev->size); + if (eev) + { + if (eev->type == ENTRANCE_EVENT_STATUS) + { + if (eev->event.status.granted) + entrance_gui_auth_valid(); + else + entrance_gui_auth_error(); + } + else if (eev->type == ENTRANCE_EVENT_MAXTRIES) + entrance_gui_auth_wait(); + else if (eev->type == ENTRANCE_EVENT_XSESSIONS) + entrance_gui_xsession_set(eev->event.xsessions.xsessions); + else if (eev->type == ENTRANCE_EVENT_USERS) + entrance_gui_users_set(eev->event.users.users); + else if (eev->type == ENTRANCE_EVENT_ACTIONS) + entrance_gui_actions_set(eev->event.actions.actions); + else + fprintf(stderr, PACKAGE": unknow signal\n"); + } + return ECORE_CALLBACK_RENEW; +} + +void +entrance_connect_auth_send(const char *login, const char *password, const char *session) +{ + Entrance_Event eev; + void *data; + int size; + + eev.event.auth.login = login; + eev.event.auth.password = password; + eev.event.auth.session = session; + eev.type = ENTRANCE_EVENT_AUTH; + data = entrance_event_encode(&eev, &size); + ecore_con_server_send(_entrance_connect, data, size); +} + +void +entrance_connect_action_send(int id) +{ + Entrance_Event eev; + void *data; + int size; + + eev.event.action.action = id; + eev.type = ENTRANCE_EVENT_ACTION; + data = entrance_event_encode(&eev, &size); + ecore_con_server_send(_entrance_connect, data, size); +} + +void +entrance_connect_init() +{ + Ecore_Event_Handler *h; + ecore_con_init(); + _entrance_connect = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM, + "entrance", 42, NULL); + if (_entrance_connect) + printf(PACKAGE": client server init ok\n"); + else + printf(PACKAGE": client server init fail\n"); + h = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, + _entrance_connect_add, NULL); + _handlers = eina_list_append(_handlers, h); + h = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, + _entrance_connect_del, NULL); + _handlers = eina_list_append(_handlers, h); + h = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, + _entrance_connect_data, NULL); + _handlers = eina_list_append(_handlers, h); +} + +void +entrance_connect_shutdown() +{ + Ecore_Event_Handler *h; + printf(PACKAGE": client server shutdown\n"); + EINA_LIST_FREE(_handlers, h) + ecore_event_handler_del(h); + ecore_con_shutdown(); +} + diff --git a/src/bin/entrance_connect.h b/src/bin/entrance_connect.h new file mode 100644 index 0000000..2fc5c51 --- /dev/null +++ b/src/bin/entrance_connect.h @@ -0,0 +1,7 @@ +#ifndef ENTRANCE_CONNECT_ +#define ENTRANCE_CONNECT_ +void entrance_connect_init(); +void entrance_connect_auth_send(const char *login, const char *password, const char *session); +void entrance_connect_action_send(int id); +void entrance_connect_shutdown(); +#endif /* ENTRANCE_CONNECT_ */ diff --git a/src/bin/entrance_gui.c b/src/bin/entrance_gui.c new file mode 100644 index 0000000..ade7e3f --- /dev/null +++ b/src/bin/entrance_gui.c @@ -0,0 +1,806 @@ +#include "entrance_client.h" +#include "Ecore_X.h" + +#define ENTRANCE_GUI_GET(edj, name) edje_object_part_external_object_get(elm_layout_edje_get(edj), name) + +typedef struct Entrance_Gui_ Entrance_Gui; +typedef struct Entrance_Screen_ Entrance_Screen; +typedef struct Entrance_Gui_Item_ Entrance_Gui_Item; + +struct Entrance_Gui_ +{ + Eina_List *screens; + Eina_List *xsessions; + Eina_List *users; + Eina_List *actions; + Eina_List *handlers; + Entrance_Xsession *selected_session; + const char *theme; +}; + +struct Entrance_Screen_ +{ + Evas_Object *win; + Evas_Object *bg; + Evas_Object *edj; + Eina_Bool managed:1; +}; + +typedef char *(*EntranceItemLabelGetFunc) (void *data, Evas_Object *obj, const char *part); +typedef Evas_Object *(*EntranceItemIconGetFunc) (void *data, Evas_Object *obj, const char *part); +typedef Eina_Bool (*EntranceItemStateGetFunc) (void *data, Evas_Object *obj, const char *part); +typedef void (*EntranceItemDelFunc) (void *data, Evas_Object *obj); + +struct Entrance_Gui_Item_ +{ + const char *item_style; //maybee need to be provided by theme ? + struct + { + EntranceItemLabelGetFunc text_get; + EntranceItemIconGetFunc content_get; + EntranceItemStateGetFunc state_get; + EntranceItemDelFunc del; + } func; +}; + +static Evas_Object *_entrance_gui_theme_get(Evas_Object *win, const char *group, const char *theme); +static void _entrance_gui_hostname_activated_cb(void *data, Evas_Object *obj, void *event_info); +static void _entrance_gui_password_activated_cb(void *data, Evas_Object *obj, void *event_info); +static void _entrance_gui_shutdown(void *data, Evas_Object *obj, void *event_info); +static void _entrance_gui_focus(void *data, Evas_Object *obj, void *event_info); +static void _entrance_gui_session_update(Entrance_Xsession *xsession); +static void _entrance_gui_users_list_set(Evas_Object *obj, Eina_List *users); +static void _entrance_gui_users_genlist_set(Evas_Object *obj, Eina_List *users); +static void _entrance_gui_users_gengrid_set(Evas_Object *obj, Eina_List *users); +static void _entrance_gui_user_sel_cb(void *data, Evas_Object *obj, void *event_info); +static void _entrance_gui_user_sel(Entrance_User *ou); +static Eina_Bool _entrance_gui_auth_enable(void *data); + +static Eina_Bool _entrance_gui_cb_window_property(void *data, int type, void *event_info); + +static void _entrance_gui_action_clicked_cb(void *data, Evas_Object *obj, void *event_info); +static Entrance_Gui *_gui; +static Ecore_Timer *_gui_login_timeout; + +static Evas_Object * +_entrance_gui_theme_get (Evas_Object *win, const char *group, const char *theme) +{ + Evas_Object *edje = NULL; + + edje = elm_layout_add(win); + if (theme) + { + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), PACKAGE_DATA_DIR"/themes/%s.edj", theme); + if (!elm_layout_file_set(edje, buf, group)) + { + fprintf(stderr, PACKAGE": can't load %s theme fallback to default\n", theme); + elm_layout_file_set(edje, PACKAGE_DATA_DIR"/themes/default.edj", group); + } + } + else + elm_layout_file_set(edje, PACKAGE_DATA_DIR"/themes/default.edj", group); + return edje; +} + +static void +_entrance_gui_hostname_activated_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + char *txt; + Eina_List *l, *ll; + Entrance_Xsession *xsess; + Entrance_User *eu = NULL; + Entrance_Screen *screen; + + txt = elm_entry_markup_to_utf8(elm_entry_entry_get(obj)); + if (!txt || !strcmp(txt, "")) + { + free(txt); + return; + } + EINA_LIST_FOREACH(_gui->users, ll, eu) + if (!strcmp(txt, eu->login)) break; + free(txt); + + if (eu && eu->lsess) + { + EINA_LIST_FOREACH(_gui->xsessions, l, xsess) + { + if (!strcmp(xsess->name, eu->lsess)) + { + _entrance_gui_session_update(xsess); + break; + } + } + } + else if (_gui->xsessions) + _entrance_gui_session_update(_gui->xsessions->data); + elm_object_focus_set(data, EINA_TRUE); + EINA_LIST_FOREACH(_gui->screens, l, screen) + edje_object_signal_emit(elm_layout_edje_get(screen->edj), + "entrance.auth.enable", ""); +} + +static void +_entrance_gui_shutdown(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + elm_exit(); + printf("shutdown cb\n"); +} + +static Eina_Bool +_entrance_gui_cb_window_property(void *data, int type __UNUSED__, void *event_info) +{ + Entrance_Screen *screen; + Ecore_X_Event_Window_Property *ev; + Eina_List *l; + ev = event_info; + screen = data; + if (ev->atom == ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK) + screen->managed = EINA_TRUE; + EINA_LIST_FOREACH(_gui->screens, l, screen) + if (!screen->managed) + return ECORE_CALLBACK_PASS_ON; + elm_exit(); + return ECORE_CALLBACK_PASS_ON; +} + +static void +_entrance_gui_focus(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Eina_List *l; + Entrance_Screen *screen; + + EINA_LIST_FOREACH(_gui->screens, l, screen) + elm_object_focus_set(ENTRANCE_GUI_GET(screen->edj, "hostname"), EINA_TRUE); +} + +static void +_entrance_gui_login_cancel_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *src __UNUSED__) +{ + Evas_Object *o; + Entrance_Screen *screen; + Eina_List *l; + + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + o = ENTRANCE_GUI_GET(screen->edj, "hostname"); + elm_entry_entry_set(o, ""); + elm_object_focus_set(o, EINA_TRUE); + o = ENTRANCE_GUI_GET(screen->edj, "password"); + elm_entry_entry_set(o, ""); + edje_object_signal_emit(elm_layout_edje_get(screen->edj), + "entrance.auth.disable", ""); + } +} + +static Eina_Bool +_entrance_gui_login_timeout(void *data) +{ + Evas_Object *popup, *o; + Entrance_Screen *screen; + Eina_List *l; + + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + popup = elm_popup_add(screen->win); + evas_object_size_hint_weight_set(popup, + EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_text_set(popup, "Something wrong hapened ..."); + + o = elm_button_add(popup); + elm_object_text_set(o, "Close"); + elm_object_part_content_set(popup, "button1", o); + evas_object_smart_callback_add(o, "clicked", + _entrance_gui_shutdown, NULL); + evas_object_show(popup); + } + _gui_login_timeout = NULL; + + return ECORE_CALLBACK_CANCEL; +} + +static void +_entrance_gui_login(Entrance_Screen *screen) +{ + Eina_List *l; + char *h, *s; + h = entrance_gui_user_get(screen); + s = entrance_gui_password_get(screen); + if (h && s) + { + if (strcmp(h, "") && strcmp(s, "")) + { + if (_gui->selected_session) + entrance_connect_auth_send(h, s, _gui->selected_session->name); + else + entrance_connect_auth_send(h, s, NULL); + _gui_login_timeout = ecore_timer_add(10.0, + _entrance_gui_login_timeout, + screen); + } + } + free(h); + free(s); + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + elm_object_focus_set(ENTRANCE_GUI_GET(screen->edj, "password"), EINA_TRUE); + edje_object_signal_emit(elm_layout_edje_get(screen->edj), + "entrance.auth.enable", ""); + } +} + +static void +_entrance_gui_login_request_cb(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *src __UNUSED__) +{ + _entrance_gui_login(data); +} + +static void +_entrance_gui_password_activated_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + _entrance_gui_login(data); +} + +static void +_entrance_gui_xsessions_clicked_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) +{ + Evas_Object *icon; + Eina_List *l; + Entrance_Screen *screen; + + _gui->selected_session = data; + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + elm_object_text_set(obj, _gui->selected_session->name); + icon = elm_icon_add(screen->win); + elm_image_file_set(icon, _gui->selected_session->icon, NULL); + elm_object_content_set(obj, icon); + evas_object_show(icon); + } +} + +static void +_entrance_gui_action_clicked_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Entrance_Action *ea; + ea = data; + if (ea) entrance_connect_action_send(ea->id); +} + + + +static void +_entrance_gui_callback_add(Entrance_Screen *screen) +{ + Evas_Object *host, *pwd; + Evas_Object *edj; + + evas_object_smart_callback_add(screen->win, "delete,request", + _entrance_gui_shutdown, NULL); + evas_object_smart_callback_add(screen->win, "focus,in", + _entrance_gui_focus, NULL); + + edj = elm_layout_edje_get(screen->edj); + host = ENTRANCE_GUI_GET(screen->edj, "hostname"); + pwd = ENTRANCE_GUI_GET(screen->edj, "password"); + evas_object_smart_callback_add(host, "activated", + _entrance_gui_hostname_activated_cb, pwd); + evas_object_smart_callback_add(pwd, "activated", + _entrance_gui_password_activated_cb, screen); + edje_object_signal_callback_add(edj, "entrance.auth.cancel", "", + _entrance_gui_login_cancel_cb, NULL); + edje_object_signal_callback_add(edj, "entrance.auth.request", "", + _entrance_gui_login_request_cb, screen); + elm_entry_single_line_set(host, EINA_TRUE); + elm_entry_single_line_set(pwd, EINA_TRUE); +} + +static void +_entrance_gui_session_update(Entrance_Xsession *xsession) +{ + Evas_Object *o, *icon; + Eina_List *l; + Entrance_Screen *screen; + + if (!xsession) return; + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + o = ENTRANCE_GUI_GET(screen->edj, "xsessions"); + _gui->selected_session = xsession; + elm_object_text_set(o, _gui->selected_session->name); + icon = elm_icon_add(screen->win); + elm_image_file_set(icon, _gui->selected_session->icon, NULL); + elm_object_content_set(o, icon); + } +} + +static void +_entrance_gui_sessions_populate() +{ + Evas_Object *o; + + Entrance_Xsession *xsession; + Eina_List *l, *ll; + Entrance_Screen *screen; + + EINA_LIST_FOREACH(_gui->screens, ll, screen) + { + o = ENTRANCE_GUI_GET(screen->edj, "xsessions"); + + EINA_LIST_FOREACH(_gui->xsessions, l, xsession) + { + elm_hoversel_item_add(o, xsession->name, xsession->icon, + ELM_ICON_FILE, + _entrance_gui_xsessions_clicked_cb, xsession); + } + edje_object_signal_emit(elm_layout_edje_get(screen->edj), + "entrance.xsession.enabled", ""); + } + if (_gui->xsessions) + _entrance_gui_session_update(_gui->xsessions->data); +} + +static void +_entrance_gui_actions_populate() +{ + Evas_Object *o; + + Entrance_Action *action; + Eina_List *l, *ll; + Entrance_Screen *screen; + + EINA_LIST_FOREACH(_gui->screens, ll, screen) + { + o = ENTRANCE_GUI_GET(screen->edj, "actions"); + EINA_LIST_FOREACH(_gui->actions, l, action) + { + elm_hoversel_item_add(o, action->label, NULL, + ELM_ICON_FILE, + _entrance_gui_action_clicked_cb, action); + } + edje_object_signal_emit(elm_layout_edje_get(screen->edj), + "entrance.action.enabled", ""); + } +} + +static Eina_Bool +_entrance_gui_auth_enable(void *data __UNUSED__) +{ + Evas_Object *o; + Eina_List *l; + Entrance_Screen *screen; + + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + o = ENTRANCE_GUI_GET(screen->edj, "hostname"); + elm_object_disabled_set(o, EINA_FALSE); + o = ENTRANCE_GUI_GET(screen->edj, "password"); + elm_object_disabled_set(o, EINA_FALSE); + } + return ECORE_CALLBACK_CANCEL; +} + + +void +entrance_gui_xsession_set(Eina_List *xsessions) +{ + if (!xsessions) return; + _gui->xsessions = xsessions; + _entrance_gui_sessions_populate(); +} + +void +entrance_gui_actions_set(Eina_List *actions) +{ + if (!actions) return; + fprintf(stderr, PACKAGE": Action set\n"); + _gui->actions = actions; + _entrance_gui_actions_populate(); +} + +int +entrance_gui_init(const char *theme) +{ + + Ecore_X_Window xw; + Entrance_Screen *screen; + int ii, i; + int x, y, w, h; + + fprintf(stderr, PACKAGE": client Gui init\n"); + _gui = calloc(1, sizeof(Entrance_Gui)); + if (!_gui) + { + fprintf(stderr, PACKAGE": client Not Enough memory\n"); + return 1; + } + +#ifdef XNEST_DEBUG + char *tmp = getenv("DISPLAY"); + if (tmp && *tmp) + { + fprintf(stderr, PACKAGE": client Using display name %s", tmp); + } +#endif + + + i = ecore_x_xinerama_screen_count_get(); + if (i < 1) i = 1; + for(ii = 0; ii < i; ++ii) + { + screen = calloc(1, sizeof(Entrance_Screen)); + if (!screen) return 1; + + _gui->screens = eina_list_append(_gui->screens, screen); + ecore_x_xinerama_screen_geometry_get(ii, &x, &y, &w, &h); + screen->win = elm_win_add(NULL, "main", ELM_WIN_BASIC); + elm_win_fullscreen_set(screen->win, EINA_TRUE); + elm_win_title_set(screen->win, PACKAGE); + + _gui->theme = eina_stringshare_add(theme); + screen->edj = _entrance_gui_theme_get(screen->win, "entrance", theme); + + if (!screen->edj) + { + fprintf(stderr, PACKAGE": client Tut Tut Tut no theme\n"); + return 2; + } + evas_object_size_hint_weight_set(screen->edj, + EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + elm_win_resize_object_add(screen->win, screen->edj); + _entrance_gui_callback_add(screen); + evas_object_show(screen->edj); + + xw = elm_win_xwindow_get(screen->win); + evas_object_resize(screen->win, w, h); + ecore_x_window_move(xw, x, y); + evas_object_show(screen->win); + _gui->handlers = + eina_list_append(_gui->handlers, + ecore_event_handler_add( + ECORE_X_EVENT_WINDOW_PROPERTY, + _entrance_gui_cb_window_property, + screen)); + } + if (_gui->screens) + { + /* tricky situation. we are not normally running with a wm and thus + * have to set focus to our window so things work right */ + screen = _gui->screens->data; + ecore_evas_focus_set + (ecore_evas_ecore_evas_get(evas_object_evas_get(screen->win)), 1); + } + return 0; +} + +void +entrance_gui_shutdown() +{ + Entrance_Xsession *xsession; + Entrance_Screen *screen; + Ecore_Event_Handler *h; + fprintf(stderr, PACKAGE": Gui shutdown\n"); + EINA_LIST_FREE(_gui->screens, screen) + { + evas_object_del(screen->win); + free(screen); + } + eina_stringshare_del(_gui->theme); + EINA_LIST_FREE(_gui->xsessions, xsession) + { + eina_stringshare_del(xsession->name); + eina_stringshare_del(xsession->command); + if (xsession->icon) eina_stringshare_del(xsession->icon); + } + EINA_LIST_FREE(_gui->handlers, h) + ecore_event_handler_del(h); + if (_gui) free(_gui); +} + +char * +entrance_gui_user_get(Entrance_Screen *screen) +{ + Evas_Object *o; + o = ENTRANCE_GUI_GET(screen->edj, "hostname"); + if (o) return elm_entry_markup_to_utf8(elm_entry_entry_get(o)); + return NULL; +} + +char * +entrance_gui_password_get(Entrance_Screen *screen) +{ + Evas_Object *o; + o = ENTRANCE_GUI_GET(screen->edj, "password"); + if (o) return elm_entry_markup_to_utf8(elm_entry_entry_get(o)); + return NULL; +} + +void +entrance_gui_auth_error() +{ + Evas_Object *o; + Eina_List *l; + Entrance_Screen *screen; + + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + o = ENTRANCE_GUI_GET(screen->edj, "password"); + elm_entry_entry_set(o, ""); + edje_object_signal_emit(elm_layout_edje_get(screen->edj), + "entrance.auth.error", ""); + } +} + +void +entrance_gui_auth_wait() +{ + Evas_Object *o; + Eina_List *l; + Entrance_Screen *screen; + + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + o = ENTRANCE_GUI_GET(screen->edj, "hostname"); + elm_entry_entry_set(o, ""); + elm_object_disabled_set(o, EINA_TRUE); + o = ENTRANCE_GUI_GET(screen->edj, "password"); + elm_entry_entry_set(o, ""); + elm_object_disabled_set(o, EINA_TRUE); + } + ecore_timer_add(5.0, _entrance_gui_auth_enable, NULL); +} + + + + +void +entrance_gui_auth_valid() +{ + Eina_List *l; + Entrance_Screen *screen; + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + edje_object_signal_emit(elm_layout_edje_get(screen->edj), + "entrance.auth.valid", ""); + } +} +///////////////// USER //////////////////////////// +void +entrance_gui_users_set(Eina_List *users) +{ + Evas_Object *ol; + const char *type; + Entrance_Screen *screen; + Eina_List *l; + + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + ol = ENTRANCE_GUI_GET(screen->edj, "entrance_users"); + if ((ol) && ((type = elm_object_widget_type_get(ol)))) + { + if (!strcmp(type, "list")) + _entrance_gui_users_list_set(ol, users); + else if (!strcmp(type, "genlist")) + _entrance_gui_users_genlist_set(ol, users); + else if (!strcmp(type, "gengrid")) + _entrance_gui_users_gengrid_set(ol, users); + + edje_object_signal_emit(elm_layout_edje_get(screen->edj), + "entrance.users.enabled", ""); + _gui->users = users; + } + } +} + + + +static void +_entrance_gui_user_sel(Entrance_User *eu) +{ + Evas_Object *o; + Entrance_Xsession *xsess; + Eina_List *l; + Entrance_Screen *screen; + + EINA_LIST_FOREACH(_gui->screens, l, screen) + { + o = ENTRANCE_GUI_GET(screen->edj, "hostname"); + elm_entry_entry_set(o, eu->login); + elm_object_focus_set(ENTRANCE_GUI_GET(screen->edj, "password"), EINA_TRUE); + edje_object_signal_emit(elm_layout_edje_get(screen->edj), + "entrance.auth.enable", ""); + } + if (eu->lsess) + { + EINA_LIST_FOREACH(_gui->xsessions, l, xsess) + { + if (!strcmp(xsess->name, eu->lsess)) + { + _entrance_gui_session_update(xsess); + break; + } + } + } + else if (_gui->xsessions) + _entrance_gui_session_update(_gui->xsessions->data); +} + +static void +_entrance_gui_user_sel_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + _entrance_gui_user_sel(data); +} + +static char * +_entrance_gui_user_text_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__) +{ + Entrance_User *eu; + eu = data; + return strdup(eu->login); +} + +static Evas_Object * +_entrance_gui_user_content_get(void *data __UNUSED__, Evas_Object *obj, const char *part) +{ + Evas_Object *ic = NULL; + Entrance_User *eu; + eu = data; + + if (eu && !strcmp(part, "elm.swallow.icon")) + { + if (eu->image) + { + ic = elm_icon_add(obj); + elm_image_file_set(ic, eu->image, "entrance/user/icon"); + } + else + { + ic = _entrance_gui_theme_get(obj, "entrance/user/default", + _gui->theme); + } + evas_object_size_hint_weight_set(ic, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(ic); + } + return ic; +} + +static Eina_Bool +_entrance_gui_user_state_get(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *part __UNUSED__) +{ + return EINA_FALSE; +} + +static void +_entrance_gui_user_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__) +{ +} + +///////////////// LIST /////////////////////////////// +static void +_entrance_gui_users_list_set(Evas_Object *obj, Eina_List *users) +{ + Entrance_User *eu; + Eina_List *l; + + EINA_LIST_FOREACH(users, l, eu) + elm_list_item_append(obj, eu->login, NULL, NULL, + _entrance_gui_user_sel_cb, eu); + elm_list_go(obj); +} + +///////////////// USER GENLIST ///////////////////////////// +static Elm_Genlist_Item_Class _entrance_glc; +static void +_entrance_gui_users_genlist_set(Evas_Object *obj, Eina_List *users) +{ + Entrance_User *eu; + Eina_List *l; + + _entrance_glc.item_style = "default"; + _entrance_glc.func.text_get = _entrance_gui_user_text_get; + _entrance_glc.func.content_get = _entrance_gui_user_content_get; + _entrance_glc.func.state_get = _entrance_gui_user_state_get; + _entrance_glc.func.del = _entrance_gui_user_del; + + + EINA_LIST_FOREACH(users, l, eu) + elm_genlist_item_append(obj, &_entrance_glc, + eu, NULL, ELM_GENLIST_ITEM_NONE, + _entrance_gui_user_sel_cb, eu); +} + +///////////////// USER GENGRID ///////////////////////////// +static Elm_Gengrid_Item_Class _entrance_ggc; +static void +_entrance_gui_users_gengrid_set(Evas_Object *obj, Eina_List *users) +{ + Entrance_User *eu; + Eina_List *l; + + _entrance_ggc.item_style = "default"; + _entrance_ggc.func.text_get = _entrance_gui_user_text_get; + _entrance_ggc.func.content_get = _entrance_gui_user_content_get; + _entrance_ggc.func.state_get = _entrance_gui_user_state_get; + _entrance_ggc.func.del = _entrance_gui_user_del; + + evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + EINA_LIST_FOREACH(users, l, eu) + elm_gengrid_item_append(obj, &_entrance_ggc, + eu, _entrance_gui_user_sel_cb, eu); + evas_object_show(obj); + +} + + + +//////////////////////////////////////////////////////////////////////////////// +///////////////// LIST /////////////////////////////// +static void +_entrance_gui_list_fill(Evas_Object *obj, Entrance_Gui_Item egi, Eina_List *users, Evas_Smart_Cb func, void *data) +{ + Entrance_User *eu; + Eina_List *l; + + EINA_LIST_FOREACH(users, l, eu) + elm_list_item_append(obj, egi.func.text_get(eu, NULL, NULL), NULL, NULL, + func, data); + elm_list_go(obj); +} + +///////////////// GENLIST ///////////////////////////// +static void +_entrance_gui_genlist_fill(Evas_Object *obj, Entrance_Gui_Item egi, Eina_List *users, Evas_Smart_Cb func, void *data) +{ + Entrance_User *eu; + Eina_List *l; + Elm_Genlist_Item_Class glc; + + glc.item_style = egi.item_style; + glc.func.text_get = egi.func.text_get; + glc.func.content_get = egi.func.content_get; + glc.func.state_get = egi.func.state_get; + glc.func.del = egi.func.del; + + + EINA_LIST_FOREACH(users, l, eu) + elm_genlist_item_append(obj, &glc, + eu, NULL, ELM_GENLIST_ITEM_NONE, + func, data); +} + +///////////////// GENGRID ///////////////////////////// +static void +_entrance_gui_gengrid_fill(Evas_Object *obj, Entrance_Gui_Item egi, Eina_List *users, Evas_Smart_Cb func, void *data) +{ + Entrance_User *eu; + Eina_List *l; + Elm_Gengrid_Item_Class ggc; + + ggc.item_style = egi.item_style; + ggc.func.text_get = egi.func.text_get; + ggc.func.content_get = egi.func.content_get; + ggc.func.state_get = egi.func.state_get; + ggc.func.del = egi.func.del; + + EINA_LIST_FOREACH(users, l, eu) + elm_gengrid_item_append(obj, &ggc, + eu, func, data); +} + +static void +_entrance_gui_cont_fill(Evas_Object *obj, Entrance_Gui_Item egi, Eina_List *users, Evas_Smart_Cb func, void *data) +{ + const char *type; + if ((type = elm_object_widget_type_get(obj))) + { + if (!strcmp(type, "list")) + _entrance_gui_list_fill(obj, egi, users, func, data); + else if (!strcmp(type, "genlist")) + _entrance_gui_genlist_fill(obj, egi, users, func, data); + else if (!strcmp(type, "gengrid")) + _entrance_gui_gengrid_fill(obj, egi, users, func, data); + } +} + diff --git a/src/bin/entrance_gui.h b/src/bin/entrance_gui.h new file mode 100644 index 0000000..f4e5d6a --- /dev/null +++ b/src/bin/entrance_gui.h @@ -0,0 +1,17 @@ +#ifndef ENTRANCE_GUI_H_ +#define ENTRANCE_GUI_H_ + +int entrance_gui_init(const char *theme); +void entrance_gui_run(); +void entrance_gui_shutdown(); +char *entrance_gui_user_get(); +char *entrance_gui_password_get(); +void entrance_gui_auth_error(); +void entrance_gui_auth_valid(); +void entrance_gui_auth_wait(); +char *entrance_gui_login_command_get(); +void entrance_gui_xsession_set(Eina_List *xsessions); +void entrance_gui_users_set(Eina_List *users); +void entrance_gui_actions_set(Eina_List *actions); + +#endif /* ENTRANCE_GUI_H_ */ diff --git a/src/bin/entrance_test.c b/src/bin/entrance_test.c new file mode 100644 index 0000000..880360e --- /dev/null +++ b/src/bin/entrance_test.c @@ -0,0 +1,60 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +int elm_main (int argc, char **argv); + +static Evas_Object * +_theme_get(Evas_Object *win, const char *group) +{ + char buffer[PATH_MAX]; + Evas_Object *edje = NULL; + + edje = elm_layout_add(win); + snprintf(buffer, sizeof(buffer), "%s/themes/default.edj", PACKAGE_DATA_DIR); + elm_layout_file_set(edje, buffer, group); + return edje; +} + +static void +_signal(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *sig, const char *src) +{ + printf("Event: %s - %s \n", sig, src); +} + + +static void +_shutdown(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + printf("Quit\n"); + elm_exit(); +} + + +int +elm_main (int argc __UNUSED__, char **argv __UNUSED__) +{ + Evas_Object *o, *win; + win = elm_win_add(NULL, "theme_test", ELM_WIN_BASIC); + elm_win_title_set(win, PACKAGE); + evas_object_smart_callback_add(win, "delete,request", + _shutdown, NULL); + o = _theme_get(win, "entrance"); + evas_object_size_hint_weight_set(o, + EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + edje_object_signal_callback_add(elm_layout_edje_get(o), + "*", "*", + _signal, NULL); + elm_win_resize_object_add(win, o); + evas_object_show(o); + evas_object_resize(win, 640, 480); + evas_object_show(win); + elm_run(); + elm_shutdown(); + return 0; +} + +ELM_MAIN() diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am new file mode 100644 index 0000000..91ace25 --- /dev/null +++ b/src/daemon/Makefile.am @@ -0,0 +1,67 @@ + +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir)/src/daemon \ +-I$(top_builddir)/src/daemon \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +-DSYSTEM_CONFIG_DIR=\"$(sysconfdir)\" \ +-DPACKAGE_BIN_DIR=\"$(libdir)/$(PACKAGE)\" \ +@ENTRANCE_CFLAGS@ + +if HAVE_CONSOLEKIT +AM_CPPFLAGS += @ENTRANCE_CK_CFLAGS@ +endif + +sbin_PROGRAMS = entrance + +internal_bindir=$(libdir)/entrance +internal_bin_PROGRAMS = entrance_wait + +if HAVE_CONSOLEKIT +internal_bin_PROGRAMS += entrance_ck_launch +endif + +entrance_SOURCES = \ +entrance_config.h \ +entrance_config.c \ +entrance_session.h \ +entrance_session.c \ +entrance_xserver.h \ +entrance_xserver.c \ +../event/entrance_event.c \ +../event/entrance_event.h \ +entrance_server.h \ +entrance_server.c \ +entrance_history.h \ +entrance_history.c \ +entrance_action.h \ +entrance_action.c \ +entrance.h \ +entrance.c + + +entrance_LDFLAGS = +entrance_LDADD = @ENTRANCE_LIBS@ -lrt + +entrance_wait_SOURCES = \ +entrance_wait.c + +entrance_wait_LDFLAGS = +entrance_wait_LDADD = + +if HAVE_PAM +entrance_SOURCES += entrance_pam.h entrance_pam.c +entrance_LDADD += -lpam +else +entrance_LDADD += -lcrypt +endif + +if HAVE_CONSOLEKIT +entrance_ck_launch_SOURCES = \ +entrance_ck_launch.c + +entrance_ck_launch_LDFLAGS = +entrance_ck_launch_LDADD = @ENTRANCE_CK_LIBS@ +endif + diff --git a/src/daemon/entrance.c b/src/daemon/entrance.c new file mode 100644 index 0000000..fea856a --- /dev/null +++ b/src/daemon/entrance.c @@ -0,0 +1,378 @@ +#include "entrance.h" +#include +#include +#include +#include "Ecore_Getopt.h" +#include + +#define ENTRANCE_DISPLAY ":0.0" + + +static Eina_Bool _open_log(); +static int _entrance_main(const char *dname); +static void _remove_lock(); +static void _signal_cb(); +static void _signal_log(); +static Eina_Bool _entrance_client_del(void *data, int type, void *event); + +static Eina_Bool _testing = 0; +static Eina_Bool _xephyr = 0; +static Ecore_Exe *_entrance_client = NULL; + + + +static void +_signal_cb(int sig) +{ + fprintf(stderr, PACKAGE": signal %d received\n", sig); + //FIXME if I don't have main loop at this time ? + if (_entrance_client) ecore_exe_terminate(_entrance_client); + /* + entrance_session_shutdown(); + entrance_xserver_shutdown(); + exit(1); + */ +} + +static void +_signal_log(int sig) +{ + fprintf(stderr, PACKAGE": signal %d received reopen the log file\n", sig); + entrance_close_log(); + _open_log(); +} + +static Eina_Bool +_get_lock() +{ + FILE *f; + char buf[128]; + int my_pid; + + my_pid = getpid(); + f = fopen(entrance_config->lockfile, "r"); + if (!f) + { + /* No lockfile, so create one */ + f = fopen(entrance_config->lockfile, "w"); + if (!f) + { + fprintf(stderr, PACKAGE": Couldn't create lockfile %s!\n", + entrance_config->lockfile); + return (EINA_FALSE); + } + snprintf(buf, sizeof(buf), "%d\n", my_pid); + if (!fwrite(buf, strlen(buf), 1, f)) + { + fclose(f); + fprintf(stderr, PACKAGE": Couldn't write the lockfile\n"); + return EINA_FALSE; + } + fclose(f); + } + else + { + int pid = 0; + /* read the lockfile */ + if (fgets(buf, sizeof(buf), f)) + pid = atoi(buf); + fclose(f); + if (pid == my_pid) + return EINA_TRUE; + fprintf(stderr, "A lock file are present another instance are present ?\n"); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static void +_update_lock() +{ + FILE *f; + char buf[128]; + f = fopen(entrance_config->lockfile, "w"); + snprintf(buf, sizeof(buf), "%d\n", getpid()); + if (!fwrite(buf, strlen(buf), 1, f)) + fprintf(stderr, PACKAGE": Coudn't update lockfile\n"); + fclose(f); +} + +static void +_remove_lock() +{ + remove(entrance_config->lockfile); +} + +static Eina_Bool +_open_log() +{ + FILE *elog; + if (_testing) return EINA_TRUE; + elog = fopen(entrance_config->logfile, "a"); + if (!elog) + { + fprintf(stderr, PACKAGE": could not open logfile %s!!!\n", + entrance_config->logfile); + return EINA_FALSE; + } + fclose(elog); + if (!freopen(entrance_config->logfile, "a", stdout)) + fprintf(stderr, PACKAGE": Error on reopen stdout\n"); + setvbuf(stdout, NULL, _IOLBF, BUFSIZ); + if (!freopen(entrance_config->logfile, "a", stderr)) + fprintf(stderr, PACKAGE": Error on reopen stderr\n"); + setvbuf(stderr, NULL, _IONBF, BUFSIZ); + return EINA_TRUE; +} + +void +entrance_close_log() +{ + if (!_testing) + { + fclose(stderr); + fclose(stdout); + } +} + +static void +_entrance_wait() +{ + execl(PACKAGE_BIN_DIR"/entrance_wait", "/usr/sbin/entrance", NULL); + fprintf(stderr, PACKAGE": HUM HUM HUM ...\n\n\n"); +} + +static int +_entrance_main(const char *dname) +{ + if (!entrance_config->autologin) + { + if (!_entrance_client) + { + char buf[PATH_MAX]; + ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + _entrance_client_del, NULL); + fprintf(stderr, PACKAGE": Exec entrance_client\n"); + snprintf(buf, sizeof(buf), + PACKAGE_BIN_DIR"/entrance_client -d %s -t %s", + dname, entrance_config->theme); + _entrance_client = ecore_exe_run(buf, NULL); + } + } + else + ecore_main_loop_quit(); + return 0; +} + +static Eina_Bool +_entrance_client_del(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Exe_Event_Del *ev; + + ev = event; + if (ev->exe != _entrance_client) + return ECORE_CALLBACK_PASS_ON; + ecore_main_loop_quit(); + _entrance_client = NULL; + fprintf(stderr, PACKAGE": client have terminated\n"); + + return ECORE_CALLBACK_DONE; +} + + +static const Ecore_Getopt options = +{ + PACKAGE, + "%prog [options]", + VERSION, + "(C) 2011 Enlightenment, see AUTHORS", + "GPL, see COPYING", + "Entrance is a login manager, written using core efl libraries", + EINA_TRUE, + { + ECORE_GETOPT_STORE_TRUE('n', "nodaemon", "Don't daemonize."), + ECORE_GETOPT_STORE_TRUE('t', "test", "run in test mode."), + ECORE_GETOPT_STORE_TRUE('x', "xephyr", "run in test mode and use Xephyr."), + ECORE_GETOPT_HELP ('h', "help"), + ECORE_GETOPT_VERSION('V', "version"), + ECORE_GETOPT_COPYRIGHT('R', "copyright"), + ECORE_GETOPT_LICENSE('L', "license"), + ECORE_GETOPT_SENTINEL + } +}; + +int +main (int argc, char ** argv) +{ + int args; + int pid; + char *dname = strdup(ENTRANCE_DISPLAY); + char *entrance_user = NULL; + unsigned char nodaemon = 0; + unsigned char quit_option = 0; + Ecore_Getopt_Value values[] = + { + ECORE_GETOPT_VALUE_BOOL(nodaemon), + ECORE_GETOPT_VALUE_BOOL(_testing), + ECORE_GETOPT_VALUE_BOOL(_xephyr), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_NONE + }; + + args = ecore_getopt_parse(&options, values, argc, argv); + if (args < 0) + { + fprintf(stderr, PACKAGE": ERROR: could not parse options.\n"); + return -1; + } + + if (quit_option) + return 0; + + if(getuid() != 0 && !_testing) + { + fprintf(stderr, "Only root can run this program\n"); + return 1; + } + + if (_testing) + nodaemon = EINA_TRUE; + + eet_init(); + entrance_config_init(); + if (!_testing && !_get_lock()) + { + exit(1); + } + + if (!nodaemon && entrance_config->daemonize) + { + if (daemon(0, 1) == -1) + { + fprintf(stderr, PACKAGE": Error on daemonize !"); + quit_option = EINA_TRUE; + } + _update_lock(); + int fd; + if ((fd = open("/dev/null", O_RDONLY))) + { + dup2(fd, 0); + close(fd); + } + } + + if (!_open_log()) + { + fprintf(stderr, PACKAGE": Can't open log file !!!!\n"); + quit_option = EINA_TRUE; + } + + if (quit_option) + { + entrance_config_shutdown(); + entrance_close_log(); + exit(1); + } + + entrance_user = getenv("ENTRANCE_USER"); +#ifdef HAVE_PAM + entrance_pam_init(PACKAGE, dname, entrance_user); +#endif + if (entrance_user) + { + char *quit; + entrance_session_end(entrance_user); + sleep(2); + entrance_xserver_end(); + quit = getenv("ENTRANCE_QUIT"); + if (quit) + { + entrance_history_init(); + unsetenv("ENTRANCE_QUIT"); + _remove_lock(); + entrance_config_shutdown(); + fprintf(stderr, PACKAGE": Good bye\n"); + exit(0); + } +// entrance_history_autolog(); + entrance_history_shutdown(); + exit(1); + } + fprintf(stderr, "\n"PACKAGE": Welcome\n"); + ecore_init(); + /* Initialise event handler */ + + signal(SIGQUIT, _signal_cb); + signal(SIGTERM, _signal_cb); + signal(SIGKILL, _signal_cb); + signal(SIGINT, _signal_cb); + signal(SIGHUP, _signal_cb); + signal(SIGPIPE, _signal_cb); + signal(SIGALRM, _signal_cb); + signal(SIGUSR2, _signal_log); + + fprintf(stderr, PACKAGE": session init\n"); + entrance_session_init(entrance_config->command.xauth_file); + fprintf(stderr, PACKAGE": xserver init\n"); + pid = entrance_xserver_init(_entrance_main, dname); + + entrance_history_init(); + if (entrance_config->autologin && !entrance_user) + { + xcb_connection_t *disp = NULL; + disp = xcb_connect(dname, NULL); + ecore_main_loop_begin(); +#ifdef HAVE_PAM + entrance_pam_item_set(ENTRANCE_PAM_ITEM_USER, entrance_config->userlogin); +#endif + entrance_session_login(entrance_config->command.session_login, EINA_FALSE); + sleep(30); + xcb_disconnect(disp); + } + else + { + fprintf(stderr, PACKAGE": action init\n"); + entrance_action_init(); + fprintf(stderr, PACKAGE": server init\n"); + entrance_server_init(); + fprintf(stderr, PACKAGE": starting main loop\n"); + ecore_main_loop_begin(); + fprintf(stderr, PACKAGE": main loop end\n"); + entrance_server_shutdown(); + fprintf(stderr, PACKAGE": server shutdown\n"); + entrance_action_shutdown(); + fprintf(stderr, PACKAGE": action shutdown\n"); + } + entrance_history_shutdown(); + entrance_xserver_shutdown(); + fprintf(stderr, PACKAGE": xserver shutdown\n"); +#ifdef HAVE_PAM + entrance_pam_shutdown(); + fprintf(stderr, PACKAGE": pam shutdown\n"); +#endif + ecore_shutdown(); + entrance_config_shutdown(); + fprintf(stderr, PACKAGE": config shutdown\n"); + entrance_session_shutdown(); + fprintf(stderr, PACKAGE": session shutdown\n"); + eet_shutdown(); + free(dname); + if (entrance_session_logged_get()) + { + fprintf(stderr, PACKAGE": close log\n"); + entrance_close_log(); + fprintf(stderr, PACKAGE": wait session \n"); + _entrance_wait(); + } + fprintf(stderr, PACKAGE": ending xserver\n"); + kill(pid, SIGTERM); + entrance_xserver_end(); + fprintf(stderr, PACKAGE": close log\n"); + entrance_close_log(); + return 0; +} + diff --git a/src/daemon/entrance.h b/src/daemon/entrance.h new file mode 100644 index 0000000..76fbe40 --- /dev/null +++ b/src/daemon/entrance.h @@ -0,0 +1,28 @@ +#ifndef ENTRANCE_H_ +#define ENTRANCE_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include + +#include "entrance_session.h" +#ifdef HAVE_PAM +#include "entrance_pam.h" +#endif +#include "entrance_config.h" +#include "entrance_xserver.h" +#include "entrance_server.h" +#include "entrance_history.h" +#include "entrance_action.h" +#include "../event/entrance_event.h" + +void entrance_close_log(); + +#endif /* ENTRANCE_H_ */ diff --git a/src/daemon/entrance_action.c b/src/daemon/entrance_action.c new file mode 100644 index 0000000..dc16d26 --- /dev/null +++ b/src/daemon/entrance_action.c @@ -0,0 +1,259 @@ +#include "entrance.h" + +typedef void (*Entrance_Action_Cb)(void *data); + +static void _entrance_action_shutdown(void *data); +static void _entrance_action_reboot(void *data); +static void _entrance_action_suspend(void *data); +static Eina_Bool _entrance_action_exe_event_del_cb(void *data, int type, void *event); +#ifdef HAVE_GRUB2 +#define GRUB2_FILE "/boot/grub/grub.cfg" + +static void _entrance_action_grub2_get(void); +#endif + +static Eina_List *_entrance_actions = NULL; + +typedef struct Entrance_Action_Data__ +{ + int id; + const char *label; + Entrance_Action_Cb func; + void *data; +} Entrance_Action_Data; + +static Ecore_Exe *_action_exe = NULL; +static Ecore_Event_Handler *_handle = NULL; + +static Entrance_Action_Data * +_entrance_action_add(const char *label, Entrance_Action_Cb func, void *data) +{ + Entrance_Action_Data *ead; + ead = calloc(1, sizeof(Entrance_Action_Data)); + ead->label = eina_stringshare_add(label); + ead->func = func; + ead->data = data; + ead->id = _entrance_actions ? (eina_list_count(_entrance_actions)) : 0; + _handle = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + _entrance_action_exe_event_del_cb, NULL); + return ead; +} + + +void +entrance_action_init(void) +{ + _entrance_actions = eina_list_append(_entrance_actions, + _entrance_action_add("Shutdown", _entrance_action_shutdown, NULL)); + _entrance_actions = eina_list_append(_entrance_actions, + _entrance_action_add("Reboot", _entrance_action_reboot, NULL)); + _entrance_actions = eina_list_append(_entrance_actions, + _entrance_action_add("Suspend", _entrance_action_suspend, NULL)); +#ifdef HAVE_GRUB2 + _entrance_action_grub2_get(); +#endif +} + +Eina_List * +entrance_action_get(void) +{ + Entrance_Action_Data *ead; + Entrance_Action *ea; + Eina_List *l, *ret = NULL; + + EINA_LIST_FOREACH(_entrance_actions, l, ead) + { + ea = calloc(1, sizeof(Entrance_Action)); + ea->label = eina_stringshare_add(ead->label); + ea->id = ead->id; + ret = eina_list_append(ret, ea); + } + return ret; +} + +void +entrance_action_shutdown(void) +{ + Entrance_Action_Data *ead; + EINA_LIST_FREE(_entrance_actions, ead) + { + eina_stringshare_del(ead->label); + free(ead); + } +} + + +void +entrance_action_run(int action) +{ + Entrance_Action_Data *ead; + + ead = eina_list_nth(_entrance_actions, action); + if (ead) + ead->func(ead->data); +} + +static void +_entrance_action_suspend(void *data __UNUSED__) +{ + _action_exe = NULL; + ecore_exe_run(entrance_config->command.suspend, NULL); +} + +static void +_entrance_action_shutdown(void *data __UNUSED__) +{ + _action_exe = ecore_exe_run(entrance_config->command.shutdown, NULL); +} + +static void +_entrance_action_reboot(void *data __UNUSED__) +{ + _action_exe = ecore_exe_run(entrance_config->command.reboot, NULL); +} + +static Eina_Bool +_entrance_action_exe_event_del_cb(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Exe_Event_Del *ev; + Eina_Bool ret = ECORE_CALLBACK_PASS_ON; + ev = event; + if (ev->exe == _action_exe) + { + ecore_main_loop_quit(); + ret = ECORE_CALLBACK_DONE; + } + return ret; +} + +/* grub2 action */ +#ifdef HAVE_GRUB2 +static void +_entrance_action_grub2(void *data) +{ + intptr_t i = 0; + char buf[PATH_MAX]; + i = (intptr_t)data; + + snprintf(buf, sizeof(buf), + "grub-reboot %ld && %s", i, entrance_config->command.reboot); + _action_exe = ecore_exe_run(buf, NULL); + +} + +static char * +_entrance_memstr(char *data, size_t length, char *look, unsigned int size) +{ + char *tmp; + + while (length >= size) + { + tmp = memchr(data, *look, length); + if (!tmp) return NULL; + + if (strncmp(tmp + 1, look + 1, size - 1) == 0) + return tmp; + length = tmp - data; + data = tmp; + } + + return NULL; +} + + +static void +_entrance_action_grub2_get(void) +{ + Eina_File *f; + unsigned char grub2_ok = 0; + intptr_t menuentry = 0; + char *data; + char *r, *r2; + char *s; + int i; + + fprintf(stderr, PACKAGE": trying to open "GRUB2_FILE); + f = eina_file_open(GRUB2_FILE, EINA_FALSE); + if (!f) return ; + fprintf(stderr, " o"); + + data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); + if (!data) goto on_error; + fprintf(stderr, "k\n"); + + s = data; + r2 = NULL; + for (i = eina_file_size_get(f); i > 0; --i, s++) + { + int size; + + /* working line by line */ + r = memchr(s, '\n', i); + if (!r) + { + r = s + i; + i = 0; + } + size = r - s; + + if (*s == '#') + goto end_line; + + /* look if the word is in this line */ + if (!grub2_ok) + r2 = _entrance_memstr(s, size, "default=\"${saved_entry}\"", 24); + else + r2 = _entrance_memstr(s, size, "menuentry", 9); + + /* still some lines to read */ + if (!r2) goto end_line; + + if (!grub2_ok) + { + grub2_ok = 1; + fprintf(stderr, PACKAGE": GRUB2 save mode found \n"); + } + else + { + char *action; + char *local; + char *tmp; + + r2 += 10; + size -= 10; + + tmp = memchr(r2, '\'', size); + if (!tmp) goto end_line; + + size -= tmp - r2 + 1; + r2 = tmp + 1; + tmp = memchr(r2, '\'', size); + if (!tmp) goto end_line; + + local = alloca(tmp - r2 + 1); + memcpy(local, r2, tmp - r2); + local[tmp - r2] = '\0'; + + action = malloc((tmp - r2 + 1 + 11) * sizeof (char)); + if (!action) goto end_line; + + sprintf(action, "Reboot on %s", local); + fprintf(stderr, PACKAGE": GRUB2 '%s'\n", action); + _entrance_actions = + eina_list_append(_entrance_actions, + _entrance_action_add(action, + _entrance_action_grub2, + (void*)(menuentry++))); + + } + + end_line: + i -= size; + s = r; + } + + eina_file_map_free(f, data); + on_error: + eina_file_close(f); +} +#endif diff --git a/src/daemon/entrance_action.h b/src/daemon/entrance_action.h new file mode 100644 index 0000000..419b205 --- /dev/null +++ b/src/daemon/entrance_action.h @@ -0,0 +1,9 @@ +#ifndef Entrance_Action_ +#define Entrance_Action_ + +void entrance_action_init(void); +void entrance_action_shutdown(void); +Eina_List *entrance_action_get(void); +void entrance_action_run(int action); + +#endif diff --git a/src/daemon/entrance_ck_launch.c b/src/daemon/entrance_ck_launch.c new file mode 100644 index 0000000..c894496 --- /dev/null +++ b/src/daemon/entrance_ck_launch.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + CkConnector *ck = NULL; + DBusError error; + pid_t pid; + int status; + + ck = ck_connector_new(); + if (ck != NULL) + { + dbus_error_init(&error); + if (ck_connector_open_session(ck, &error)) + { + pid = fork(); + if (pid) + { + waitpid(pid, &status, 0); + exit(status); + } + else + setenv("XDG_SESSION_COOKIE", + ck_connector_get_cookie(ck), 1); + } + else + fprintf(stderr, "entrance_ck: error connecting to ConsoleKit\n"); + } + else + fprintf(stderr, "entrance_ck: can't set up connection to ConsoleKit\n"); + + + if (argc > 1) + execvp(argv[1], argv + 1); + _exit (1); +} diff --git a/src/daemon/entrance_config.c b/src/daemon/entrance_config.c new file mode 100644 index 0000000..077aa18 --- /dev/null +++ b/src/daemon/entrance_config.c @@ -0,0 +1,184 @@ +#include "entrance.h" +#include + +#define ENTRANCE_CONFIG_KEY "config" + +static void _defaults_set(Entrance_Config *config); +static void _users_get(); +static void _config_free(Entrance_Config *config); +static Entrance_Config *_cache_get(Eet_Data_Descriptor *edd); + +static void +_defaults_set(Entrance_Config *config) +{ + config->session_path = eina_stringshare_add("/bin:/usr/bin:/usr/local/bin"); + config->command.xinit_path = eina_stringshare_add("/usr/bin/X"); + config->command.xinit_args = eina_stringshare_add("-nolisten tcp -br vt7"); + config->command.xauth_path = eina_stringshare_add("/usr/bin/xauth"); + config->command.xauth_file = eina_stringshare_add("/var/run/entrance.auth"); + config->command.session_start = eina_stringshare_add("/usr/bin/sessreg -a -l :0.0" ); + config->command.session_login = eina_stringshare_add("exec /bin/bash -login /etc/X11/xinit/xinitrc"); + config->command.session_stop = eina_stringshare_add("/usr/bin/sessreg -d -l :0.0"); + config->command.shutdown = eina_stringshare_add("/usr/bin/shutdown -h now"); + config->command.reboot = eina_stringshare_add("/usr/bin/shutdown -r now"); + config->command.suspend = eina_stringshare_add("/usr/sbin/suspend"); + config->daemonize = EINA_TRUE; + config->numlock = EINA_FALSE; + config->xsessions = EINA_FALSE; + config->autologin = EINA_FALSE; + config->userlogin = eina_stringshare_add("mylogintouse"); + config->lockfile = eina_stringshare_add("/var/run/entrance.pid"); + config->logfile = eina_stringshare_add("/var/log/entrance.log"); + config->theme = eina_stringshare_add("default"); +} + + +static void +_users_get() +{ + Eet_File *ef; + FILE *f; + int textlen; + char *text; + + if (!ecore_file_is_dir("/var/cache/"PACKAGE)) + ecore_file_mkdir("/var/cache/"PACKAGE); + ef = eet_open("/var/cache/"PACKAGE"/"ENTRANCE_CONFIG_FILE, + EET_FILE_MODE_READ_WRITE); + if (!ef) + ef = eet_open("/var/cache/"PACKAGE"/"ENTRANCE_CONFIG_FILE, + EET_FILE_MODE_WRITE); + f = fopen(SYSTEM_CONFIG_DIR"/entrance.conf", "rb"); + if (!f) + { + fprintf(stderr, + PACKAGE": Could not open "SYSTEM_CONFIG_DIR"/entrance.conf\n"); + return; + } + + fseek(f, 0, SEEK_END); + textlen = ftell(f); + rewind(f); + text = (char *)malloc(textlen); + if (!text) + { + fclose(f); + eet_close(ef); + return; + } + + if (fread(text, textlen, 1, f) != 1) + { + free(text); + fclose(f); + eet_close(ef); + return; + } + + fclose(f); + if (eet_data_undump(ef, ENTRANCE_CONFIG_KEY, text, textlen, 1)) + fprintf(stderr, PACKAGE": Updating configuration\n"); + free(text); + eet_close(ef); +} + +static Entrance_Config * +_cache_get(Eet_Data_Descriptor *edd) +{ + Entrance_Config *config = NULL; + Eet_File *file; + + if (!ecore_file_is_dir("/var/cache/"PACKAGE)) + ecore_file_mkdir("/var/cache/"PACKAGE); + file = eet_open("/var/cache/"PACKAGE"/"ENTRANCE_CONFIG_FILE, + EET_FILE_MODE_READ); + + config = eet_data_read(file, edd, ENTRANCE_CONFIG_KEY); + if (!config) + { + fprintf(stderr, PACKAGE": Warning no configuration found! This must \ + not append, we will go back to default configuration\n"); + config = (Entrance_Config *) calloc(1, sizeof(Entrance_Config)); + _defaults_set(config); + } + + eet_close(file); + + return config; +} + +static void +_config_free(Entrance_Config *config) +{ + eina_stringshare_del(config->session_path); + eina_stringshare_del(config->command.xinit_path); + eina_stringshare_del(config->command.xinit_args); + eina_stringshare_del(config->command.xauth_path); + eina_stringshare_del(config->command.xauth_file); + eina_stringshare_del(config->command.session_start); + eina_stringshare_del(config->command.session_login); + eina_stringshare_del(config->command.session_stop); + eina_stringshare_del(config->command.shutdown); + eina_stringshare_del(config->command.reboot); + eina_stringshare_del(config->command.suspend); + eina_stringshare_del(config->userlogin); + eina_stringshare_del(config->lockfile); + eina_stringshare_del(config->logfile); + eina_stringshare_del(config->theme); + free(config); +} + +void +entrance_config_init() +{ + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor_Class eddc; + struct stat cache; + struct stat conf; + + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Entrance_Config); + edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "session_path", session_path, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "xinit_path", command.xinit_path, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "xinit_args", command.xinit_args, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "xauth_path", command.xauth_path, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "xauth_file", command.xauth_file, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "session_start", command.session_start, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "session_login", command.session_login, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "session_stop", command.session_stop, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "shutdown", command.shutdown, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "reboot", command.reboot, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "suspend", command.suspend, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "daemonize", daemonize, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "numlock", numlock, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "xsessions", xsessions, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "autologin", autologin, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "userlogin", userlogin, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "lockfile", lockfile, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "logfile", logfile, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Config, "theme", theme, EET_T_STRING); + + if (stat( "/var/cache/"PACKAGE"/"ENTRANCE_CONFIG_FILE, &cache) == -1) + { + _users_get(); + } + else + { + stat(SYSTEM_CONFIG_DIR"/entrance.conf", &conf); + if (cache.st_mtime < conf.st_mtime) + { + _users_get(); + } + } + entrance_config = _cache_get(edd); + eet_data_descriptor_free(edd); +} + + +void +entrance_config_shutdown() +{ + _config_free(entrance_config); +} + diff --git a/src/daemon/entrance_config.h b/src/daemon/entrance_config.h new file mode 100644 index 0000000..d5c426a --- /dev/null +++ b/src/daemon/entrance_config.h @@ -0,0 +1,39 @@ +#ifndef ENTRANCE_CONFIG_H_ +#define ENTRANCE_CONFIG_H_ + +#define ENTRANCE_CONFIG_FILE "entrance.cfg" + +typedef struct _Entrance_Config Entrance_Config; + +struct _Entrance_Config +{ + const char *session_path; + struct + { + const char *xinit_path; + const char *xinit_args; + const char *xauth_path; + const char *xauth_file; + const char *session_start; + const char *session_login; + const char *session_stop; + const char *shutdown; + const char *reboot; + const char *suspend; + } command; + Eina_Bool daemonize;// :1; + Eina_Bool numlock;// :1; + Eina_Bool xsessions; + Eina_Bool autologin; + const char *userlogin; + const char *lockfile; + const char *logfile; + const char *theme; +}; + +void entrance_config_init(); +void entrance_config_shutdown(); + +Entrance_Config *entrance_config; + +#endif /* ENTRANCE_CONFIG_H_ */ diff --git a/src/daemon/entrance_history.c b/src/daemon/entrance_history.c new file mode 100644 index 0000000..f2a7f5e --- /dev/null +++ b/src/daemon/entrance_history.c @@ -0,0 +1,194 @@ +#include "entrance.h" + +#define ENTRANCE_SESSION_KEY "session" +#define ENTRANCE_HISTORY_FILE "entrance.hst" + +static void _entrance_history_read(); +static void _entrance_history_write(); +static void _entrance_user_init(); +static void _entrance_user_shutdown(); +const char *_entrance_history_match(const char *login); + + +static Eet_Data_Descriptor *_eddh; +static Entrance_History *_entrance_history; +static Eina_List *_lusers = NULL; +static Eina_Bool _history_update = EINA_FALSE; + +void +entrance_history_init() +{ + fprintf(stderr, PACKAGE": history init\n"); + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor_Class eddc, eddcl; + // TODO add idler to load history and thread stuff + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Entrance_Login); + edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Login, "login", login, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Login, "session", session, EET_T_STRING); + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddcl, Entrance_History); + _eddh = eet_data_descriptor_stream_new(&eddcl); + EET_DATA_DESCRIPTOR_ADD_LIST(_eddh, Entrance_History, "history", history, edd); + + _entrance_history_read(); + _entrance_user_init(); +} + +Eina_List *entrance_history_get() +{ + return _lusers; +} + +void +entrance_history_shutdown() +{ + fprintf(stderr, PACKAGE": history shutdown\n"); + _entrance_history_write(); + _entrance_user_shutdown(); +} + +static void +_entrance_history_read() +{ + Eet_File *ef; + + ef = eet_open("/var/cache/"PACKAGE"/"ENTRANCE_HISTORY_FILE, + EET_FILE_MODE_READ_WRITE); + if (!(ef) || !(_entrance_history = eet_data_read(ef, _eddh, ENTRANCE_SESSION_KEY))) + { + fprintf(stderr, PACKAGE": Error on reading last session login\n"); + _entrance_history = calloc(1, sizeof(Entrance_History)); + } + eet_close(ef); +} + +static void +_entrance_history_write() +{ + Eet_File *ef; + Entrance_Login *el; + + + if (_history_update) + { + fprintf(stderr, PACKAGE": writing history file\n"); + ef = eet_open("/var/cache/"PACKAGE"/"ENTRANCE_HISTORY_FILE, + EET_FILE_MODE_READ_WRITE); + if (!ef) + ef = eet_open("/var/cache/"PACKAGE"/"ENTRANCE_HISTORY_FILE, + EET_FILE_MODE_WRITE); + + if (!eet_data_write(ef, _eddh, ENTRANCE_SESSION_KEY, _entrance_history, 1)) + fprintf(stderr, PACKAGE": Error on updating last session login\n"); + + eet_close(ef); + } + EINA_LIST_FREE(_entrance_history->history, el) + { + eina_stringshare_del(el->login); + eina_stringshare_del(el->session); + } +} + +void +entrance_history_push(const char *login, const char *session) +{ + Eina_List *l; + Entrance_Login *el; + + EINA_LIST_FOREACH(_entrance_history->history, l, el) + { + if (!strcmp(login, el->login)) + { + if (el->session && strcmp(session, el->session)) + { + eina_stringshare_replace(&el->session, session); + _history_update = EINA_TRUE; + } + break; + } + } + if (!el) + { + if ((el = (Entrance_Login *) malloc(sizeof(Entrance_Login)))) + { + el->login = eina_stringshare_add(login); + el->session = eina_stringshare_add(session); + _entrance_history->history = + eina_list_append(_entrance_history->history, el); + _history_update = EINA_TRUE; + } + } +} + + +const char * +_entrance_history_match(const char *login) +{ + Eina_List *l; + Entrance_Login *el; + const char *ret = NULL; + EINA_LIST_FOREACH(_entrance_history->history, l, el) + { + if (!strcmp(el->login, login)) + ret = el->session; + } + return ret; +} + +static void +_entrance_user_init() +{ + char buf[PATH_MAX]; + FILE *f; + Entrance_User *eu; + Eina_List *lu = NULL; + char *token; + char *user; + int uid; + + f = fopen("/etc/passwd", "r"); + if (f) + { + while (fgets(buf, sizeof(buf), f)) + { + user = strtok(buf, ":"); + strtok(NULL, ":"); + token = strtok(NULL, ":"); + uid = atoi(token); + if (uid > 500 && uid < 3000) + lu = eina_list_append(lu, eina_stringshare_add(user)); + } + } + EINA_LIST_FREE(lu, user) + { + if ((eu = (Entrance_User *) malloc(sizeof(Entrance_User)))) + { + eu->login = eina_stringshare_add(user); + snprintf(buf, sizeof(buf), + "/var/cache/"PACKAGE"/users/%s.edj", user); + if (ecore_file_exists(buf)) + eu->image = eina_stringshare_add(buf); + else + eu->image = NULL; + eu->lsess = _entrance_history_match(user); + eina_stringshare_del(user); + _lusers = eina_list_append(_lusers, eu); + } + } +} + +static void +_entrance_user_shutdown() +{ + Entrance_User *eu; + EINA_LIST_FREE(_lusers, eu) + { + eina_stringshare_del(eu->login); + free(eu); + } + free(_entrance_history); +} + diff --git a/src/daemon/entrance_history.h b/src/daemon/entrance_history.h new file mode 100644 index 0000000..cc000b2 --- /dev/null +++ b/src/daemon/entrance_history.h @@ -0,0 +1,24 @@ +#ifndef ENTRANCE_HISTORY_ +#define ENTRANCE_HISTORY_ + +void entrance_history_init(); +void entrance_history_shutdown(); +void entrance_history_push(const char *login, const char *session); +Eina_List *entrance_history_get(); + +typedef struct _Entrance_Login Entrance_Login; +typedef struct _Entrance_History Entrance_History; + +struct _Entrance_Login +{ + const char *login; + const char *session; +}; + +struct _Entrance_History +{ + Eina_List *history; +}; + + +#endif /* ENTRANCE_HISTORY_ */ diff --git a/src/daemon/entrance_pam.c b/src/daemon/entrance_pam.c new file mode 100644 index 0000000..bef0979 --- /dev/null +++ b/src/daemon/entrance_pam.c @@ -0,0 +1,305 @@ +#include +#include +#include + +#include "entrance.h" + + /* + * ... + * pam_start(...); Initializes the PAM library + * ... + * if ( ! pam_authenticate(...) ) Autenticates using modules + * error_exit(); + * ... + * if ( ! pam-acct_mgmt(...) ) Checks for a valid, unexpired account and + * verifies access restrictions with "account" modules + * error_exit(); + * ... + * pam_setcred(...) Sets extra credentials, e.g. a Kerberos ticket + * ... + * pam_open_session(...); Sets up the session with "session" modules + * do_stuff(); + * + * pam_close_session(...); Tear-down session using the "session" modules + * pam_end(...); + * */ +static int _entrance_pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr); + +static struct pam_conv _pam_conversation; +static pam_handle_t* _pam_handle; +static int last_result; +static char *_login = NULL; +static char *_passwd = NULL; + + + +static int +_entrance_pam_conv(int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr __UNUSED__) { + int i, result = PAM_SUCCESS; + *resp = (struct pam_response *) calloc(num_msg, sizeof(struct pam_response)); + for (i = 0; i < num_msg; ++i){ + resp[i]->resp=0; + resp[i]->resp_retcode=0; + switch(msg[i]->msg_style){ + case PAM_PROMPT_ECHO_ON: + // We assume PAM is asking for the username + fprintf(stderr, PACKAGE": echo on\n"); + resp[i]->resp = _login; + break; + + case PAM_PROMPT_ECHO_OFF: + fprintf(stderr, PACKAGE": echo off\n"); + resp[i]->resp = _passwd; + _passwd = NULL; + break; + case PAM_ERROR_MSG: + fprintf(stderr, PACKAGE": error msg\n"); + case PAM_TEXT_INFO: + fprintf(stderr, PACKAGE": info %s\n", msg[i]->msg); + break; + case PAM_SUCCESS: + fprintf(stderr, PACKAGE": success :)\n"); + break; + default: + fprintf(stderr, PACKAGE": default\n"); + + } + if (result != PAM_SUCCESS) break; + } + if (result != PAM_SUCCESS) { + for (i = 0; i < num_msg; ++i){ + if (resp[i]->resp==0) continue; + free(resp[i]->resp); + resp[i]->resp=0; + }; + free(*resp); + *resp=0; + } + return result; +} + +static char * +_get_running_username(void) +{ + char *result; + struct passwd *pwent = NULL; + pwent = getpwuid(getuid()); + result = strdup(pwent->pw_name); + endpwent(); + return (result); +} + + +int +entrance_pam_open_session() +{ + last_result = pam_setcred(_pam_handle, PAM_ESTABLISH_CRED); + switch (last_result) + { + case PAM_CRED_ERR: + case PAM_USER_UNKNOWN: + fprintf(stderr, PACKAGE": PAM user unknow\n"); + return 1; + case PAM_AUTH_ERR: + case PAM_PERM_DENIED: + fprintf(stderr, PACKAGE": PAM error on login password\n"); + return 1; + default: + fprintf(stderr, PACKAGE": PAM open warning unknow error\n"); + return 1; + case PAM_SUCCESS: + break; + } + last_result = pam_open_session(_pam_handle, 0); + switch(last_result) + { + default: + //case PAM_SESSION_ERROR: ??? + pam_setcred(_pam_handle, PAM_DELETE_CRED); + entrance_pam_end(); + case PAM_SUCCESS: + break; + } + return 0; +} + +void +entrance_pam_close_session() { + fprintf(stderr, PACKAGE": PAM close session\n"); + last_result = pam_close_session(_pam_handle, PAM_SILENT); + switch (last_result) { + default: + //case PAM_SESSION_ERROR: + pam_setcred(_pam_handle, PAM_DELETE_CRED); + entrance_pam_end(); + case PAM_SUCCESS: + break; + }; + last_result = pam_setcred(_pam_handle, PAM_DELETE_CRED); + switch(last_result) { + default: + case PAM_CRED_ERR: + case PAM_CRED_UNAVAIL: + case PAM_CRED_EXPIRED: + case PAM_USER_UNKNOWN: + entrance_pam_end(); + case PAM_SUCCESS: + break; + }; + return; +} + +int +entrance_pam_end() { + int result; + result = pam_end(_pam_handle, last_result); + _pam_handle = NULL; + return result; +} + +int +entrance_pam_authenticate() +{ + last_result = pam_authenticate(_pam_handle, 0); + switch (last_result) + { + case PAM_ABORT: + case PAM_AUTHINFO_UNAVAIL: + fprintf(stderr, PACKAGE": PAM error !\n"); + entrance_pam_end(); + return 1; + case PAM_USER_UNKNOWN: + fprintf(stderr, PACKAGE": PAM user unknow error !\n"); + return 1; + case PAM_MAXTRIES: + fprintf(stderr, PACKAGE": PAM max tries error !\n"); + entrance_server_client_wait(); + return 1; + case PAM_CRED_INSUFFICIENT: + fprintf(stderr, PACKAGE": PAM %s don't have sufficient credential to authenticate !\n", PACKAGE); + return 1; + case PAM_AUTH_ERR: + fprintf(stderr, PACKAGE": PAM authenticate error !\n"); + return 1; + default: + fprintf(stderr, PACKAGE": PAM auth warning unknow error\n"); + return 1; + case PAM_SUCCESS: + break; + } + last_result=pam_acct_mgmt(_pam_handle, PAM_SILENT); + switch(last_result) + { + default: + //case PAM_NEW_AUTHTOKEN_REQD: + case PAM_ACCT_EXPIRED: + case PAM_USER_UNKNOWN: + entrance_pam_end(); + return 1; + case PAM_AUTH_ERR: + case PAM_PERM_DENIED: + return 1; + case PAM_SUCCESS: + break; + } + + return 0; +} + +int +entrance_pam_init(const char *service, const char *display, const char *user) { + int status; + + if (!service && !*service) goto pam_error; + if (!display && !*display) goto pam_error; + + _pam_handle = NULL; + _pam_conversation.conv = _entrance_pam_conv; + _pam_conversation.appdata_ptr = NULL; + + + fprintf(stderr, PACKAGE": Pam init with name %s\n", service); + if (_pam_handle) entrance_pam_end(); + status = pam_start(service, user, &_pam_conversation, &_pam_handle); + + if (status != 0) goto pam_error; + status = entrance_pam_item_set(ENTRANCE_PAM_ITEM_TTY, display); + if (status != 0) goto pam_error; + status = entrance_pam_item_set(ENTRANCE_PAM_ITEM_RUSER, _get_running_username()); + if (status != 0) goto pam_error; +// status = entrance_pam_item_set(ENTRANCE_PAM_ITEM_RHOST, "localhost"); +// if (status != 0) goto pam_error; + return 0; + +pam_error: + fprintf(stderr, PACKAGE": PAM error !!!\n"); + return 1; +} + +int +entrance_pam_item_set(ENTRANCE_PAM_ITEM_TYPE type, const void *value) { + last_result = pam_set_item(_pam_handle, type, value); + if (last_result == PAM_SUCCESS) { + return 0; + } + fprintf(stderr, PACKAGE": PAM error: %d on %d", last_result, type); + return 1; +} + +const void * +entrance_pam_item_get(ENTRANCE_PAM_ITEM_TYPE type) { + const void *data; + last_result = pam_get_item(_pam_handle, type, &data); + switch (last_result) { + default: + case PAM_SYSTEM_ERR: + entrance_pam_end(); + fprintf(stderr, PACKAGE": error on pam item get\n"); + case PAM_PERM_DENIED: /* Here data was NULL */ + case PAM_SUCCESS: + break; + } + return data; +} + +int +entrance_pam_env_set(const char *env, const char *value) { + char buf[1024]; + if (!env || !value) return 1; + snprintf(buf, sizeof(buf), "%s=%s", env, value); + last_result = pam_putenv(_pam_handle, buf); + switch (last_result) { + default: + case PAM_PERM_DENIED: + case PAM_ABORT: + case PAM_BUF_ERR: + entrance_pam_end(); + return 1; + case PAM_SUCCESS: + break; + }; + return 0; + +} + +char ** +entrance_pam_env_list_get() { + return pam_getenvlist(_pam_handle); +} + +void +entrance_pam_shutdown() { + fprintf(stderr, PACKAGE": Pam shutdown\n"); +} + +int +entrance_pam_auth_set(const char *login, const char *passwd) +{ + if (!login) + return 1; + _login = strdup(login); + if (passwd) + _passwd = strdup(passwd); + return 0; +} diff --git a/src/daemon/entrance_pam.h b/src/daemon/entrance_pam.h new file mode 100644 index 0000000..1d94ece --- /dev/null +++ b/src/daemon/entrance_pam.h @@ -0,0 +1,28 @@ +#ifndef ENTRANCE_PAM_H_ +#define ENTRANCE_PAM_H_ + +#include + +typedef enum ENTRANCE_PAM_ITEM_TYPE_ { + ENTRANCE_PAM_ITEM_SERVICE = PAM_SERVICE, + ENTRANCE_PAM_ITEM_USER = PAM_USER, + ENTRANCE_PAM_ITEM_TTY = PAM_TTY, + ENTRANCE_PAM_ITEM_RUSER = PAM_RUSER, + ENTRANCE_PAM_ITEM_RHOST = PAM_RHOST, + ENTRANCE_PAM_ITEM_CONV = PAM_CONV +} ENTRANCE_PAM_ITEM_TYPE; + + +int entrance_pam_item_set(ENTRANCE_PAM_ITEM_TYPE type, const void *value); +const void *entrance_pam_item_get(ENTRANCE_PAM_ITEM_TYPE); +int entrance_pam_env_set(const char *env, const char *value); +char **entrance_pam_env_list_get(); +int entrance_pam_init(const char *service, const char *display, const char *user); +void entrance_pam_shutdown(); +int entrance_pam_open_session(); +void entrance_pam_close_session(); +int entrance_pam_authenticate(); +int entrance_pam_auth_set(const char *login, const char *passwd); +int entrance_pam_end(); + +#endif /* ENTRANCE_PAM_H_ */ diff --git a/src/daemon/entrance_server.c b/src/daemon/entrance_server.c new file mode 100644 index 0000000..f938f09 --- /dev/null +++ b/src/daemon/entrance_server.c @@ -0,0 +1,172 @@ +#include +#include "entrance.h" +#include "../event/entrance_event.h" + +static Eina_Bool _entrance_server_add(void *data, int type, void *event); +static Eina_Bool _entrance_server_del(void *data, int type, void *event); +static Eina_Bool _entrance_server_data(void *data, int type, void *event); + + +Ecore_Con_Server *_entrance_server = NULL; +Eina_List *_handlers = NULL; + + +static Eina_Bool +_my_hack2(void *data) +{ + Entrance_Event eev; + void *enc; + int size; + eev.type = ENTRANCE_EVENT_ACTIONS; + eev.event.actions.actions = entrance_action_get(); + enc = entrance_event_encode(&eev, &size); + ecore_con_client_send(data, enc, size); + return ECORE_CALLBACK_CANCEL; +} + +static Eina_Bool +_my_hack(void *data) +{ + Entrance_Event eev; + void *enc; + int size; + + eev.type = ENTRANCE_EVENT_XSESSIONS; + if (entrance_config->xsessions) + { + eev.event.xsessions.xsessions = entrance_session_list_get(); + enc = entrance_event_encode(&eev, &size); + ecore_con_client_send(data, enc, size); + } + ecore_timer_add(0.5, _my_hack2, data); + return ECORE_CALLBACK_CANCEL; +} + + +static Eina_Bool +_entrance_server_add(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Con_Event_Client_Add *ev; + Entrance_Event eeu; + ev = event; + void *enc; + int size; + + fprintf(stderr, PACKAGE": server client connected\n"); + eeu.type = ENTRANCE_EVENT_USERS; + eeu.event.users.users = entrance_history_get(); + enc = entrance_event_encode(&eeu, &size); + ecore_con_client_send(ev->client, enc, size); +// ecore_con_client_flush(ev->client); + ecore_timer_add(0.5, _my_hack, ev->client); + /* + eev.type = ENTRANCE_EVENT_XSESSIONS; + if (entrance_config->xsessions) + { + eev.event.xsessions.xsessions = entrance_session_list_get(); + enc = entrance_event_encode(&eev, &size); + ecore_con_client_send(data, enc, size); + } + */ + return ECORE_CALLBACK_RENEW; +} + + +static Eina_Bool +_entrance_server_del(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Con_Event_Client_Del *ev; + ev = event; + fprintf(stderr, PACKAGE": server client disconnected\n"); + + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_entrance_server_data(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + + Ecore_Con_Event_Client_Data *ev; + Entrance_Event *eev, neev; + int size; + void *enc; + + ev = event; + eev = entrance_event_decode(ev->data, ev->size); + if (eev->type == ENTRANCE_EVENT_AUTH) + { + neev.type = ENTRANCE_EVENT_STATUS; + if (entrance_session_authenticate(eev->event.auth.login, + eev->event.auth.password)) + { + entrance_session_login(eev->event.auth.session, EINA_TRUE); + neev.event.status.granted = EINA_TRUE; + fprintf(stderr, PACKAGE": server authenticate granted\n"); + } + else + { + neev.event.status.granted = EINA_FALSE; + fprintf(stderr, PACKAGE": server authenticate error\n"); + } + enc = entrance_event_encode(&neev, &size); + ecore_con_client_send(ev->client, enc, size); + } + else if (eev->type == ENTRANCE_EVENT_ACTION) + entrance_action_run(eev->event.action.action); + else + fprintf(stderr, PACKAGE": UNKNOW signal server\n"); + + return ECORE_CALLBACK_RENEW; +} + +void +entrance_server_init() +{ + Ecore_Event_Handler *h; + ecore_con_init(); + fprintf(stderr, PACKAGE": server init\n"); + _entrance_server = ecore_con_server_add(ECORE_CON_LOCAL_SYSTEM, + "entrance", 42, NULL); + if (_entrance_server) + fprintf(stderr, PACKAGE": server init ok\n"); + else + fprintf(stderr, PACKAGE": server init fail\n"); + + h = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, + _entrance_server_add, NULL); + _handlers = eina_list_append(_handlers, h); + h = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, + _entrance_server_del, NULL); + _handlers = eina_list_append(_handlers, h); + h = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, + _entrance_server_data, NULL); + _handlers = eina_list_append(_handlers, h); +} + +void +entrance_server_shutdown() +{ + Ecore_Event_Handler *h; + fprintf(stderr, PACKAGE": server shutdown\n"); + if (_entrance_server) + ecore_con_server_del(_entrance_server); + EINA_LIST_FREE(_handlers, h) + ecore_event_handler_del(h); + ecore_con_shutdown(); +} + +void +entrance_server_client_wait() +{ + const Eina_List *l; + Entrance_Event eev; + Ecore_Con_Client *ecc; + void *enc; + int size; + eev.type = ENTRANCE_EVENT_MAXTRIES; + eev.event.maxtries.maxtries = EINA_TRUE; + enc = entrance_event_encode(&eev, &size); + EINA_LIST_FOREACH(ecore_con_server_clients_get(_entrance_server), l, ecc) + ecore_con_client_send(ecc, enc, size); +} + diff --git a/src/daemon/entrance_server.h b/src/daemon/entrance_server.h new file mode 100644 index 0000000..21c6ead --- /dev/null +++ b/src/daemon/entrance_server.h @@ -0,0 +1,8 @@ +#ifndef ENTRANCE_SERVER_ +#define ENTRANCE_SERVER_ + +void entrance_server_init(); +void entrance_server_client_wait(); +void entrance_server_shutdown(); + +#endif /* ENTRANCE_SERVER_ */ diff --git a/src/daemon/entrance_session.c b/src/daemon/entrance_session.c new file mode 100644 index 0000000..918dc88 --- /dev/null +++ b/src/daemon/entrance_session.c @@ -0,0 +1,477 @@ +#include +#include +#include +#ifndef HAVE_PAM +#include +#include +#endif + +#include +#include +#include "entrance.h" + +#define HAVE_SHADOW 1 + +static char *_mcookie; +static char **env; +static char *_login = NULL; +static unsigned char _logged = 0; +//static Eina_List *_user_list = NULL; +static pid_t _session_pid; +static Eina_List *_xsessions = NULL; +static int _entrance_session_userid_set(struct passwd *pwd); + +static void _entrance_session_run(struct passwd *pwd, const char *cmd, const char *cookie); + +static void _entrance_session_desktops_scan_file(const char *path); +static void _entrance_session_desktops_scan(const char *dir); +static void _entrance_session_desktops_init(); +//static void _entrance_session_desktops_shutdown(); +static const char *_entrance_session_find_command(const char *path, const char *session); +static struct passwd *_entrance_session_session_open(); + +long +entrance_session_seed_get() +{ + struct timespec ts; + long pid = getpid(); + long tm = time(NULL); + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + ts.tv_sec = ts.tv_nsec = 0; + return pid + tm + (ts.tv_sec ^ ts.tv_nsec); +} + +static int +_entrance_session_cookie_add(const char *mcookie, const char *display, + const char *xauth_cmd, const char *auth_file) +{ + char buf[PATH_MAX]; + FILE *cmd; + + if (!xauth_cmd || !auth_file) return 1; + snprintf(buf, sizeof(buf), "%s -f %s -q", xauth_cmd, auth_file); + fprintf(stderr, PACKAGE": write auth '%s'\n", buf); + cmd = popen(buf, "w"); + if (!cmd) return 1; + fprintf(cmd, "remove %s\n", display); + fprintf(cmd, "add %s . %s\n", display, mcookie); + fprintf(cmd, "exit\n"); + pclose(cmd); + return 0; +} + +static int +_entrance_session_userid_set(struct passwd *pwd) +{ + if (!pwd) + { + fprintf(stderr, PACKAGE": no passwd !\n"); + return 1; + } + if (initgroups(pwd->pw_name, pwd->pw_gid) != 0) + { + fprintf(stderr, PACKAGE": can't init group\n"); + return 1; + } + if (setgid(pwd->pw_gid) != 0) + { + fprintf(stderr, PACKAGE": can't set gid\n"); + return 1; + } + if (setuid(pwd->pw_uid) != 0) + { + fprintf(stderr, PACKAGE": can't set uid\n"); + return 1; + } + +/* fprintf(stderr, PACKAGE": name -> %s, gid -> %d, uid -> %d\n", + pwd->pw_name, pwd->pw_gid, pwd->pw_uid); */ + return 0; +} + +static Eina_Bool +_entrance_session_begin(struct passwd *pwd, const char *cookie) +{ + fprintf(stderr, PACKAGE": Session Init\n"); + if (pwd->pw_shell[0] == '\0') + { + setusershell(); + strcpy(pwd->pw_shell, getusershell()); + endusershell(); + } +#ifdef HAVE_PAM + char *term = getenv("TERM"); + if (term) entrance_pam_env_set("TERM", term); + entrance_pam_env_set("HOME", pwd->pw_dir); + entrance_pam_env_set("SHELL", pwd->pw_shell); + entrance_pam_env_set("USER", pwd->pw_name); + entrance_pam_env_set("LOGNAME", pwd->pw_name); + entrance_pam_env_set("PATH", entrance_config->session_path); + entrance_pam_env_set("DISPLAY", ":0.0"); + entrance_pam_env_set("MAIL", ""); + entrance_pam_env_set("XAUTHORITY", cookie); + entrance_pam_env_set("XDG_SESSION_CLASS", "greeter"); +#endif + return EINA_TRUE; +} + +static void +_entrance_session_run(struct passwd *pwd, const char *cmd, const char *cookie) +{ + //char **tmp; + char buf[PATH_MAX]; + pid_t pid; + pid = fork(); + if (pid == 0) + { + + fprintf(stderr, PACKAGE": Session Run\n"); +#ifdef HAVE_PAM + env = entrance_pam_env_list_get(); + entrance_pam_end(); +#else + int n = 0; + char *term = getenv("TERM"); + env = (char **)malloc(10 * sizeof(char *)); + if(term) + { + snprintf(buf, sizeof(buf), "TERM=%s", term); + env[n++]=strdup(buf); + } + snprintf(buf, sizeof(buf), "HOME=%s", pwd->pw_dir); + env[n++]=strdup(buf); + snprintf(buf, sizeof(buf), "SHELL=%s", pwd->pw_shell); + env[n++]=strdup(buf); + snprintf(buf, sizeof(buf), "USER=%s", pwd->pw_name); + env[n++]=strdup(buf); + snprintf(buf, sizeof(buf), "LOGNAME=%s", pwd->pw_name); + env[n++]=strdup(buf); + snprintf(buf, sizeof(buf), "PATH=%s", entrance_config->session_path); + env[n++]=strdup(buf); + snprintf(buf, sizeof(buf), "DISPLAY=%s", ":0.0"); + env[n++]=strdup(buf); + snprintf(buf, sizeof(buf), "MAIL="); + env[n++]=strdup(buf); + snprintf(buf, sizeof(buf), "XAUTHORITY=%s", cookie); + env[n++]=strdup(buf); + env[n++]=0; +#endif + snprintf(buf, sizeof(buf), + "%s %s ", + entrance_config->command.session_start, + pwd->pw_name); + if (-1 == system(buf)) + fprintf(stderr, PACKAGE": Error on session start command %s\n", buf); + if(_entrance_session_userid_set(pwd)) return; + _entrance_session_cookie_add(_mcookie, ":0", + entrance_config->command.xauth_path, cookie); + if (chdir(pwd->pw_dir)) + { + fprintf(stderr, PACKAGE": change directory for user fail\n"); + return; + } +// fprintf(stderr, PACKAGE": Open %s`s session\n", pwd->pw_name); + snprintf(buf, sizeof(buf), "%s/.entrance_session.log", pwd->pw_dir); + remove(buf); + { + Eina_List *files; + char *exec_file; + char exec_buff[PATH_MAX]; + files = ecore_file_ls("/etc/profile.d/"); + EINA_LIST_FREE(files, exec_file) + { + snprintf(exec_buff, sizeof(exec_buff), "%s /etc/profile.d/%s", + pwd->pw_shell, exec_file); + if (-1 == system(exec_buff)) + fprintf(stderr, PACKAGE": error on executing %s\n", + exec_buff); + free(exec_file); + } + } + + +#ifdef HAVE_CONSOLEKIT + snprintf(buf, sizeof(buf), PACKAGE_BIN_DIR"/entrance_ck_launch %s > %s/.entrance_session.log 2>&1", + cmd, pwd->pw_dir); +#else + snprintf(buf, sizeof(buf), "%s > %s/.entrance_session.log 2>&1", + cmd, pwd->pw_dir); +#endif + execle(pwd->pw_shell, pwd->pw_shell, "-c", buf, NULL, env); + fprintf(stderr, PACKAGE": The Xsessions are not launched :(\n"); + } +} + +void +entrance_session_end(const char *user) +{ + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), + "%s %s ", entrance_config->command.session_stop, user); + if (-1 == system(buf)) + fprintf(stderr, PACKAGE": Error on session stop command %s", buf); +#ifdef HAVE_PAM + entrance_pam_close_session(); + entrance_pam_end(); + entrance_pam_shutdown(); +#endif +} + +void +entrance_session_pid_set(pid_t pid) +{ + fprintf(stderr, "%s: session pid %d\n", PACKAGE, pid); + _session_pid = pid; +} + +pid_t +entrance_session_pid_get() +{ + return _session_pid; +} + +static const char *dig = "0123456789abcdef"; + +void +entrance_session_init(const char *file) +{ + uint16_t word; + uint8_t hi, lo; + int i; + char buf[PATH_MAX]; + + fprintf(stderr, PACKAGE": Session init '%s'\n", file); + + _mcookie = calloc(33, sizeof(char)); + _mcookie[0] = 'a'; + + srand(entrance_session_seed_get()); + for (i=0; i<32; i+=4) + { + word = rand() & 0xffff; + lo = word & 0xff; + hi = word >> 8; + _mcookie[i] = dig[lo & 0x0f]; + _mcookie[i+1] = dig[lo >> 4]; + _mcookie[i+2] = dig[hi & 0x0f]; + _mcookie[i+3] = dig[hi >> 4]; + } + remove(file); + snprintf(buf, sizeof(buf), "XAUTHORITY=%s", file); + putenv(strdup(buf)); + //fprintf(stderr, PACKAGE": cookie %s \n", _mcookie); + _entrance_session_cookie_add(_mcookie, ":0", + entrance_config->command.xauth_path, file); + _entrance_session_desktops_init(); +} + +void +entrance_session_shutdown() +{ + Entrance_Xsession *xsession; + + EINA_LIST_FREE(_xsessions, xsession) + { + eina_stringshare_del(xsession->name); + eina_stringshare_del(xsession->icon); + if (xsession->command) eina_stringshare_del(xsession->command); + free(xsession); + } +} + +Eina_Bool +entrance_session_authenticate(const char *login, const char *passwd) +{ + _login = strdup(login); +#ifdef HAVE_PAM + return (!entrance_pam_auth_set(login, passwd) + && !entrance_pam_authenticate()); +#else + char *enc, *v; + struct passwd *pwd; + + pwd = getpwnam(login); + endpwent(); + if(!pwd) + return EINA_FALSE; +#ifdef HAVE_SHADOW + struct spwd *spd; + spd = getspnam(pwd->pw_name); + endspent(); + if(spd) + v = spd->sp_pwdp; + else +#endif + v = pwd->pw_passwd; + if(!v || *v == '\0') + return EINA_TRUE; + enc = crypt(passwd, v); + return !strcmp(enc, v); +#endif +} + +static struct passwd * +_entrance_session_session_open() +{ +#ifdef HAVE_PAM + if (!entrance_pam_open_session()) + return getpwnam(entrance_pam_item_get(ENTRANCE_PAM_ITEM_USER)); + return NULL; +#else + return getpwnam(entrance_session_login_get()); +#endif +} + +Eina_Bool +entrance_session_login(const char *session, Eina_Bool push) +{ + struct passwd *pwd; + const char *cmd; + char buf[PATH_MAX]; + + pwd = _entrance_session_session_open(); + endpwent(); + if (!pwd) return ECORE_CALLBACK_CANCEL; + _logged = EINA_TRUE; + snprintf(buf, sizeof(buf), "%s/.Xauthority", pwd->pw_dir); + if (!_entrance_session_begin(pwd, buf)) + { + fprintf(stderr, "Entrance: couldn't open session\n"); + exit(1); + } + if (push) entrance_history_push(pwd->pw_name, session); + cmd = _entrance_session_find_command(pwd->pw_dir, session); + fprintf(stderr, PACKAGE": launching %s for user %s\n", cmd, _login); + _entrance_session_run(pwd, cmd, buf); + return ECORE_CALLBACK_CANCEL; +} + +static const char * +_entrance_session_find_command(const char *path, const char *session) +{ + Eina_List *l; + Entrance_Xsession *xsession; + char buf[PATH_MAX]; + if (session) + { + EINA_LIST_FOREACH(_xsessions, l, xsession) + { + if (!strcmp(xsession->name, session)) + { + if (xsession->command) + return xsession->command; + } + } + } + snprintf(buf, sizeof(buf), "%s/%s", path, ".Xsession"); + if (ecore_file_can_exec(buf)) + return eina_stringshare_add(buf); + return (entrance_config->command.session_login); +} + +char * +entrance_session_login_get() +{ + return _login; +} + +int +entrance_session_logged_get() +{ + return !!_logged; +} + +Eina_List * +entrance_session_list_get() +{ + return _xsessions; +} + +static void +_entrance_session_desktops_init() +{ + char buf[PATH_MAX]; + Eina_List *dirs; + const char *path; + Entrance_Xsession *xsession; + Eina_List *l; + + xsession = calloc(1, sizeof(Entrance_Xsession)); + xsession->name = eina_stringshare_add("System"); + xsession->icon = eina_stringshare_add("entrance/system"); + _xsessions = eina_list_append(_xsessions, xsession); + + efreet_init(); + efreet_desktop_type_alias(EFREET_DESKTOP_TYPE_APPLICATION, "XSession"); + /* Maybee need to scan other directories ? + * _entrance_session_desktops_scan("/etc/share/xsessions"); + */ + _entrance_session_desktops_scan("/etc/X11/dm/Sessions"); + snprintf(buf, sizeof(buf), "%s/xsessions", efreet_data_home_get()); + _entrance_session_desktops_scan(buf); + dirs = efreet_data_dirs_get(); + EINA_LIST_FOREACH(dirs, l, path) + { + snprintf(buf, sizeof(buf), "%s/xsessions", path); + _entrance_session_desktops_scan(buf); + } + efreet_shutdown(); +} + +static void +_entrance_session_desktops_scan(const char *dir) +{ + Eina_List *files; + char *filename; + char path[PATH_MAX]; + + if (ecore_file_is_dir(dir)) + { + fprintf(stderr, PACKAGE": scanning directory %s\n", dir); + files = ecore_file_ls(dir); + EINA_LIST_FREE(files, filename) + { + snprintf(path, sizeof(path), "%s/%s", dir, filename); + _entrance_session_desktops_scan_file(path); + free(filename); + } + } +} + +static void +_entrance_session_desktops_scan_file(const char *path) +{ + Efreet_Desktop *desktop; + Eina_List *commands; + Eina_List *l; + Entrance_Xsession *xsession; + char *command = NULL; + + desktop = efreet_desktop_get(path); + if (!desktop) return; + EINA_LIST_FOREACH(_xsessions, l, xsession) + { + if (!strcmp(xsession->name, desktop->name)) + { + efreet_desktop_free(desktop); + return; + } + } + + commands = efreet_desktop_command_local_get(desktop, NULL); + if (commands) + command = eina_list_data_get(commands); + if (command && desktop->name) + { + xsession= calloc(1, sizeof(Entrance_Xsession)); + xsession->command = eina_stringshare_add(command); + xsession->name = eina_stringshare_add(desktop->name); + if (desktop->icon) xsession->icon = eina_stringshare_add(desktop->icon); + _xsessions = eina_list_append(_xsessions, xsession); + fprintf(stderr, PACKAGE": client find sessions %s\n", desktop->name); + } + EINA_LIST_FREE(commands, command) + free(command); + efreet_desktop_free(desktop); +} + diff --git a/src/daemon/entrance_session.h b/src/daemon/entrance_session.h new file mode 100644 index 0000000..e73bf38 --- /dev/null +++ b/src/daemon/entrance_session.h @@ -0,0 +1,17 @@ +#ifndef ENTRANCE_SESSION_H_ +#define ENTRANCE_SESSION_H_ +#include + +void entrance_session_init(const char *file); +void entrance_session_end(const char *login); +void entrance_session_shutdown(); +Eina_Bool entrance_session_authenticate(const char *login, const char *pwd); +Eina_Bool entrance_session_login(const char *command, Eina_Bool push); +void entrance_session_pid_set(pid_t pid); +pid_t entrance_session_pid_get(); +long entrance_session_seed_get(); +char *entrance_session_login_get(); +int entrance_session_logged_get(); +Eina_List *entrance_session_list_get(); + +#endif /* ENTRANCE_SESSION_H_ */ diff --git a/src/daemon/entrance_test.c b/src/daemon/entrance_test.c new file mode 100644 index 0000000..880360e --- /dev/null +++ b/src/daemon/entrance_test.c @@ -0,0 +1,60 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +int elm_main (int argc, char **argv); + +static Evas_Object * +_theme_get(Evas_Object *win, const char *group) +{ + char buffer[PATH_MAX]; + Evas_Object *edje = NULL; + + edje = elm_layout_add(win); + snprintf(buffer, sizeof(buffer), "%s/themes/default.edj", PACKAGE_DATA_DIR); + elm_layout_file_set(edje, buffer, group); + return edje; +} + +static void +_signal(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *sig, const char *src) +{ + printf("Event: %s - %s \n", sig, src); +} + + +static void +_shutdown(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + printf("Quit\n"); + elm_exit(); +} + + +int +elm_main (int argc __UNUSED__, char **argv __UNUSED__) +{ + Evas_Object *o, *win; + win = elm_win_add(NULL, "theme_test", ELM_WIN_BASIC); + elm_win_title_set(win, PACKAGE); + evas_object_smart_callback_add(win, "delete,request", + _shutdown, NULL); + o = _theme_get(win, "entrance"); + evas_object_size_hint_weight_set(o, + EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + edje_object_signal_callback_add(elm_layout_edje_get(o), + "*", "*", + _signal, NULL); + elm_win_resize_object_add(win, o); + evas_object_show(o); + evas_object_resize(win, 640, 480); + evas_object_show(win); + elm_run(); + elm_shutdown(); + return 0; +} + +ELM_MAIN() diff --git a/src/daemon/entrance_wait.c b/src/daemon/entrance_wait.c new file mode 100644 index 0000000..27f38e3 --- /dev/null +++ b/src/daemon/entrance_wait.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +static void _entrance_wait_action(int sig, siginfo_t *si, void *data); +static void kill_wait(); + + +static pid_t _x_pid = 0; + +static void +_entrance_wait_action(int sig, siginfo_t * si __UNUSED__, void *data __UNUSED__) +{ + kill_wait(); + if (sig != SIGCHLD) + setenv("ENTRANCE_QUIT", "1", 1); +} + +static void +kill_wait() +{ + kill(_x_pid, SIGTERM); +} + +int +main (int argc __UNUSED__, char **argv __UNUSED__) +{ + int status = 0; + char *pid; + struct sigaction action; + + pid_t rpid; + pid = getenv("ENTRANCE_XPID"); + if (!pid) return -1; + _x_pid = atoi(pid); + + action.sa_sigaction = _entrance_wait_action; + action.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGCHLD, &action, NULL); + sigaction(SIGQUIT, &action, NULL); + sigaction(SIGTERM, &action, NULL); + sigaction(SIGKILL, &action, NULL); + sigaction(SIGINT, &action, NULL); + sigaction(SIGHUP, &action, NULL); + sigaction(SIGPIPE, &action, NULL); + sigaction(SIGALRM, &action, NULL); + + while ((rpid = wait(&status)) != _x_pid) + { + if (rpid == -1) + { + if ((errno == ECHILD) || (errno == EINVAL)) + break; + } + } + if (_x_pid == rpid) + { + if (WIFEXITED(status) && WEXITSTATUS(status)) + setenv("ENTRANCE_QUIT", "1", 1); + execlp("entrance", "entrance", "--nodaemon", NULL); + } + return -1; +} + diff --git a/src/daemon/entrance_xserver.c b/src/daemon/entrance_xserver.c new file mode 100644 index 0000000..c472e90 --- /dev/null +++ b/src/daemon/entrance_xserver.c @@ -0,0 +1,139 @@ +#include "entrance.h" +#include +#include + +typedef struct Entrance_Xserver_ +{ + const char *dname; + Entrance_X_Cb start; +} Entrance_Xserver; + +Entrance_Xserver *_xserver; +Ecore_Event_Handler *_handler_start; + +/* + * man Xserver + * SIGUSR1 This signal is used quite differently from either of the + * above. When the server starts, it checks to see if it has inherite + * SIGUSR1 as SIG_IGN instead of the usual SIG_DFL. In this case, the server + * sends a SIGUSR1 to its parent process after it has set up the various + * connection schemes. Xdm uses this feature to recognize when connecting to + * the server is possible. + * */ +static void +_env_set(const char *dname) +{ + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), "DISPLAY=%s", dname); + putenv(strdup(buf)); +} + +static int +_xserver_start() +{ + char *buf = NULL; + char **args = NULL; + pid_t pid; + + pid = fork(); + if (!pid) + { + char *token; + int num_token = 0; + entrance_close_log(); + signal(SIGTTIN, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + signal(SIGUSR1, SIG_IGN); + + if (!(buf = strdup(entrance_config->command.xinit_args))) + goto xserver_error; + token = strtok(buf, " "); + while(token) + { + ++num_token; + token = strtok(NULL, " "); + } + if (buf) free(buf); + if (num_token) + { + int i; + if (!(buf = strdup(entrance_config->command.xinit_args))) + goto xserver_error; + if (!(args = calloc(num_token + 2, sizeof(char *)))) + { + if (buf) free(buf); + goto xserver_error; + } + args[0] = (char *)entrance_config->command.xinit_path; + token = strtok(buf, " "); + ++num_token; + for(i = 1; i < num_token; ++i) + { + if (token) + args[i] = token; + token = strtok(NULL, " "); + } + args[num_token] = NULL; + } + else + { + if (!(args = calloc(2, sizeof(char*)))) + goto xserver_error; + args[0] = (char *)entrance_config->command.xinit_path; + args[1] = NULL; + } + execv(args[0], args); + if (buf) free(buf); + if (args) free(args); + fprintf(stderr, PACKAGE": Couldn't launch Xserver ...\n"); + } + return pid; +xserver_error: + _exit(EXIT_FAILURE); +} + +static Eina_Bool +_xserver_started(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__) +{ + fprintf(stderr, PACKAGE": xserver started\n"); + _env_set(_xserver->dname); + _xserver->start(_xserver->dname); + return ECORE_CALLBACK_PASS_ON; +} + +int +entrance_xserver_init(Entrance_X_Cb start, const char *dname) +{ + int pid; + char buf[64]; + sigset_t newset; + sigemptyset(&newset); + + fprintf(stderr, PACKAGE": xserver init\n"); + _xserver = calloc(1, sizeof(Entrance_Xserver)); + _xserver->dname = eina_stringshare_add(dname); + _xserver->start = start; + pid = _xserver_start(); + snprintf(buf, sizeof(buf), "ENTRANCE_XPID=%d", pid); + putenv(strdup(buf)); + _handler_start = ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER, + _xserver_started, + NULL); + return pid; +} + +void +entrance_xserver_end() +{ + fprintf(stderr, PACKAGE": xserver end\n"); + unsetenv("ENTRANCE_XPID"); +} + +void +entrance_xserver_shutdown() +{ + eina_stringshare_del(_xserver->dname); + free(_xserver); + ecore_event_handler_del(_handler_start); +} + diff --git a/src/daemon/entrance_xserver.h b/src/daemon/entrance_xserver.h new file mode 100644 index 0000000..5d075ad --- /dev/null +++ b/src/daemon/entrance_xserver.h @@ -0,0 +1,8 @@ +#ifndef ENTRANCE_XLIB_H_ +#define ENTRANCE_XLIB_H_ +typedef int (*Entrance_X_Cb)(const char *data); +int entrance_xserver_init(Entrance_X_Cb start, const char *dname); +void entrance_xserver_wait(); +void entrance_xserver_end(); +void entrance_xserver_shutdown(); +#endif /* ENTRANCE_XLIB_H_ */ diff --git a/src/event/entrance_event.c b/src/event/entrance_event.c new file mode 100644 index 0000000..25aeb74 --- /dev/null +++ b/src/event/entrance_event.c @@ -0,0 +1,230 @@ +#include +#include +#include "entrance_event.h" + +#define ENTRANCE_EVENT_AUTH_NAME "EntranceEventAuth" +#define ENTRANCE_EVENT_MAXTRIES_NAME "EntranceEventMaxtries" +#define ENTRANCE_EVENT_XSESSIONS_NAME "EntranceEventSession" +#define ENTRANCE_EVENT_STATUS_NAME "EntranceEventStatus" +#define ENTRANCE_EVENT_USERS_NAME "EntranceEventUsers" +#define ENTRANCE_EVENT_ACTIONS_NAME "EntranceEventActions" +#define ENTRANCE_EVENT_ACTION_NAME "EntranceEventAction" + +static Eina_Bool _entrance_event_type_set(const char *type, void *data, Eina_Bool unknow); +static const char *_entrance_event_type_get(const void *data, Eina_Bool *unknow); + +static Eet_Data_Descriptor *_entrance_event_auth_dd(); +static Eet_Data_Descriptor *_entrance_event_status_dd(); +static Eet_Data_Descriptor *_entrance_event_xsessions_dd(); + +static Eina_Bool +_entrance_event_type_set(const char *type, void *data, Eina_Bool unknow) +{ + Entrance_Event_Type *ev = data; + if (unknow) + return EINA_FALSE; + if (!strcmp(type, ENTRANCE_EVENT_AUTH_NAME)) + *ev = ENTRANCE_EVENT_AUTH; + else if (!strcmp(type, ENTRANCE_EVENT_MAXTRIES_NAME)) + *ev = ENTRANCE_EVENT_MAXTRIES; + else if (!strcmp(type, ENTRANCE_EVENT_STATUS_NAME)) + *ev = ENTRANCE_EVENT_STATUS; + else if (!strcmp(type, ENTRANCE_EVENT_XSESSIONS_NAME)) + *ev = ENTRANCE_EVENT_XSESSIONS; + else if (!strcmp(type, ENTRANCE_EVENT_USERS_NAME)) + *ev = ENTRANCE_EVENT_USERS; + else if (!strcmp(type, ENTRANCE_EVENT_ACTIONS_NAME)) + *ev = ENTRANCE_EVENT_ACTIONS; + else if (!strcmp(type, ENTRANCE_EVENT_ACTION_NAME)) + *ev = ENTRANCE_EVENT_ACTION; + else + { + printf("error on type set\n"); + *ev = ENTRANCE_EVENT_UNKNOWN; + return EINA_FALSE; + } + return EINA_TRUE; +} + +static const char * +_entrance_event_type_get(const void *data, Eina_Bool *unknow) +{ + const Entrance_Event_Type *ev = data; + if (*ev == ENTRANCE_EVENT_AUTH) + return ENTRANCE_EVENT_AUTH_NAME; + else if (*ev == ENTRANCE_EVENT_MAXTRIES) + return ENTRANCE_EVENT_MAXTRIES_NAME; + else if (*ev == ENTRANCE_EVENT_STATUS) + return ENTRANCE_EVENT_STATUS_NAME; + else if (*ev == ENTRANCE_EVENT_XSESSIONS) + return ENTRANCE_EVENT_XSESSIONS_NAME; + else if (*ev == ENTRANCE_EVENT_USERS) + return ENTRANCE_EVENT_USERS_NAME; + else if (*ev == ENTRANCE_EVENT_ACTIONS) + return ENTRANCE_EVENT_ACTIONS_NAME; + else if (*ev == ENTRANCE_EVENT_ACTION) + return ENTRANCE_EVENT_ACTION_NAME; + if (*unknow) + { + printf("error on type get\n"); + *unknow = EINA_TRUE; + } + return NULL; +} + +static Eet_Data_Descriptor * +_entrance_event_xsessions_dd() +{ + Eet_Data_Descriptor_Class eddc, eddcl; + Eet_Data_Descriptor *edd, *eddl; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Entrance_Xsession); + edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Xsession, "name", + name, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Xsession, "icon", + icon, EET_T_STRING); + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddcl, Entrance_Xsessions_Event); + eddl = eet_data_descriptor_stream_new(&eddcl); + EET_DATA_DESCRIPTOR_ADD_LIST(eddl, Entrance_Xsessions_Event, "xsessions", xsessions, edd); + return eddl; +} + +static Eet_Data_Descriptor * +_entrance_event_auth_dd() +{ + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor_Class eddc; + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Entrance_Auth_Event); + edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Auth_Event, "login", + login, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Auth_Event, "password", + password, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Auth_Event, "session", + session, EET_T_STRING); + return edd; + +} + +static Eet_Data_Descriptor * +_entrance_event_maxtries_dd() +{ + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor_Class eddc; + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Entrance_Maxtries_Event); + edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Maxtries_Event, "maxtries", + maxtries, EET_T_UCHAR); + return edd; +} + +static Eet_Data_Descriptor * +_entrance_event_status_dd() +{ + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor_Class eddc; + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Entrance_Status_Event); + edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Status_Event, "granted", + granted, EET_T_UCHAR); + return edd; + +} + +static Eet_Data_Descriptor * +_entrance_event_users_dd() +{ + Eet_Data_Descriptor *edd, *eddl; + Eet_Data_Descriptor_Class eddc, eddcl; + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Entrance_User); + edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_User, "login", + login, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_User, "image", + image, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_User, "lsess", + lsess, EET_T_STRING); + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddcl, Entrance_Users_Event); + eddl = eet_data_descriptor_stream_new(&eddcl); + EET_DATA_DESCRIPTOR_ADD_LIST(eddl, Entrance_Users_Event, "users", users, edd); + return eddl; +} + +static Eet_Data_Descriptor * +_entrance_event_actions_dd() +{ + Eet_Data_Descriptor *edd, *eddl; + Eet_Data_Descriptor_Class eddc, eddcl; + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Entrance_Action); + edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Action, "label", + label, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Action, "id", + id, EET_T_INT); + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddcl, Entrance_Actions_Event); + eddl = eet_data_descriptor_stream_new(&eddcl); + EET_DATA_DESCRIPTOR_ADD_LIST(eddl, Entrance_Actions_Event, "actions", actions, edd); + return eddl; +} + +static Eet_Data_Descriptor * +_entrance_event_action_dd() +{ + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor_Class eddc; + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Entrance_Status_Event); + edd = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Entrance_Action_Event, "action", + action, EET_T_INT); + return edd; +} + +static Eet_Data_Descriptor * +_entrance_event_new() +{ + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor *unified; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Entrance_Event); + edd = eet_data_descriptor_stream_new(&eddc); + + eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION; + eddc.func.type_get = _entrance_event_type_get; + eddc.func.type_set = _entrance_event_type_set; + unified = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, ENTRANCE_EVENT_XSESSIONS_NAME, _entrance_event_xsessions_dd()); + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, ENTRANCE_EVENT_AUTH_NAME, _entrance_event_auth_dd()); + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, ENTRANCE_EVENT_MAXTRIES_NAME, _entrance_event_maxtries_dd()); + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, ENTRANCE_EVENT_STATUS_NAME, _entrance_event_status_dd()); + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, ENTRANCE_EVENT_USERS_NAME, _entrance_event_users_dd()); + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, ENTRANCE_EVENT_ACTIONS_NAME, _entrance_event_actions_dd()); + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, ENTRANCE_EVENT_ACTION_NAME, _entrance_event_action_dd()); + + EET_DATA_DESCRIPTOR_ADD_UNION(edd, Entrance_Event, "event", event, type, unified); + return edd; +} + +void * +entrance_event_encode(Entrance_Event *eev, int *size) +{ + Eet_Data_Descriptor *edd; + + edd = _entrance_event_new(); + + return eet_data_descriptor_encode(edd, eev, size); +} + +Entrance_Event * +entrance_event_decode(void *data, int size) +{ + Eet_Data_Descriptor *edd; + + edd = _entrance_event_new(); + + return eet_data_descriptor_decode(edd, data, size); +} + diff --git a/src/event/entrance_event.h b/src/event/entrance_event.h new file mode 100644 index 0000000..510e9da --- /dev/null +++ b/src/event/entrance_event.h @@ -0,0 +1,91 @@ +#ifndef ENTRANCE_EVENT_ +#define ENTRANCE_EVENT_ + +typedef enum Entrance_Event_Type_ +{ + ENTRANCE_EVENT_UNKNOWN, + ENTRANCE_EVENT_AUTH, + ENTRANCE_EVENT_STATUS, + ENTRANCE_EVENT_XSESSIONS, + ENTRANCE_EVENT_USERS, + ENTRANCE_EVENT_ACTIONS, + ENTRANCE_EVENT_ACTION, + ENTRANCE_EVENT_MAXTRIES +} Entrance_Event_Type; + +typedef struct Entrance_Xsession_ +{ + const char *name; + const char *command; + const char *icon; +} Entrance_Xsession; + +typedef struct Entrance_Xsessions_Event_ +{ + Eina_List *xsessions; +} Entrance_Xsessions_Event; + +typedef struct Entrance_Auth_Event_ +{ + const char *login; + const char *password; + const char *session; +} Entrance_Auth_Event; + +typedef struct Entrance_Maxtries_Event_ +{ + Eina_Bool maxtries; +} Entrance_Maxtries_Event; + +typedef struct Entrance_Status_Event_ +{ + Eina_Bool granted; +} Entrance_Status_Event; + +typedef struct Entrance_Action_Event_ +{ + int action; +} Entrance_Action_Event; + +typedef struct Entrance_User_ +{ + const char *login; + const char *image; + const char *lsess; +} Entrance_User; + + +typedef struct Entrance_Users_Event_ +{ + Eina_List *users; +} Entrance_Users_Event; + +typedef struct Entrance_Action_ +{ + int id; + const char *label; +} Entrance_Action; + +typedef struct Entrance_Actions_Event_ +{ + Eina_List *actions; +} Entrance_Actions_Event; + +typedef struct Entrance_Event_ +{ + Entrance_Event_Type type; + union + { + Entrance_Xsessions_Event xsessions; + Entrance_Auth_Event auth; + Entrance_Maxtries_Event maxtries; + Entrance_Status_Event status; + Entrance_Users_Event users; + Entrance_Actions_Event actions; + Entrance_Action_Event action; + } event; +} Entrance_Event; + +void *entrance_event_encode(Entrance_Event *ev, int *size); +Entrance_Event *entrance_event_decode(void *data, int size); +#endif /* ENTRANCE_EVENT_ */