3 Create a suitable configuration for kdm taking previous xdm/kdm
4 installations into account
6 Copyright (C) 2001-2005 Oswald Buddenhagen <ossi@kde.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 #include <X11/Xresource.h>
30 #include <sys/types.h>
46 #include <sys/param.h>
54 #define RCVERSTR stringify(RCVERMAJOR) "." stringify(RCVERMINOR)
56 static int old_scripts
, no_old_scripts
, old_confs
, no_old
,
57 no_backup
, no_in_notice
, use_destdir
, mixed_scripts
;
58 static const char *newdir
= KDMCONF
, *facesrc
= KDMDATA
"/pics/users",
59 *oldxdm
, *oldkde
, *oldkdepfx
;
64 typedef struct StrList
{
69 typedef struct StrMap
{
71 const char *key
, *value
;
80 if (!(ptr
= malloc( sz
))) {
81 fprintf( stderr
, "Out of memory\n" );
92 if (!(ptr
= calloc( 1, sz
))) {
93 fprintf( stderr
, "Out of memory\n" );
100 mrealloc( void *optr
, size_t sz
)
104 if (!(ptr
= realloc( optr
, sz
))) {
105 fprintf( stderr
, "Out of memory\n" );
112 mstrdup( const char *optr
)
118 if (!(ptr
= strdup( optr
))) {
119 fprintf( stderr
, "Out of memory\n" );
127 #define STATIC static
132 int clen
, blen
, tlen
;
136 outCh_OCA( void *bp
, char c
)
138 OCABuf
*ocabp
= (OCABuf
*)bp
;
141 if (ocabp
->clen
>= ocabp
->blen
) {
142 ocabp
->blen
= ocabp
->blen
* 3 / 2 + 100;
143 ocabp
->buf
= mrealloc( ocabp
->buf
, ocabp
->blen
);
145 ocabp
->buf
[ocabp
->clen
++] = c
;
149 VASPrintf( char **strp
, const char *fmt
, va_list args
)
151 OCABuf ocab
= { 0, 0, 0, -1 };
153 doPrint( outCh_OCA
, &ocab
, fmt
, args
);
154 outCh_OCA( &ocab
, 0 );
155 *strp
= realloc( ocab
.buf
, ocab
.clen
);
162 ASPrintf( char **strp
, const char *fmt
, ... )
167 va_start( args
, fmt
);
168 len
= VASPrintf( strp
, fmt
, args
);
174 strCat( char **strp
, const char *fmt
, ... )
180 va_start( args
, fmt
);
181 el
= VASPrintf( &str
, fmt
, args
);
184 int ol
= strlen( *strp
);
185 tstr
= mmalloc( el
+ ol
+ 1 );
186 memcpy( tstr
, *strp
, ol
);
187 memcpy( tstr
+ ol
, str
, el
+ 1 );
198 typedef struct File
{
199 char *buf
, *eof
, *cur
;
200 #if defined(HAVE_MMAP) && defined(WANT_CLOSE)
206 readFile( File
*file
, const char *fn
)
211 if ((fd
= open( fn
, O_RDONLY
)) < 0)
214 flen
= lseek( fd
, 0, SEEK_END
);
217 file
->ismapped
= False
;
219 file
->buf
= mmap( 0, flen
+ 1, PROT_READ
| PROT_WRITE
, MAP_PRIVATE
, fd
, 0 );
222 file
->ismapped
= True
;
229 file
->buf
= mmalloc( flen
+ 1 );
230 lseek( fd
, 0, SEEK_SET
);
231 if (read( fd
, file
->buf
, flen
) != flen
) {
234 fprintf( stderr
, "Cannot read file\n" );
235 return False
; /* maybe better abort? */
238 file
->eof
= file
->buf
+ flen
;
245 freeBuf( File
*file
)
249 munmap( file
->buf
, file
->eof
- file
->buf
);
257 isTrue( const char *val
)
259 return !strcmp( val
, "true" ) ||
260 !strcmp( val
, "yes" ) ||
261 !strcmp( val
, "on" ) ||
267 mkpdirs( const char *name
, const char *what
)
269 char *mfname
= mstrdup( name
);
273 for (i
= 1; mfname
[i
]; i
++)
274 if (mfname
[i
] == '/') {
276 if (stat( mfname
, &st
)) {
277 if (mkdir( mfname
, 0755 )) {
278 fprintf( stderr
, "Cannot create parent %s of %s directory %s: %s\n",
279 mfname
, what
, name
, strerror( errno
) );
283 chmod( mfname
, 0755 );
292 mkdirp( const char *name
, int mode
, const char *what
, int existok
)
296 if (stat( name
, &st
)) {
297 mkpdirs( name
, what
);
298 if (mkdir( name
, mode
)) {
299 fprintf( stderr
, "Cannot create %s directory %s: %s\n",
300 what
, name
, strerror( errno
) );
311 displace( const char *fn
)
314 char bn
[PATH_MAX
+ 4];
315 sprintf( bn
, "%s.bak", fn
); /* won't overflow if only existing paths are passed */
323 locate( const char *exe
)
326 char *path
, *pathe
, *name
, *thenam
, nambuf
[PATH_MAX
+1];
328 if (!(path
= getenv( "PATH" )))
331 name
= nambuf
+ PATH_MAX
- len
;
332 memcpy( name
, exe
, len
+ 1 );
335 if (!(pathe
= strchr( path
, ':' )))
336 pathe
= path
+ strlen( path
);
338 if (len
&& !(len
== 1 && *path
== '.')) {
340 if (thenam
>= nambuf
) {
341 memcpy( thenam
, path
, len
);
342 if (!access( thenam
, X_OK
))
343 return mstrdup( thenam
);
347 } while (*path
++ != '\0');
353 * target data to be written to kdmrc
356 typedef struct Entry
{
364 typedef struct Section
{
365 struct Section
*next
;
372 static Section
*config
; /* the kdmrc data to be written */
375 * Specification of the (currently possible) kdmrc entries
381 void (*func
)( Entry
*ce
, Section
*cs
);
385 typedef struct Sect
{
391 static Sect
*findSect( const char *name
);
392 static Ent
*findEnt( Sect
*sect
, const char *key
);
395 * Functions to manipulate the current kdmrc data
399 getFqVal( const char *sect
, const char *key
, const char *defval
)
404 for (cs
= config
; cs
; cs
= cs
->next
)
405 if (!strcmp( cs
->name
, sect
)) {
406 for (ce
= cs
->ents
; ce
; ce
= ce
->next
)
407 if (!strcmp( ce
->spec
->key
, key
)) {
408 if (ce
->active
&& ce
->written
)
418 putFqVal( const char *sect
, const char *key
, const char *value
)
426 for (csp
= &config
; (cs
= *csp
); csp
= &(cs
->next
))
427 if (!strcmp( sect
, cs
->name
))
429 cs
= mcalloc( sizeof(*cs
) );
430 ASPrintf( (char **)&cs
->name
, "%s", sect
);
431 cs
->spec
= findSect( sect
);
435 for (cep
= &(cs
->ents
); (ce
= *cep
); cep
= &(ce
->next
))
436 if (!strcmp( key
, ce
->spec
->key
))
438 ce
= mcalloc( sizeof(*ce
) );
439 ce
->spec
= findEnt( cs
->spec
, key
);
442 ASPrintf( (char **)&ce
->value
, "%s", value
);
443 ce
->written
= ce
->active
= True
;
446 static const char *csect
;
448 #define setSect(se) csect = se
451 putVal( const char *key
, const char *value
)
453 putFqVal( csect
, key
, value
);
458 writeKdmrc( FILE *f
)
462 StrList
*sl
= 0, *sp
;
465 putFqVal( "General", "ConfigVersion", RCVERSTR
);
466 for (cs
= config
; cs
; cs
= cs
->next
) {
467 fprintf( f
, "%s[%s]\n",
468 cs
->comment
? cs
->comment
: "\n", cs
->name
);
469 for (ce
= cs
->ents
; ce
; ce
= ce
->next
) {
470 if (ce
->spec
->comment
) {
471 cmt
= ce
->spec
->comment
;
472 for (sp
= sl
; sp
; sp
= sp
->next
)
473 if (sp
->str
== cmt
) {
474 cmt
= "# See above\n";
477 if (!(sp
= malloc( sizeof(*sp
) )))
478 fprintf( stderr
, "Warning: Out of memory\n" );
481 sp
->next
= sl
; sl
= sp
;
486 fprintf( f
, "%s%s%s=%s\n",
487 cmt
, ce
->active
? "" : "#", ce
->spec
->key
, ce
->value
);
497 static const char def_xaccess
[] =
498 "# Xaccess - Access control file for XDMCP connections\n"
500 "# To control Direct and Broadcast access:\n"
504 "# To control Indirect queries:\n"
506 "# pattern list of hostnames and/or macros ...\n"
508 "# To use the chooser:\n"
510 "# pattern CHOOSER BROADCAST\n"
514 "# pattern CHOOSER list of hostnames and/or macros ...\n"
516 "# To define macros:\n"
518 "# %name list of hosts ...\n"
520 "# The first form tells xdm which displays to respond to itself.\n"
521 "# The second form tells xdm to forward indirect queries from hosts matching\n"
522 "# the specified pattern to the indicated list of hosts.\n"
523 "# The third form tells xdm to handle indirect queries using the chooser;\n"
524 "# the chooser is directed to send its own queries out via the broadcast\n"
525 "# address and display the results on the terminal.\n"
526 "# The fourth form is similar to the third, except instead of using the\n"
527 "# broadcast address, it sends DirectQuerys to each of the hosts in the list\n"
529 "# In all cases, xdm uses the first entry which matches the terminal;\n"
530 "# for IndirectQuery messages only entries with right hand sides can\n"
531 "# match, for Direct and Broadcast Query messages, only entries without\n"
532 "# right hand sides can match.\n"
535 "* #any host can get a login window\n"
538 "# To hardwire a specific terminal to a specific host, you can\n"
539 "# leave the terminal sending indirect queries to this host, and\n"
540 "# use an entry of the form:\n"
543 "#terminal-a host-a\n"
547 "# The nicest way to run the chooser is to just ask it to broadcast\n"
548 "# requests to the network - that way new hosts show up automatically.\n"
549 "# Sometimes, however, the chooser cannot figure out how to broadcast,\n"
550 "# so this may not work in all environments.\n"
553 "* CHOOSER BROADCAST #any indirect host can get a chooser\n"
556 "# If you would prefer to configure the set of hosts each terminal sees,\n"
557 "# then just uncomment these lines (and comment the CHOOSER line above)\n"
558 "# and edit the %hostlist line as appropriate\n"
561 "#%hostlist host-a host-b\n"
563 "#* CHOOSER %hostlist #\n";
567 static const char def_willing
[] =
569 "# The output of this script is displayed in the chooser window\n"
570 "# (instead of \"Willing to manage\").\n"
572 "load=`uptime|sed -e 's/^.*load[^0-9]*//'`\n"
573 "nrusers=`who|cut -c 1-8|sort -u|wc -l|sed 's/^[ \t]*//'`\n"
574 "s=\"\"; [ \"$nrusers\" != 1 ] && s=s\n"
576 "echo \"${nrusers} user${s}, load: ${load}\"\n";
579 static const char def_setup
[] =
581 "# Xsetup - run as root before the login dialog appears\n"
583 "#xconsole -geometry 480x130-0-0 -notify -verbose -fn fixed -exitOnFail -file /dev/xconsole &\n";
585 static const char def_startup
[] =
587 "# Xstartup - run as root before session starts\n"
589 "# By convention, both xconsole and xterm -C check that the\n"
590 "# console is owned by the invoking user and is readable before attaching\n"
591 "# the console output. This way a random user can invoke xterm -C without\n"
592 "# causing serious grief; still, it can cause havoc, so xconsole is started\n"
593 "# by Xsetup usually.\n"
594 "# This is not required if you use PAM with the pam_console module.\n"
596 "#chown $USER /dev/console\n"
599 "# We create a pseudodevice for finger. (host:0 becomes xdm/host_0)\n"
600 "# Without it, finger errors out with \"Cannot stat /dev/host:0\".\n"
602 "#devname=`echo $DISPLAY | cut -c1-8`\n"
603 "#if [ ! -d /dev/xdm ]; then\n"
605 "# chmod 755 /dev/xdm\n"
607 "#touch /dev/xdm/$devname\n"
608 "#chmod 644 /dev/xdm/$devname\n"
609 "#exec sessreg -a -l xdm/$devname -h \"`echo $DISPLAY | cut -d: -f1`\""
611 "#exec sessreg -a -l $DISPLAY -h \"`echo $DISPLAY | cut -d: -f1`\""
613 " -x " KDMCONF
"/Xservers"
617 "\n# NOTE: The session is aborted if the last command returns non-zero.\n";
619 static const char def_reset
[] =
621 "# Xreset - run as root after session exits\n"
623 "# Reassign ownership of the console to root, this should disallow\n"
624 "# assignment of console output to any random users's xterm. See Xstartup.\n"
626 "#chown root /dev/console\n"
627 "#chmod 622 /dev/console\n"
630 "#devname=`echo $DISPLAY | cut -c1-8`\n"
631 "#exec sessreg -d -l xdm/$devname -h \"`echo $DISPLAY | cut -d: -f1`\""
633 "#exec sessreg -d -l $DISPLAY -h \"`echo $DISPLAY | cut -d: -f1`\""
635 " -x " KDMCONF
"/Xservers"
640 static const char def_session1
[] =
642 "# Xsession - run as user\n"
646 "# Note that the respective logout scripts are not sourced.\n"
649 " [ -z \"$BASH\" ] && exec $SHELL $0 \"$@\"\n"
651 " [ -f /etc/profile ] && . /etc/profile\n"
652 " if [ -f $HOME/.bash_profile ]; then\n"
653 " . $HOME/.bash_profile\n"
654 " elif [ -f $HOME/.bash_login ]; then\n"
655 " . $HOME/.bash_login\n"
656 " elif [ -f $HOME/.profile ]; then\n"
657 " . $HOME/.profile\n"
661 " [ -z \"$ZSH_NAME\" ] && exec $SHELL $0 \"$@\"\n"
663 " [ -d /etc/zsh ] && zdir=/etc/zsh || zdir=/etc\n"
664 " zhome=${ZDOTDIR:-$HOME}\n"
665 " # zshenv is always sourced automatically.\n"
666 " [ -f $zdir/zprofile ] && . $zdir/zprofile\n"
667 " [ -f $zhome/.zprofile ] && . $zhome/.zprofile\n"
668 " [ -f $zdir/zlogin ] && . $zdir/zlogin\n"
669 " [ -f $zhome/.zlogin ] && . $zhome/.zlogin\n"
672 " # [t]cshrc is always sourced automatically.\n"
673 " # Note that sourcing csh.login after .cshrc is non-standard.\n"
675 static const char def_session2
[] =
677 " $SHELL -c \"if (-f /etc/csh.login) source /etc/csh.login; if (-f ~/.login) source ~/.login; /bin/sh -c export -p >! $xsess_tmp\"\n"
679 " rm -f $xsess_tmp\n"
681 " *) # Plain sh, ksh, and anything we do not know.\n"
682 " [ -f /etc/profile ] && . /etc/profile\n"
683 " [ -f $HOME/.profile ] && . $HOME/.profile\n"
687 "[ -f /etc/xprofile ] && . /etc/xprofile\n"
688 "[ -f $HOME/.xprofile ] && . $HOME/.xprofile\n"
692 " exec xmessage -center -buttons OK:0 -default OK \"Sorry, $DESKTOP_SESSION is no valid session.\"\n"
695 " exec xterm -geometry 80x24-0-0\n"
698 " exec $HOME/.xsession\n"
701 " exec " KDE_BINDIR
"/startkde\n"
704 " eval exec \"$session\"\n"
707 "exec xmessage -center -buttons OK:0 -default OK \"Sorry, cannot execute $session. Check $DESKTOP_SESSION.desktop.\"\n";
709 static const char def_background
[] =
711 "BackgroundMode=Flat\n"
713 "BlendMode=NoBlending\n"
714 "ChangeInterval=60\n"
716 "Color2=192,192,192\n"
717 "CurrentWallpaper=0\n"
719 "MinOptimizationDepth=1\n"
720 "MultiWallpaperMode=NoMulti\n"
723 "ReverseBlending=false\n"
725 "Wallpaper=default_blue.jpg\n"
727 "WallpaperMode=Scaled\n";
729 /* Create a new file in KDMCONF */
731 createFile( const char *fn
, int mode
)
736 ASPrintf( &nname
, "%s/%s", newdir
, fn
);
738 if (!(f
= fopen( nname
, "w" ))) {
739 fprintf( stderr
, "Cannot create %s\n", nname
);
742 chmod( nname
, mode
);
747 /* Create a copy of a file under KDMCONF and fill it */
749 writeCopy( const char *fn
, int mode
, time_t stamp
, const char *buf
, size_t len
)
755 ASPrintf( &nname
, "%s/%s", newdir
, fn
);
757 mkpdirs( nname
, "target" );
758 if ((fd
= creat( nname
, mode
)) < 0) {
759 fprintf( stderr
, "Cannot create %s\n", nname
);
762 write( fd
, buf
, len
);
765 utim
.actime
= utim
.modtime
= stamp
;
766 utime( nname
, &utim
);
772 /* returns static array! */
774 reSect( const char *sec
, const char *name
)
776 static char sname
[64];
779 if ((p
= strrchr( sec
, '-' ))) {
780 sprintf( sname
, "%.*s-%s", (int)(p
- sec
), sec
, name
);
787 inNewDir( const char *name
)
789 return !memcmp( name
, KDMCONF
"/", sizeof(KDMCONF
) );
793 getMapping( StrMap
*sm
, const char *k
)
795 for (; sm
; sm
= sm
->next
)
796 if (!strcmp( sm
->key
, k
))
802 addMapping( StrMap
**sm
, const char *k
, const char *v
)
804 for (; *sm
; sm
= &(*sm
)->next
)
805 if (!strcmp( (*sm
)->key
, k
))
807 *sm
= mcalloc( sizeof(**sm
) );
808 ASPrintf( (char **)&(*sm
)->key
, "%s", k
);
809 ASPrintf( (char **)&(*sm
)->value
, "%s", v
);
813 inList( StrList
*sp
, const char *s
)
815 for (; sp
; sp
= sp
->next
)
816 if (!strcmp( sp
->str
, s
))
822 addStr( StrList
**sp
, const char *s
)
824 for (; *sp
; sp
= &(*sp
)->next
)
825 if (!strcmp( (*sp
)->str
, s
))
827 *sp
= mcalloc( sizeof(**sp
) );
828 ASPrintf( (char **)&(*sp
)->str
, "%s", s
);
832 splitList( const char *str
)
834 StrList
*sp
, **spp
= &sp
;
839 *spp
= mcalloc( sizeof(**spp
) );
840 if (!(e
= strchr( str
, ',' )))
842 ASPrintf( (char **)&(*spp
)->str
, "%.*s", (int)(e
- str
), str
);
846 (*spp
)->str
= mstrdup( str
);
852 joinList( StrList
*sp
)
856 return mstrdup( "" );
857 s
= mstrdup( sp
->str
);
862 strCat( &s
, ",%s", sp
->str
);
867 StrList
*aflist
, *uflist
, *eflist
, *cflist
, *lflist
;
869 /* file is part of new config */
871 addedFile( const char *fn
)
873 addStr( &aflist
, fn
);
876 /* file from old config was parsed */
878 usedFile( const char *fn
)
880 addStr( &uflist
, fn
);
883 /* file from old config was copied with slight modifications */
885 editedFile( const char *fn
)
887 addStr( &eflist
, fn
);
890 /* file from old config was copied verbatim */
892 copiedFile( const char *fn
)
894 addStr( &cflist
, fn
);
897 /* file from old config is still being used */
899 linkedFile( const char *fn
)
901 addStr( &lflist
, fn
);
905 * NOTE: This code will not correctly deal with default files colliding
906 * with pre-existing files. This should be OK, as for each class of files
907 * (scripts, configs) only one origin is used, and conflicts between classes
908 * are rather unlikely.
911 /* Make a possibly modified copy of a file under KDMCONF */
913 copyFile( Entry
*ce
, int mode
, int (*proc
)( File
* ) )
923 if ((nname
= (char *)getMapping( cfmap
, ce
->value
))) {
924 rt
= inList( aflist
, nname
);
928 int olen
= strlen( oldkde
);
929 if (!memcmp( ce
->value
, oldkde
, olen
)) {
930 if (!memcmp( ce
->value
+ olen
, "/kdm/", 5 )) {
931 tptr
= ce
->value
+ olen
+ 4;
934 if (ce
->value
[olen
] == '/') {
935 tptr
= ce
->value
+ olen
;
941 int olen
= strlen( oldxdm
);
942 if (!memcmp( ce
->value
, oldxdm
, olen
) && ce
->value
[olen
] == '/') {
943 tptr
= ce
->value
+ olen
;
947 if (!(tptr
= strrchr( ce
->value
, '/' ))) {
948 fprintf( stderr
, "Warning: cannot cope with relative path %s\n", ce
->value
);
952 ASPrintf( &nname
, KDMCONF
"%s", tptr
);
953 if (inList( aflist
, nname
)) {
957 ASPrintf( &nname
, KDMCONF
"%s-%d", tptr
, ++cnt
);
958 } while (inList( aflist
, nname
));
960 addMapping( &cfmap
, ce
->value
, nname
);
961 if (!readFile( &file
, ce
->value
)) {
962 fprintf( stderr
, "Warning: cannot copy file %s\n", ce
->value
);
965 if (!proc
|| !proc( &file
)) {
966 if (!use_destdir
&& !strcmp( ce
->value
, nname
))
970 stat( ce
->value
, &st
);
971 writeCopy( nname
+ sizeof(KDMCONF
), mode
, st
.st_mtime
,
972 file
.buf
, file
.eof
- file
.buf
);
973 copiedFile( ce
->value
);
976 writeCopy( nname
+ sizeof(KDMCONF
), mode
, 0,
977 file
.buf
, file
.eof
- file
.buf
);
978 editedFile( ce
->value
);
980 if (strcmp( ce
->value
, nname
) && inNewDir( ce
->value
) && !use_destdir
)
981 displace( ce
->value
);
991 doLinkFile( const char *name
)
995 if (inList( aflist
, name
))
997 if (!readFile( &file
, name
)) {
998 fprintf( stderr
, "Warning: cannot read file %s\n", name
);
1001 if (inNewDir( name
) && use_destdir
) {
1004 writeCopy( name
+ sizeof(KDMCONF
), st
.st_mode
, st
.st_mtime
,
1005 file
.buf
, file
.eof
- file
.buf
);
1012 /* Incorporate an existing file */
1014 linkFile( Entry
*ce
)
1016 if (ce
->written
&& *ce
->value
)
1017 doLinkFile( ce
->value
);
1020 /* Create a new file in KDMCONF and fill it */
1022 writeFile( const char *tname
, int mode
, const char *cont
)
1024 FILE *f
= createFile( tname
+ sizeof(KDMCONF
), mode
);
1032 handleBgCfg( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1034 if (!ce
->active
) /* can be only the X-*-Greeter one */
1035 writeFile( def_BackgroundCfg
, 0644, def_background
);
1036 #if 0 /* risk of kcontrol clobbering the original file */
1041 if (!copyFile( ce
, 0644, 0 )) {
1042 if (!strcmp( cs
->name
, "X-*-Greeter" ))
1043 writeFile( def_BackgroundCfg
, 0644, def_background
);
1052 memMem( char *mem
, int lmem
, const char *smem
, int lsmem
)
1054 for (; lmem
>= lsmem
; mem
++, lmem
--)
1055 if (!memcmp( mem
, smem
, lsmem
))
1060 static int maxTTY
, TTYmask
;
1071 if (readFile( &it
, "/etc/inittab" )) {
1072 usedFile( "/etc/inittab" );
1073 for (p
= it
.buf
; p
< it
.eof
; p
= eol
+ 1) {
1074 for (eol
= p
; eol
< it
.eof
&& *eol
!= '\n'; eol
++);
1076 if ((ep
= memMem( p
, eol
- p
, " tty", 4 )) &&
1077 ep
< eol
&& isdigit( *ep
))
1079 if (ep
+ 1 == eol
|| isspace( *(ep
+ 1) ))
1081 else if (isdigit( *(ep
+ 1) ) &&
1082 (ep
+ 2 == eol
|| isspace( *(ep
+ 2) )))
1083 tty
= (*ep
- '0') * 10 + (*(ep
+ 1) - '0');
1086 TTYmask
|= 1 << (tty
- 1);
1102 /* TODO: handle solaris' local_uid specs */
1105 readWord( File
*file
, int EOFatEOL
)
1107 char *wordp
, *wordBuffer
;
1112 wordp
= wordBuffer
= file
->cur
;
1116 if (file
->cur
== file
->eof
) {
1118 if (wordp
== wordBuffer
)
1130 if (file
->cur
== file
->eof
)
1133 } while (c
!= '\n');
1136 if (EOFatEOL
&& !quoted
) {
1140 if (wordp
!= wordBuffer
) {
1147 if (wordp
!= wordBuffer
)
1161 /* backslashes are double-escaped - first parseArgs, then KConfig */
1164 splitArgs( const char *string
)
1169 StrList
*args
, **argp
= &args
;
1172 if (isspace( *string
)) {
1179 if (*string
== '\\') {
1180 if (*++string
!= '\\')
1182 if (*++string
!= '\\')
1187 } else if (*string
== '\'') {
1188 while (*++string
!= '\'' && *string
) {
1189 if (*string
== '\\' && *++string
!= '\\')
1193 } else if (*string
== '"') {
1194 while (*++string
!= '"' && *string
) {
1195 if (*string
== '\\') {
1196 if (*++string
!= '\\')
1198 if (*++string
!= '\\')
1207 } while (*++string
&& !isspace( *string
));
1208 *argp
= mmalloc( sizeof(**argp
) );
1209 (*argp
)->str
= str
= mmalloc( wlen
+ 1 );
1211 if (*word
== '\\') {
1212 if (*++word
!= '\\')
1214 if (*++word
!= '\\')
1219 } else if (*word
== '\'') {
1220 while (*++word
!= '\'' && *word
) {
1221 if (*word
== '\\' && *++word
!= '\\')
1225 } else if (*word
== '"') {
1226 while (*++word
!= '"' && *word
) {
1227 if (*word
== '\\') {
1228 if (*++word
!= '\\')
1230 if (*++word
!= '\\')
1239 } while (*++word
&& !isspace( *word
));
1241 argp
= &(*argp
)->next
;
1248 joinArgs( StrList
*argv
)
1257 for (slen
= 0, av
= argv
; slen
++, av
; av
= av
->next
) {
1259 for (s
= av
->str
; *s
; s
++, slen
++)
1260 if (isspace( *s
) || *s
== '\'')
1264 else if (*s
== '\\')
1268 rs
= str
= mmalloc( slen
);
1269 for (av
= argv
; av
; av
= av
->next
) {
1271 for (s
= av
->str
; *s
; s
++)
1272 if (isspace( *s
) || *s
== '\'')
1278 for (s
= av
->str
; *s
; s
++) {
1281 if (*s
== '"' || *s
== '\\') {
1294 static struct displayMatch
{
1297 } displayTypes
[] = {
1298 { "local", 5, True
},
1299 { "foreign", 7, False
},
1303 parseDisplayType( const char *string
, const char **atPos
)
1305 struct displayMatch
*d
;
1308 for (d
= displayTypes
; d
< displayTypes
+ as(displayTypes
); d
++) {
1309 if (!memcmp( d
->name
, string
, d
->len
) &&
1310 (!string
[d
->len
] || string
[d
->len
] == '@'))
1312 if (string
[d
->len
] == '@' && string
[d
->len
+ 1])
1313 *atPos
= string
+ d
->len
+ 1;
1320 typedef struct serverEntry
{
1321 struct serverEntry
*next
;
1322 const char *name
, *class2
, *console
, *argvs
, *arglvs
;
1323 StrList
*argv
, *arglv
;
1324 int local
, reserve
, vt
;
1328 absorbXservers( const char *sect ATTR_UNUSED
, char **value
)
1330 ServerEntry
*se
, *se1
, *serverList
, **serverPtr
;
1331 const char *word
, *word2
;
1332 char *sdpys
, *rdpys
;
1333 StrList
**argp
, **arglp
, *ap
, *ap2
;
1335 int nldpys
= 0, nrdpys
= 0, dpymask
= 0;
1341 if (**value
== '/') {
1342 if (!readFile( &file
, *value
))
1347 file
.eof
= *value
+ strlen( *value
);
1349 file
.cur
= file
.buf
;
1351 serverPtr
= &serverList
;
1355 while ((word
= readWord( &file
, 0 ))) {
1356 se
= mcalloc( sizeof(*se
) );
1358 if (!(word
= readWord( &file
, 1 )))
1360 se
->local
= parseDisplayType( word
, &se
->console
);
1361 if (se
->local
< 0) {
1363 if (!(word
= readWord( &file
, 1 )))
1365 se
->local
= parseDisplayType( word
, &se
->console
);
1366 if (se
->local
< 0) {
1367 while (readWord( &file
, 1 ));
1371 word
= readWord( &file
, 1 );
1372 if (word
&& !strcmp( word
, "reserve" )) {
1374 word
= readWord( &file
, 1 );
1376 if (se
->local
!= (word
!= 0))
1382 if (word
[0] == 'v' && word
[1] == 't')
1383 se
->vt
= atoi( word
+ 2 );
1384 else if (!strcmp( word
, "-crt" )) { /* SCO style */
1385 if (!(word
= readWord( &file
, 1 )) ||
1386 memcmp( word
, "/dev/tty", 8 ))
1388 se
->vt
= atoi( word
+ 8 );
1391 if (strcmp( word
, se
->name
)) {
1392 ap
= mmalloc( sizeof(*ap
) );
1394 if (!strcmp( word
, "-nolisten" )) {
1395 if (!(word2
= readWord( &file
, 1 )))
1397 ap2
= mmalloc( sizeof(*ap2
) );
1400 if (!strcmp( word2
, "unix" )) {
1412 word
= readWord( &file
, 1 );
1417 dpymask
|= 1 << atoi( se
->name
+ 1 );
1422 serverPtr
= &se
->next
;
1427 /* don't copy only if all local displays are ordered and have a vt */
1430 for (se
= serverList
, mtty
= maxTTY
; se
; se
= se
->next
)
1433 if (se
->vt
!= mtty
) {
1440 for (se
= serverList
; se
; se
= se
->next
) {
1441 se
->argvs
= joinArgs( se
->argv
);
1442 se
->arglvs
= joinArgs( se
->arglv
);
1445 se1
= 0, cpcmd
= cpcmdl
= False
;
1446 for (se
= serverList
; se
; se
= se
->next
)
1451 if (strcmp( se1
->argvs
, se
->argvs
))
1453 if (strcmp( se1
->arglvs
, se
->arglvs
))
1458 putFqVal( "X-:*-Core", "ServerCmd", se1
->argvs
);
1459 putFqVal( "X-:*-Core", "ServerArgsLocal", se1
->arglvs
);
1460 for (se
= serverList
; se
; se
= se
->next
)
1463 sprintf( sec
, "X-%s-Core", se
->name
);
1465 putFqVal( sec
, "ServerCmd", se
->argvs
);
1467 putFqVal( sec
, "ServerArgsLocal", se
->arglvs
);
1469 if (cpvt
&& se
->vt
) {
1471 sprintf( vt
, "%d", se
->vt
);
1472 putFqVal( sec
, "ServerVT", vt
);
1476 putFqVal( sec
, "ServerTTY", se
->console
);
1482 for (se
= serverList
; se
; se
= se
->next
)
1483 strCat( se
->reserve
? &rdpys
: &sdpys
,
1484 se
->class2
? ",%s_%s" : ",%s", se
->name
, se
->class2
);
1487 /* add reserve dpys */
1488 if (nldpys
< 4 && nldpys
&& !nrdpys
)
1489 for (; nldpys
< 4; nldpys
++) {
1490 for (dn
= 0; dpymask
& (1 << dn
); dn
++);
1491 dpymask
|= (1 << dn
);
1492 strCat( &rdpys
, ",:%d", dn
);
1496 putFqVal( "General", "StaticServers", sdpys
? sdpys
+ 1 : "" );
1497 putFqVal( "General", "ReserveServers", rdpys
? rdpys
+ 1 : "" );
1499 if (**value
== '/' && inNewDir( *value
) && !use_destdir
)
1505 upd_servervts( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1507 if (!ce
->active
) { /* there is only the Global one */
1508 #ifdef __linux__ /* XXX actually, sysvinit */
1510 ASPrintf( (char **)&ce
->value
, "-%d", maxTTY
+ 1 );
1511 ce
->active
= ce
->written
= True
;
1517 upd_consolettys( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1519 if (!ce
->active
) { /* there is only the Global one */
1520 #ifdef __linux__ /* XXX actually, sysvinit */
1525 for (i
= 0, buf
= 0; i
< 16; i
++)
1526 if (TTYmask
& (1 << i
))
1527 strCat( &buf
, ",tty%d", i
+ 1 );
1529 ce
->value
= buf
+ 1;
1530 ce
->active
= ce
->written
= True
;
1538 upd_servercmd( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1545 if (!ce
->active
|| oldver
>= 0x0204)
1547 if (!(sa
= splitArgs( ce
->value
)))
1549 ASPrintf( &svr
, "%s -help 2>&1", sa
->str
);
1550 if (!(fp
= popen( svr
, "r" )))
1552 buf
[fread( buf
, 1, sizeof(buf
) - 1, fp
)] = 0;
1554 if (strstr( buf
, "\n-br " ))
1555 addStr( &sa
, "-br" );
1556 if (strstr( buf
, "\n-novtswitch " ))
1557 addStr( &sa
, "-novtswitch" );
1558 if (strstr( buf
, "\n-quiet " ))
1559 addStr( &sa
, "-quiet" );
1560 ce
->value
= joinArgs( sa
);
1566 cp_keyfile( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1568 if (!ce
->active
) /* there is only the Global one */
1573 if (!copyFile( ce
, 0600, 0 ))
1578 mk_xaccess( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1580 if (!ce
->active
) /* there is only the Global one */
1581 writeFile( def_Xaccess
, 0644, def_xaccess
);
1585 copyFile( ce
, 0644, 0 ); /* don't handle error, it will disable Xdmcp automatically */
1589 mk_willing( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1593 if (!ce
->active
) /* there is only the Global one */
1596 if (!(fname
= strchr( ce
->value
, '/' )))
1597 return; /* obviously in-line (or empty) */
1598 if (old_scripts
|| inNewDir( fname
))
1599 doLinkFile( fname
);
1602 ce
->value
= KDMCONF
"/Xwilling";
1603 ce
->active
= ce
->written
= True
;
1604 writeFile( ce
->value
, 0755, def_willing
);
1612 edit_resources( File *file )
1614 // XXX remove any login*, chooser*, ... resources
1620 cp_resources( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1622 if (!ce
->active
) /* the X-*-Greeter one */
1627 if (!copyFile( ce
, 0644, 0/*edit_resources*/ ))
1632 delstr( File
*fil
, const char *pat
)
1635 const char *pap
, *paap
;
1638 for (p
= fil
->buf
; *p
; p
++) {
1639 for (pp
= p
, pap
= pat
; ; ) {
1642 memcpy( p
+ 1, pp
, fil
->eof
- pp
+ 1 );
1643 fil
->eof
-= pp
- p
- 1;
1645 } else if (!memcmp( pap
, "*/", 2 )) {
1647 while (!isspace( *pap
))
1652 for (bpp
= ++pp
; *pp
!= '/'; pp
++)
1653 if (!*pp
|| isspace( *pp
))
1656 if ((pp
- bpp
!= pap
- paap
) || memcmp( bpp
, paap
, pap
- paap
))
1658 } else if (*pap
== '\t') {
1660 while (*pp
== ' ' || *pp
== '\t')
1662 } else if (*pap
== '[') {
1666 fprintf( stderr
, "Internal error: unterminated char set\n" );
1670 while (*++pap
!= ']')
1672 fprintf( stderr
, "Internal error: unterminated char set\n" );
1684 while (*pp
== ' ' || *pp
== '\t')
1698 the UseBackground voodoo will horribly fail, if multiple sections link
1699 to the same Xsetup file
1702 static int mod_usebg
;
1705 edit_setup( File
*file
)
1710 " PIDFILE=/var/run/kdmdesktop-$DISPLAY.pid\n"
1711 " */kdmdesktop\t&\n"
1712 " echo $! >$PIDFILE\n"
1717 "*/kdmdesktop\t&\n" ) |
1719 "kdmdesktop\t&\n" ) |
1722 putVal( "UseBackground", chg
? "true" : "false" );
1727 mk_setup( Entry
*ce
, Section
*cs
)
1729 setSect( reSect( cs
->name
, "Greeter" ) );
1730 if (old_scripts
|| mixed_scripts
) {
1731 if (mod_usebg
&& *ce
->value
)
1732 putVal( "UseBackground", "false" );
1735 if (ce
->active
&& inNewDir( ce
->value
)) {
1737 copyFile( ce
, 0755, edit_setup
);
1741 ce
->value
= KDMCONF
"/Xsetup";
1742 ce
->active
= ce
->written
= True
;
1743 writeFile( ce
->value
, 0755, def_setup
);
1749 edit_startup( File
*file
)
1751 int chg1
= False
, chg2
= False
;
1755 "PIDFILE=/var/run/kdmdesktop-$DISPLAY.pid\n"
1756 "if [[] -f $PIDFILE ] ; then\n"
1757 " kill `cat $PIDFILE`\n"
1760 "PIDFILE=/var/run/kdmdesktop-$DISPLAY.pid\n"
1761 "test -f $PIDFILE && kill `cat $PIDFILE`\n" )))
1763 if (oldver
< 0x0203) {
1767 "# We create a pseudodevice for finger. (host:0 becomes [kx]dm/host_0)\n" );
1768 "# Without it, finger errors out with \"Cannot stat /dev/host:0\".\n"
1770 "if [[] -f /usr/lib/X11/xdm/sessreg ]; then\n"
1771 " devname=`echo $DISPLAY | /usr/bin/sed -e 's/[[]:\\.]/_/g' | /usr/bin/cut -c1-8`\n"
1772 " hostname=`echo $DISPLAY | /usr/bin/cut -d':' -f1`\n"
1774 " if [[] -z \"$devname\" ]; then\n"
1775 " devname=\"unknown\"\n"
1777 " if [[] ! -d /dev/[kx]dm ]; then\n"
1778 " /usr/bin/mkdir /dev/[kx]dm\n"
1779 " /usr/bin/chmod 755 /dev/[kx]dm\n"
1781 " /usr/bin/touch /dev/[kx]dm/$devname\n"
1782 " /usr/bin/chmod 644 /dev/[kx]dm/$devname\n"
1784 " if [[] -z \"$hostname\" ]; then\n"
1785 " exec /usr/lib/X11/xdm/sessreg -a -l [kx]dm/$devname $USER\n"
1787 " exec /usr/lib/X11/xdm/sessreg -a -l [kx]dm/$devname -h $hostname $USER\n"
1793 "exec sessreg -a -l $DISPLAY -x */Xservers -u " _PATH_UTMP
" $USER\n" ) |
1797 "exec sessreg -a -l $DISPLAY"
1803 "exec sessreg -a -l $DISPLAY -u /var/run/utmp -x */Xservers $USER\n" );
1804 putVal( "UseSessReg", chg2
? "true" : "false" );
1810 mk_startup( Entry
*ce
, Section
*cs
)
1812 setSect( cs
->name
);
1813 if (old_scripts
|| mixed_scripts
)
1816 if (ce
->active
&& inNewDir( ce
->value
)) {
1817 if (mod_usebg
|| oldver
< 0x0203)
1818 copyFile( ce
, 0755, edit_startup
);
1822 ce
->value
= KDMCONF
"/Xstartup";
1823 ce
->active
= ce
->written
= True
;
1824 writeFile( ce
->value
, 0755, def_startup
);
1830 edit_reset( File
*file
)
1835 "if [[] -f /usr/lib/X11/xdm/sessreg ]; then\n"
1836 " devname=`echo $DISPLAY | /usr/bin/sed -e 's/[[]:\\.]/_/g' | /usr/bin/cut -c1-8`\n"
1837 " exec /usr/lib/X11/xdm/sessreg -d -l [kx]dm/$devname $USER\n"
1842 "exec sessreg -d -l $DISPLAY -x */Xservers -u " _PATH_UTMP
" $USER\n" ) |
1846 "exec sessreg -d -l $DISPLAY"
1852 "exec sessreg -d -l $DISPLAY -u /var/run/utmp -x */Xservers $USER\n" );
1856 mk_reset( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1858 if (old_scripts
|| mixed_scripts
)
1861 if (ce
->active
&& inNewDir( ce
->value
)) {
1862 if (oldver
< 0x0203)
1863 copyFile( ce
, 0755, edit_reset
);
1867 ce
->value
= KDMCONF
"/Xreset";
1868 ce
->active
= ce
->written
= True
;
1869 writeFile( ce
->value
, 0755, def_reset
);
1875 mk_session( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1880 if ((old_scripts
|| (ce
->active
&& inNewDir( ce
->value
))) &&
1884 tmpf
= locate( "mktemp" ) ?
1885 "`mktemp /tmp/xsess-env-XXXXXX`" :
1886 locate( "tempfile" ) ?
1888 "$HOME/.xsession-env-$DISPLAY";
1889 ASPrintf( &def_session
, "%s%s%s", def_session1
, tmpf
, def_session2
);
1890 ce
->value
= KDMCONF
"/Xsession";
1891 ce
->active
= ce
->written
= True
;
1892 writeFile( ce
->value
, 0755, def_session
);
1897 upd_language( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1899 if (!strcmp( ce
->value
, "C" ))
1900 ce
->value
= (char *)"en_US";
1904 upd_guistyle( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1906 if (!strcmp( ce
->value
, "Motif+" ))
1907 ce
->value
= (char *)"MotifPlus";
1908 else if (!strcmp( ce
->value
, "KDE" ))
1909 ce
->value
= (char *)"Default";
1913 upd_showusers( Entry
*ce
, Section
*cs
)
1915 if (!strcmp( ce
->value
, "All" ))
1916 ce
->value
= (char *)"NotHidden";
1917 else if (!strcmp( ce
->value
, "None" )) {
1919 putFqVal( cs
->name
, "UserList", "false" );
1920 ce
->value
= (char *)"Selected";
1926 static const char *defminuid
, *defmaxuid
;
1929 upd_minshowuid( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1932 ce
->value
= defminuid
;
1933 ce
->active
= ce
->written
= True
;
1938 upd_maxshowuid( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1941 ce
->value
= defmaxuid
;
1942 ce
->active
= ce
->written
= True
;
1947 upd_hiddenusers( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1950 const char *msu
, *pt
, *et
;
1952 unsigned minuid
, maxuid
;
1958 msu
= getFqVal( cs
->name
, "MinShowUID", "0" );
1959 sscanf( msu
, "%u", &minuid
);
1960 msu
= getFqVal( cs
->name
, "MaxShowUID", "65535" );
1961 sscanf( msu
, "%u", &maxuid
);
1966 et
= strpbrk( pt
, ";," );
1968 memcpy( nbuf
, pt
, et
- pt
);
1972 if ((pw
= getpwnam( nbuf
))) {
1974 (pw
->pw_uid
>= minuid
&& pw
->pw_uid
<= maxuid
))
1977 strCat( &nv
, ",%s", nbuf
);
1979 nv
= mstrdup( nbuf
);
1986 ce
->value
= nv
? nv
: "";
1990 upd_forgingseed( Entry
*ce
, Section
*cs ATTR_UNUSED
)
1993 ASPrintf( (char **)&ce
->value
, "%d", time( 0 ) );
1994 ce
->active
= ce
->written
= True
;
1999 upd_fifodir( Entry
*ce
, Section
*cs ATTR_UNUSED
)
2006 dir
= ce
->active
? ce
->value
: def_FifoDir
;
2008 chmod( dir
, st
.st_mode
| 0755 );
2012 upd_datadir( Entry
*ce
, Section
*cs ATTR_UNUSED
)
2014 char *oldsts
, *newsts
;
2019 dir
= ce
->active
? ce
->value
: def_DataDir
;
2020 if (mkdirp( dir
, 0755, "data", 0 ) && oldkde
) {
2021 ASPrintf( &oldsts
, "%s/kdm/kdmsts", oldkde
);
2022 ASPrintf( &newsts
, "%s/kdmsts", dir
);
2023 rename( oldsts
, newsts
);
2028 upd_userlogfile( Entry
*ce
, Section
*cs ATTR_UNUSED
)
2032 if ((p
= strstr( ce
->value
, "%s" )))
2033 ASPrintf( (char **)&ce
->value
, "%.*s%%d%s", p
- ce
->value
, ce
->value
, p
+ 2 );
2038 * Do not overwrite existing target.
2039 * Do not complain if source cannot be read.
2042 copyPlainFile( const char *from
, const char *to
)
2047 if (readFile( &file
, from
)) {
2048 if ((fd
= open( to
, O_WRONLY
| O_CREAT
| O_EXCL
, 0644 )) >= 0) {
2049 write( fd
, file
.buf
, file
.eof
- file
.buf
);
2051 } else if (errno
!= EEXIST
)
2052 fprintf( stderr
, "Warning: cannot create %s\n", to
);
2058 copyDir( const char *from
, const char *to
)
2063 char bn
[PATH_MAX
], bo
[PATH_MAX
];
2065 if (!(dir
= opendir( from
)))
2067 while ((ent
= readdir( dir
))) {
2068 if (!strcmp( ent
->d_name
, "." ) || !strcmp( ent
->d_name
, ".." ))
2070 sprintf( bo
, "%s/%s", from
, ent
->d_name
);
2071 if (stat( bo
, &st
) || !S_ISREG( st
.st_mode
))
2073 sprintf( bn
, "%s/%s", to
, ent
->d_name
);
2074 copyPlainFile( bo
, bn
);
2081 upd_facedir( Entry
*ce
, Section
*cs ATTR_UNUSED
)
2083 char *oldpic
, *newpic
, *olddir
;
2088 if (oldkdepfx
) { /* Do we have a previous install? */
2089 /* This would be the prev install's default location */
2090 ASPrintf( &olddir
, "%s/share/apps/kdm/faces", oldkdepfx
);
2091 if (ce
->active
&& strcmp( olddir
, ce
->value
))
2092 /* Not default location, so don't touch the setting. */
2094 /* Default location, so absorb it. */
2096 /* Don't copy if old dir == new new. */
2097 if (!strcmp( olddir
, def_FaceDir
))
2101 if (mkdirp( def_FaceDir
, 0755, "user face", True
)) {
2102 const char *defpic
= def_FaceDir
"/.default.face.icon";
2103 const char *rootpic
= def_FaceDir
"/root.face.icon";
2104 if (oldkde
&& (!olddir
|| !copyDir( olddir
, def_FaceDir
)) &&
2105 oldver
< 0x0201) /* This isn't exact - didn't inc version. */
2108 while ((pw
= getpwent()))
2109 if (strcmp( pw
->pw_name
, "root" )) {
2110 ASPrintf( &oldpic
, "%s/share/apps/kdm/pics/users/%s.png",
2111 oldkdepfx
, pw
->pw_name
);
2112 ASPrintf( &newpic
, def_FaceDir
"/%s.face.icon", pw
->pw_name
);
2113 rename( oldpic
, newpic
);
2118 ASPrintf( &oldpic
, "%s/share/apps/kdm/pics/users/default.png", oldkdepfx
);
2119 if (!rename( oldpic
, defpic
))
2121 ASPrintf( &oldpic
, "%s/share/apps/kdm/pics/users/root.png", oldkdepfx
);
2122 if (!rename( oldpic
, rootpic
))
2126 ASPrintf( &oldpic
, "%s/default1.png", facesrc
);
2127 copyPlainFile( oldpic
, defpic
);
2130 ASPrintf( &oldpic
, "%s/root1.png", facesrc
);
2131 copyPlainFile( oldpic
, rootpic
);
2137 upd_sessionsdirs( Entry
*ce
, Section
*cs ATTR_UNUSED
)
2141 char olddir
[PATH_MAX
];
2144 sprintf( olddir
, "%s/share/apps/kdm/sessions", oldkdepfx
);
2145 olen
= strlen( oldkde
);
2146 sl
= splitList( ce
->value
);
2147 for (sp
= sl
; sp
; sp
= sp
->next
) {
2148 if (!strcmp( sp
->str
, olddir
))
2149 sp
->str
= def_SessionsDirs
;
2150 else if (!memcmp( sp
->str
, oldkde
, olen
) &&
2151 !memcmp( sp
->str
+ olen
, "/kdm/", 5 ))
2154 sprintf( nd
, "%s%s", newdir
, sp
->str
+ olen
+ 4 );
2155 mkdirp( nd
, 0755, "sessions", False
);
2156 copyDir( sp
->str
, nd
);
2157 ASPrintf( (char **)&sp
->str
, KDMCONF
"%s", sp
->str
+ olen
+ 4 );
2160 ce
->value
= joinList( sl
);
2163 sprintf( nd
, "%s/sessions", newdir
);
2164 mkdirp( nd
, 0755, "sessions", False
);
2169 upd_preloader( Entry
*ce
, Section
*cs ATTR_UNUSED
)
2171 if (ce
->written
) { /* implies oldkde != 0 */
2173 ASPrintf( &oldpl
, "%s/bin/preloadkde", oldkdepfx
);
2174 if (!strcmp( ce
->value
, oldpl
))
2175 ce
->value
= (char *)KDE_BINDIR
"/preloadkde";
2184 findSect( const char *name
)
2189 p
= strrchr( name
, '-' );
2192 for (i
= 0; i
< as(allSects
); i
++)
2193 if (!strcmp( allSects
[i
]->name
, p
))
2195 fprintf( stderr
, "Internal error: unknown section %s\n", name
);
2200 findEnt( Sect
*sect
, const char *key
)
2204 for (i
= 0; i
< sect
->nents
; i
++)
2205 if (!strcmp( sect
->ents
[i
].key
, key
))
2206 return sect
->ents
+ i
;
2207 fprintf( stderr
, "Internal error: unknown key %s in section %s\n",
2217 typedef struct DEnt
{
2223 typedef struct DSect
{
2227 const char *comment
;
2233 makeDefaultConfig( void )
2239 for (csp
= &config
, sc
= 0; sc
< as(dAllSects
); csp
= &(cs
->next
), sc
++) {
2240 cs
= mcalloc( sizeof(*cs
) );
2242 cs
->spec
= findSect( dAllSects
[sc
].name
);
2243 cs
->name
= dAllSects
[sc
].name
;
2244 cs
->comment
= dAllSects
[sc
].comment
;
2245 for (cep
= &(cs
->ents
), ec
= 0; ec
< dAllSects
[sc
].nents
;
2246 cep
= &(ce
->next
), ec
++)
2248 ce
= mcalloc( sizeof(*ce
) );
2250 ce
->spec
= findEnt( cs
->spec
, dAllSects
[sc
].ents
[ec
].key
);
2251 ce
->value
= dAllSects
[sc
].ents
[ec
].value
;
2252 ce
->active
= dAllSects
[sc
].ents
[ec
].active
;
2259 * read rc file structure
2262 typedef struct REntry
{
2263 struct REntry
*next
;
2268 typedef struct RSection
{
2269 struct RSection
*next
;
2275 readConfig( const char *fname
)
2278 char *s
, *e
, *st
, *en
, *ek
, *sl
;
2279 RSection
*rootsec
= 0, *cursec
;
2285 if (!readFile( &file
, fname
))
2289 for (s
= file
.buf
, line
= 0, cursec
= 0, sectmoan
= 1; s
< file
.eof
; s
++) {
2292 while ((s
< file
.eof
) && isspace( *s
) && (*s
!= '\n'))
2295 if ((s
< file
.eof
) && ((*s
== '\n') || (*s
== '#'))) {
2297 while ((s
< file
.eof
) && (*s
!= '\n'))
2304 while ((s
< file
.eof
) && (*s
!= '\n'))
2307 while ((e
> sl
) && isspace( *e
))
2310 fprintf( stderr
, "Invalid section header at %s:%d\n",
2317 for (cursec
= rootsec
; cursec
; cursec
= cursec
->next
)
2318 if (!memcmp( nstr
, cursec
->name
, nlen
) &&
2319 !cursec
->name
[nlen
])
2321 #if 0 /* not our business ... */
2322 fprintf( stderr
, "Warning: Multiple occurrences of section "
2323 "[%.*s] in %s. Consider merging them.\n",
2324 nlen
, nstr
, fname
);
2328 cursec
= mmalloc( sizeof(*cursec
) );
2329 ASPrintf( (char **)&cursec
->name
, "%.*s", nlen
, nstr
);
2331 cursec
->next
= rootsec
;
2340 fprintf( stderr
, "Entry outside any section at %s:%d",
2346 for (; (s
< file
.eof
) && (*s
!= '\n'); s
++)
2349 fprintf( stderr
, "Invalid entry (missing '=') at %s:%d\n", fname
, line
);
2353 for (ek
= s
- 1;; ek
--) {
2355 fprintf( stderr
, "Invalid entry (empty key) at %s:%d\n",
2359 if (!isspace( *ek
))
2364 while ((s
< file
.eof
) && isspace( *s
) && (*s
!= '\n'))
2367 while ((s
< file
.eof
) && (*s
!= '\n'))
2369 for (en
= s
- 1; en
>= st
&& isspace( *en
); en
--);
2373 for (curent
= cursec
->ents
; curent
; curent
= curent
->next
)
2374 if (!memcmp( nstr
, curent
->key
, nlen
) &&
2375 !curent
->key
[nlen
]) {
2376 fprintf( stderr
, "Multiple occurrences of key '%s' in section "
2377 "[%s] of %s.\n", curent
->key
, cursec
->name
, fname
);
2380 curent
= mmalloc( sizeof(*curent
) );
2381 ASPrintf( (char **)&curent
->key
, "%.*s", nlen
, nstr
);
2382 ASPrintf( (char **)&curent
->value
, "%.*s", en
- st
+ 1, st
);
2383 curent
->next
= cursec
->ents
;
2384 cursec
->ents
= curent
;
2393 mergeKdmRcOld( const char *path
)
2398 ASPrintf( &p
, "%s/kdmrc", path
);
2399 if (stat( p
, &st
)) {
2403 printf( "Information: ignoring pre-existing kdmrc %s from kde < 2.2\n", p
);
2409 const char *sect
, *key
, *def
;
2410 int (*cond
)( void );
2414 * The idea is to determine how exactly the pre-existing config would
2415 * have been interpreted, so no default configs are created where builtin
2416 * defaults were used so far.
2419 applyDefs( FDefs
*chgdef
, int ndefs
, const char *path
)
2424 for (i
= 0; i
< ndefs
; i
++)
2425 if (!getFqVal( chgdef
[i
].sect
, chgdef
[i
].key
, 0 ) &&
2426 (!chgdef
[i
].cond
|| chgdef
[i
].cond()))
2428 ASPrintf( &p
, chgdef
[i
].def
, path
);
2429 putFqVal( chgdef
[i
].sect
, chgdef
[i
].key
, p
);
2437 return isTrue( getFqVal( "X-*-Greeter", "UseBackground", "true" ) );
2440 static FDefs kdmdefs_all
[] = {
2442 { "Xdmcp", "Xaccess", "%s/kdm/Xaccess", 0 },
2443 { "Xdmcp", "Willing", "", 0 },
2445 { "X-*-Core", "Setup", "", 0 },
2446 { "X-*-Core", "Startup", "", 0 },
2447 { "X-*-Core", "Reset", "", 0 },
2448 { "X-*-Core", "Session", XBINDIR
"/xterm -ls -T", 0 },
2449 { "X-*-Greeter", "BackgroundCfg", "%s/kdm/backgroundrc", if_usebg
},
2452 typedef struct KUpdEnt
{
2453 const char *okey
, *nsec
, *nkey
;
2454 void (*func
)( const char *sect
, char **value
);
2457 typedef struct KUpdSec
{
2465 P_EnableChooser( const char *sect ATTR_UNUSED
, char **value
)
2467 *value
= (char *)(isTrue( *value
) ? "DefaultLocal" : "LocalOnly");
2472 P_UseLilo( const char *sect ATTR_UNUSED
, char **value
)
2474 *value
= (char *)(isTrue( *value
) ? "Lilo" : "None");
2478 P_EchoMode( const char *sect ATTR_UNUSED
, char **value
)
2480 *value
= (char *)(!strcmp( *value
, "NoEcho" ) ? "false" : "true");
2486 mergeKdmRcNewer( const char *path
, int obsRet
)
2489 const char *cp
, *sec
, *key
;
2490 RSection
*rootsect
, *cs
;
2493 static char sname
[64];
2495 ASPrintf( &p
, "%s/kdm/kdmrc", path
);
2496 if (!(rootsect
= readConfig( p
))) {
2500 for (cs
= rootsect
; cs
; cs
= cs
->next
)
2501 if (!strcmp( cs
->name
, "General" ))
2502 for (ce
= cs
->ents
; ce
; ce
= ce
->next
)
2503 if (!strcmp( ce
->key
, "ConfigVersion" ))
2505 printf( "Information: ignoring pre-existing kdmrc %s from kde < 3.1\n", p
);
2509 sscanf( ce
->value
, "%d.%d", &ma
, &mi
);
2510 oldver
= (ma
<< 8) | mi
;
2511 printf( "Information: reading pre-existing kdmrc %s (config version %d.%d)\n",
2515 for (cs
= rootsect
; cs
; cs
= cs
->next
) {
2516 cp
= strrchr( cs
->name
, '-' );
2519 else if (cs
->name
[0] != 'X' || cs
->name
[1] != '-')
2521 for (i
= 0; i
< as(kupsects
); i
++)
2522 if (!strcmp( cp
, kupsects
[i
].osec
)) {
2523 for (ce
= cs
->ents
; ce
; ce
= ce
->next
) {
2524 for (j
= 0; j
< kupsects
[i
].nents
; j
++)
2525 if (!strcmp( ce
->key
, kupsects
[i
].ents
[j
].okey
)) {
2526 if (kupsects
[i
].ents
[j
].nsec
== (char *)-1) {
2527 kupsects
[i
].ents
[j
].func( 0, &ce
->value
);
2530 if (!kupsects
[i
].ents
[j
].nsec
)
2534 sprintf( sname
, "%.*s-%s",
2535 (int)(cp
- cs
->name
), cs
->name
,
2536 kupsects
[i
].ents
[j
].nsec
);
2538 if (!kupsects
[i
].ents
[j
].nkey
)
2541 key
= kupsects
[i
].ents
[j
].nkey
;
2542 if (kupsects
[i
].ents
[j
].func
)
2543 kupsects
[i
].ents
[j
].func( sec
, &ce
->value
);
2544 putFqVal( sec
, key
, ce
->value
);
2547 printf( "Information: dropping key %s from section [%s]\n",
2548 ce
->key
, cs
->name
);
2554 printf( "Information: dropping section [%s]\n", cs
->name
);
2558 applyDefs( kdmdefs_all
, as(kdmdefs_all
), path
);
2564 typedef struct XResEnt
{
2566 const char *ksec
, *kname
;
2567 void (*func
)( const char *sect
, char **value
);
2571 handleXdmVal( const char *dpy
, const char *key
, char *value
,
2572 const XResEnt
*ents
, int nents
)
2576 char knameb
[80], sname
[80];
2578 for (i
= 0; i
< nents
; i
++)
2579 if (!strcmp( key
, ents
[i
].xname
) ||
2580 (key
[0] == toupper( ents
[i
].xname
[0] ) &&
2581 !strcmp( key
+ 1, ents
[i
].xname
+ 1 )))
2583 if (ents
[i
].ksec
== (char *)-1) {
2584 ents
[i
].func( 0, &value
);
2587 sprintf( sname
, ents
[i
].ksec
, dpy
);
2589 kname
= ents
[i
].kname
;
2592 sprintf( knameb
, "%c%s",
2593 toupper( ents
[i
].xname
[0] ), ents
[i
].xname
+ 1 );
2596 ents
[i
].func( sname
, &value
);
2597 putFqVal( sname
, kname
, value
);
2603 P_list( const char *sect ATTR_UNUSED
, char **value
)
2608 for (st
= *value
, is
= False
, d
= s
= 0; st
[s
]; s
++)
2609 if (st
[s
] == ' ' || st
[s
] == '\t') {
2621 P_authDir( const char *sect ATTR_UNUSED
, char **value
)
2625 l
= strlen( *value
);
2630 if ((*value
)[l
-1] == '/')
2632 if (!strncmp( *value
, "/tmp/", 5 ) ||
2633 !strncmp( *value
, "/var/tmp/", 9 ))
2635 printf( "Warning: Resetting inappropriate value %s for AuthDir to default\n",
2640 if ((l
>= 4 && !strcmp( *value
+ l
- 4, "/tmp" )) ||
2641 (l
>= 6 && !strcmp( *value
+ l
- 6, "/xauth" )) ||
2642 (l
>= 8 && !strcmp( *value
+ l
- 8, "/authdir" )) ||
2643 (l
>= 10 && !strcmp( *value
+ l
- 10, "/authfiles" )))
2645 ASPrintf( value
, "%s/authdir", *value
);
2649 P_openDelay( const char *sect
, char **value
)
2651 putFqVal( sect
, "ServerTimeout", *value
);
2655 P_noPassUsers( const char *sect
, char **value ATTR_UNUSED
)
2657 putFqVal( sect
, "NoPassEnable", "true" );
2661 P_autoUser( const char *sect
, char **value ATTR_UNUSED
)
2663 putFqVal( sect
, "AutoLoginEnable", "true" );
2668 P_requestPort( const char *sect
, char **value
)
2670 if (!strcmp( *value
, "0" )) {
2672 putFqVal( sect
, "Enable", "false" );
2674 putFqVal( sect
, "Enable", "true" );
2678 static int kdmrcmode
= 0644;
2681 P_autoPass( const char *sect ATTR_UNUSED
, char **value ATTR_UNUSED
)
2688 static XrmQuark XrmQString
, empty
= NULLQUARK
;
2691 dumpEntry( XrmDatabase
*db ATTR_UNUSED
,
2692 XrmBindingList bindings
,
2693 XrmQuarkList quarks
,
2694 XrmRepresentation
*type
,
2696 XPointer data ATTR_UNUSED
)
2698 const char *dpy
, *key
;
2702 if (*type
!= XrmQString
)
2704 if (*bindings
== XrmBindLoosely
||
2705 strcmp( XrmQuarkToString (*quarks
), "DisplayManager" ))
2707 bindings
++, quarks
++;
2710 if (*bindings
!= XrmBindLoosely
&& !quarks
[1]) { /* DM.foo */
2711 key
= XrmQuarkToString (*quarks
);
2712 handleXdmVal( 0, key
, value
->addr
, globents
, as(globents
) );
2714 } else if (*bindings
== XrmBindLoosely
&& !quarks
[1]) { /* DM*bar */
2716 key
= XrmQuarkToString (*quarks
);
2717 } else if (*bindings
!= XrmBindLoosely
&& quarks
[1] &&
2718 *bindings
!= XrmBindLoosely
&& !quarks
[2])
2721 strcpy( dpybuf
+ 4, XrmQuarkToString (*quarks
) );
2722 for (hasu
= False
, el
= 4; dpybuf
[el
]; el
++)
2723 if (dpybuf
[el
] == '_')
2725 if (!hasu
/* && isupper (dpy[0])*/) {
2727 memcpy( dpybuf
, "*:*_", 4 );
2730 if (dpybuf
[el
] == '_') {
2733 if (dpybuf
[el
] == '_')
2738 key
= XrmQuarkToString (quarks
[1]);
2741 handleXdmVal( dpy
, key
, value
->addr
, dpyents
, as(dpyents
) );
2745 static FDefs xdmdefs
[] = {
2747 { "Xdmcp", "Xaccess", "%s/Xaccess", 0 },
2748 { "Xdmcp", "Willing", "", 0 },
2750 { "X-*-Core", "Setup", "", 0 },
2751 { "X-*-Core", "Startup", "", 0 },
2752 { "X-*-Core", "Reset", "", 0 },
2753 { "X-*-Core", "Session", "", 0 },
2757 mergeXdmCfg( const char *path
)
2762 ASPrintf( &p
, "%s/xdm-config", path
);
2763 if ((db
= XrmGetFileDatabase( p
))) {
2764 printf( "Information: reading xdm config file %s\n", p
);
2767 XrmEnumerateDatabase( db
, &empty
, &empty
, XrmEnumAllLevels
,
2768 dumpEntry
, (XPointer
)0 );
2769 applyDefs( xdmdefs
, as(xdmdefs
), path
);
2778 fprintfLineWrap( FILE *f
, const char *msg
, ... )
2780 char *txt
, *ftxt
, *line
;
2782 int col
, lword
, fspace
;
2784 va_start( ap
, msg
);
2785 VASPrintf( &txt
, msg
, ap
);
2788 for (line
= txt
, col
= 0, lword
= fspace
= -1; line
[col
]; ) {
2789 if (line
[col
] == '\n') {
2790 strCat( &ftxt
, "%.*s", ++col
, line
);
2793 lword
= fspace
= -1;
2795 } else if (line
[col
] == ' ') {
2803 if (col
>= 78 && fspace
>= 0) {
2804 strCat( &ftxt
, "%.*s\n", fspace
, line
);
2821 static const char *oldkdes
[] = {
2823 "/opt/kde4/share/config",
2824 "/usr/local/kde4/share/config",
2826 "/opt/kde/share/config",
2827 "/usr/local/kde/share/config",
2828 "/usr/local/share/config",
2829 "/usr/share/config",
2831 "/opt/kde3/share/config",
2832 "/usr/local/kde3/share/config",
2835 static const char *oldxdms
[] = {
2840 int main( int argc
, char **argv
)
2847 int i
, ap
, locals
, foreigns
;
2848 int no_old_xdm
= 0, no_old_kde
= 0;
2851 for (ap
= 1; ap
< argc
; ap
++) {
2852 if (!strcmp( argv
[ap
], "--help" )) {
2854 "genkdmconf - generate configuration files for kdm\n"
2856 "If an older xdm/kdm configuration is found, its config files are \"absorbed\";\n"
2857 "if it lives in the new target directory, its scripts are reused (and possibly\n"
2858 "modified) as well, otherwise the scripts are ignored and default scripts are\n"
2862 " --in /path/to/new/kdm-config-dir\n"
2863 " In which directory to put the new configuration. You can use this\n"
2864 " to support a $(DESTDIR), but not to change the final location of\n"
2865 " the installation - the paths inside the files are not affected.\n"
2866 " Default is " KDMCONF
".\n"
2867 " --old-xdm /path/to/old/xdm-dir\n"
2868 " Where to look for the config files of an xdm.\n"
2869 " Default is to scan /etc/X11/xdm & $XLIBDIR/xdm.\n"
2870 " Note that you possibly need to use --no-old-kde to make this take effect.\n"
2871 " --old-kde /path/to/old/kde-config-dir\n"
2872 " Where to look for the kdmrc of a previously installed kdm.\n"
2873 " Default is to scan " KDE_CONFDIR
" and\n"
2874 " {/usr,/usr/local,{/opt,/usr/local}/{kde4,kde,kde3}}/share/config.\n"
2876 " Do not look at older xdm/kdm configurations, just create default config.\n"
2878 " Do not look at older xdm configurations.\n"
2880 " Do not look at older kdm configurations.\n"
2882 " Directly use all scripts from the older xdm/kdm configuration.\n"
2883 " --no-old-scripts\n"
2884 " Do not use scripts from the older xdm/kdm configuration even if it lives\n"
2885 " in the new target directory.\n"
2887 " Directly use all ancillary config files from the older xdm/kdm\n"
2888 " configuration. This is usually a bad idea.\n"
2890 " Overwrite/delete old config files instead of backing them up.\n"
2892 " Do not put the notice about --in being used into the generated README.\n"
2896 if (!strcmp( argv
[ap
], "--no-old" )) {
2900 if (!strcmp( argv
[ap
], "--old-scripts" )) {
2904 if (!strcmp( argv
[ap
], "--no-old-scripts" )) {
2905 no_old_scripts
= True
;
2908 if (!strcmp( argv
[ap
], "--old-confs" )) {
2912 if (!strcmp( argv
[ap
], "--no-old-xdm" )) {
2916 if (!strcmp( argv
[ap
], "--no-old-kde" )) {
2920 if (!strcmp( argv
[ap
], "--no-backup" )) {
2924 if (!strcmp( argv
[ap
], "--no-in-notice" )) {
2925 no_in_notice
= True
;
2929 if (!strcmp( argv
[ap
], "--in" ))
2931 else if (!strcmp( argv
[ap
], "--old-xdm" ))
2933 else if (!strcmp( argv
[ap
], "--old-kde" ))
2935 else if (!strcmp( argv
[ap
], "--face-src" ))
2938 fprintf( stderr
, "Unknown command line option '%s', try --help\n", argv
[ap
] );
2941 if (ap
+ 1 == argc
|| argv
[ap
+ 1][0] == '-') {
2942 fprintf( stderr
, "Missing argument to option '%s', try --help\n", argv
[ap
] );
2945 *where
= argv
[++ap
];
2947 if (memcmp( newdir
, KDMCONF
, sizeof(KDMCONF
) ))
2950 if (!mkdirp( newdir
, 0755, "target", True
))
2953 makeDefaultConfig();
2957 if ((dir
= opendir( newdir
))) {
2960 while ((ent
= readdir( dir
))) {
2962 if (!strcmp( ent
->d_name
, "." ) || !strcmp( ent
->d_name
, ".." ))
2964 l
= sprintf( bn
, "%s/%s", newdir
, ent
->d_name
); /* cannot overflow (kernel would not allow the creation of a longer path) */
2965 if (!stat( bn
, &st
) && !S_ISREG( st
.st_mode
))
2967 if (no_backup
|| !memcmp( bn
+ l
- 4, ".bak", 5 ))
2973 for (; bfl
; bfl
= bfl
->next
)
2974 displace( bfl
->str
);
2978 if (!mergeKdmRcNewer( oldkde
, True
) && !mergeKdmRcOld( oldkde
)) {
2980 "Cannot read pre-existing kdmrc at specified location\n" );
2983 } else if (!no_old_kde
) {
2984 for (i
= 0; i
< as(oldkdes
); i
++) {
2985 if (i
&& !strcmp( oldkdes
[0], oldkdes
[i
] ))
2987 if (mergeKdmRcNewer( oldkdes
[i
], 0 )) {
2988 oldkde
= oldkdes
[i
];
2991 mergeKdmRcOld( oldkdes
[i
] ); /* only prints a message */
2995 #define SHR_CONF "/share/config"
2996 int olen
= strlen( oldkde
);
2997 if (olen
< (int)sizeof(SHR_CONF
) ||
2998 memcmp( oldkde
+ olen
- sizeof(SHR_CONF
) + 1,
2999 SHR_CONF
, sizeof(SHR_CONF
) ))
3002 "Warning: --old-kde does not end with " SHR_CONF
". "
3003 "Might wreak havoc.\n" );
3006 ASPrintf( (char **)&oldkdepfx
,
3007 "%.*s", olen
- sizeof(SHR_CONF
) + 1, oldkde
);
3009 } else if (!no_old_xdm
) {
3011 XrmQString
= XrmPermStringToQuark( "String" );
3013 if (!mergeXdmCfg( oldxdm
)) {
3015 "Cannot read xdm-config at specified location\n" );
3019 for (i
= 0; i
< as(oldxdms
); i
++)
3020 if (mergeXdmCfg( oldxdms
[i
] )) {
3021 oldxdm
= oldxdms
[i
];
3027 * How to proceed with pre-existing scripts (which are named in the config):
3028 * - old_scripts set or some scripts in new target already => keep 'em
3029 * - no_old_scripts set or all scripts outside new target => pretend that
3030 * the old config did not reference them in the first place
3035 locals
= foreigns
= False
;
3036 for (cs
= config
; cs
; cs
= cs
->next
)
3037 if (!strcmp( cs
->spec
->name
, "-Core" )) {
3038 for (ce
= cs
->ents
; ce
; ce
= ce
->next
)
3040 (!strcmp( ce
->spec
->key
, "Setup" ) ||
3041 !strcmp( ce
->spec
->key
, "Startup" ) ||
3042 !strcmp( ce
->spec
->key
, "Reset" )))
3044 if (inNewDir( ce
->value
))
3053 "Warning: both local and foreign scripts referenced. "
3054 "Will not touch any.\n" );
3055 mixed_scripts
= True
;
3058 for (cs
= config
; cs
; cs
= cs
->next
) {
3059 if (!strcmp( cs
->spec
->name
, "Xdmcp" )) {
3060 for (ce
= cs
->ents
; ce
; ce
= ce
->next
)
3061 if (!strcmp( ce
->spec
->key
, "Willing" ))
3062 ce
->active
= ce
->written
= False
;
3063 } else if (!strcmp( cs
->spec
->name
, "-Core" )) {
3064 for (cep
= &cs
->ents
; (ce
= *cep
); ) {
3066 (!strcmp( ce
->spec
->key
, "Setup" ) ||
3067 !strcmp( ce
->spec
->key
, "Startup" ) ||
3068 !strcmp( ce
->spec
->key
, "Reset" ) ||
3069 !strcmp( ce
->spec
->key
, "Session" )))
3071 if (!memcmp( cs
->name
, "X-*-", 4 ))
3072 ce
->active
= ce
->written
= False
;
3087 if (!stat( "/etc/debian_version", &st
)) { /* debian */
3089 defmaxuid
= "29999";
3090 } else if (!stat( "/usr/portage", &st
)) { /* gentoo */
3092 defmaxuid
= "65000";
3093 } else if (!stat( "/etc/mandrake-release", &st
)) { /* mandrake - check before redhat! */
3095 defmaxuid
= "65000";
3096 } else if (!stat( "/etc/redhat-release", &st
)) { /* redhat */
3098 defmaxuid
= "65000";
3099 } else /* if (!stat( "/etc/SuSE-release", &st )) */ { /* suse */
3101 defmaxuid
= "65000";
3105 defmaxuid
= "65000";
3107 for (i
= 0; i
< CONF_MAX_PRIO
; i
++)
3108 for (cs
= config
; cs
; cs
= cs
->next
)
3109 for (ce
= cs
->ents
; ce
; ce
= ce
->next
)
3110 if (ce
->spec
->func
&& i
== ce
->spec
->prio
)
3111 ce
->spec
->func( ce
, cs
);
3112 f
= createFile( "kdmrc", kdmrcmode
);
3116 f
= createFile( "README", 0644 );
3118 "This automatically generated configuration consists of the following files:\n" );
3119 fprintf( f
, "- " KDMCONF
"/kdmrc\n" );
3120 for (fp
= aflist
; fp
; fp
= fp
->next
)
3121 fprintf( f
, "- %s\n", fp
->str
);
3122 if (use_destdir
&& !no_in_notice
)
3124 "All files destined for " KDMCONF
" were actually saved in %s; "
3125 "this config will not be workable until moved in place.\n", newdir
);
3126 if (uflist
|| eflist
|| cflist
|| lflist
) {
3129 "This config was derived from existing files. As the used algorithms are\n"
3130 "pretty dumb, it may be broken.\n" );
3133 "Information from these files was extracted:\n" );
3134 for (fp
= uflist
; fp
; fp
= fp
->next
)
3135 fprintf( f
, "- %s\n", fp
->str
);
3139 "These files were directly incorporated:\n" );
3140 for (fp
= lflist
; fp
; fp
= fp
->next
)
3141 fprintf( f
, "- %s\n", fp
->str
);
3145 "These files were copied verbatim:\n" );
3146 for (fp
= cflist
; fp
; fp
= fp
->next
)
3147 fprintf( f
, "- %s\n", fp
->str
);
3151 "These files were copied with modifications:\n" );
3152 for (fp
= eflist
; fp
; fp
= fp
->next
)
3153 fprintf( f
, "- %s\n", fp
->str
);
3155 if (!no_backup
&& !use_destdir
)
3157 "Old files that would have been overwritten were renamed to <oldname>.bak.\n" );
3160 "\nTry 'genkdmconf --help' if you want to generate another configuration.\n"
3161 "\nYou may delete this README.\n" );