initial-freebsd-port-work-20010414
[openafs.git] / src / login / login.c
1 /*
2  * Notes:
3  *
4  * This is an AFS-aware login.
5  *
6  * Machine/os specific code is surrounded by #ifdef <system>
7  *
8  * The Q_SETUID and Q_DOWARN #ifdefs are for IBM's AOS which doesn't
9  * define them if NFS is configured. Like that matters anymore
10  */
11
12 /*
13  * Copyright (c) 1980, 1987, 1988 The Regents of the University of California.
14  * All rights reserved.
15  *
16  * Redistribution and use in source and binary forms are permitted
17  * provided that the above copyright notice and this paragraph are
18  * duplicated in all such forms and that any documentation,
19  * advertising materials, and other materials related to such
20  * distribution and use acknowledge that the software was developed
21  * by the University of California, Berkeley.  The name of the
22  * University may not be used to endorse or promote products derived
23  * from this software without specific prior written permission.
24  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
26  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27  */
28
29 #ifndef lint
30 char copyright[] =
31 "@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\
32  All rights reserved.\n";
33 #endif /* not lint */
34
35 /*
36  * login [ name ]
37  * login -h hostname    (for telnetd, etc.)
38  * login -f name        (for pre-authenticated login: datakit, xterm, etc.)
39  */
40
41 #if !defined(UT_NAMESIZE)
42 #define UT_NAMESIZE 8
43 #endif
44
45 #include <afs/param.h>
46 #include <unistd.h>
47 #include <stdlib.h>
48 #include <limits.h>
49 #include <afs/kautils.h>
50 #ifdef  AFS_SUN5_ENV
51 #include <sys/fs/ufs_quota.h>
52 #else
53 #if  !defined(AFS_HPUX_ENV) && !defined(AFS_AIX_ENV)
54 #if defined(AFS_SUN_ENV) || (defined(AFS_ATHENA_STDENV) && !defined(AFS_DEC_ENV)) || defined(AFS_OSF_ENV)
55 #include <ufs/quota.h>
56 #elif defined(AFS_FBSD_ENV)
57 #include <ufs/ufs/quota.h>
58 #else
59 #include <sys/quota.h>
60 #endif
61 #endif /* AIX */
62 #endif /* SUN5 */
63 #include <sys/stat.h>
64 #include <sys/time.h>
65 #include <sys/resource.h>
66 #include <sys/file.h>
67 #ifdef  AFS_SUN5_ENV
68 #include <sys/termios.h>
69 #include <sys/ttychars.h>
70 /* hack to get it to build */
71 #define CBRK    0377
72 #include <sys/ttydev.h>
73 #include <sys/ttold.h>
74 #include <sys/filio.h>
75 #endif
76 #ifdef AFS_FBSD_ENV
77 #define USE_OLD_TTY 1
78 #include <sys/ttydefaults.h>
79 #endif
80 #include <sys/ioctl.h>
81
82 #include <utmp.h>
83 #ifdef  AFS_SUN5_ENV
84 #include <utmpx.h>
85 #include <dirent.h>
86 #endif
87 #include <signal.h>
88 #if !defined(AIX) && !defined(AFS_HPUX_ENV) && !defined(AFS_AIX32_ENV) && !defined(AFS_FBSD_ENV)
89 #include <lastlog.h>
90 #endif
91 #include <errno.h>
92 #if defined(AIX)
93 #include <stand.h>
94 #undef B300
95 #undef B1200
96 #undef B9600
97 #include <sys/termio.h>
98 #include <sys/syslog.h>
99 #include <fcntl.h>
100 #else
101 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV)
102 #include <ttyent.h>
103 #endif
104 #if defined(AFS_HPUX_ENV)
105 #include <sgtty.h>
106 #include <sys/bsdtty.h>
107 #endif
108 #include <syslog.h>
109 #endif
110 #include <grp.h>
111 #include <pwd.h>
112 #include <setjmp.h>
113 #include <stdio.h>
114 #include <string.h>
115 #include <time.h>
116
117 #define TTYGRPNAME      "tty"           /* name of group to own ttys */
118
119 #define MOTDFILE        "/etc/motd"
120
121 #if defined(AFS_SUN5_ENV) || defined(AFS_HPUX100_ENV)
122 #ifndef NO_MAIL
123 #ifdef V4FS
124 #define MAILDIR         "/var/mail/"
125 #else
126 #define MAILDIR         "/usr/mail/"
127 #endif /* V4FS */
128 static char mail[30];
129 #endif /* NO_MAIL */
130 #else /* AFS_SUN5_ENV || AFS_HPUX100_ENV */
131 #define MAILDIR         "/usr/spool/mail"
132 #endif /* AFS_SUN5_ENV || AFS_HPUX100_ENV */
133
134 #define NOLOGIN         "/etc/nologin"
135 #define HUSHLOGIN       ".hushlogin"
136 #define LASTLOG         "/usr/adm/lastlog"
137 #define BSHELL          "/bin/sh"
138 #define SECURETTY_FILE  "/etc/securetty"
139
140 /*
141  * This bounds the time given to login.  Not a define so it can
142  * be patched on machines where it's too small.
143  */
144 int     timeout = 300;
145
146 struct  passwd *pwd, *getpwnam();
147 int     failures;
148 char    term[64], *hostname, *username, *tty;
149 #ifdef  AFS_OSF_ENV
150 char    ousername[256];
151 #endif
152 struct  sgttyb sgttyb;
153
154 #ifdef  AFS_SUN5_ENV
155 #include <deflt.h>
156 extern char *defread(), *strdup();
157 static  void    defaults();
158 static  char    *Pndefault      = "/etc/default/login";
159 static  char    *Altshell       = NULL;
160 static  char    *Console        = NULL;
161 static  int     Idleweeks       = -1;
162 static  char    *Passreq        = NULL;
163 #define DEFUMASK        022
164 static  mode_t  Umask           = DEFUMASK;
165 static  char    *Def_tz         = NULL;
166 static  char    *tmp_tz         = NULL;
167 static  char    *Def_hertz      = NULL;
168 #define SET_FSIZ        2                       /* ulimit() command arg */
169 static  long    Def_ulimit      = 0;
170 #define MAX_TIMEOUT     (15 * 60)
171 #define DEF_TIMEOUT     5*60
172 static  unsigned Def_timeout    = DEF_TIMEOUT;
173 static  char    *Def_path       = NULL;
174 static  char    *Def_supath     = NULL;
175 #define DEF_PATH        "/usr/bin:"     /* same as PATH */
176 #define DEF_SUPATH      "/usr/sbin:/usr/bin" /* same as ROOTPATH */
177 /*
178  * Intervals to sleep after failed login
179  */
180 #ifndef SLEEPTIME
181 #       define  SLEEPTIME 4     /* sleeptime before login incorrect msg */
182 #endif
183 static int      Sleeptime = SLEEPTIME;
184
185 #include <shadow.h>
186 /* This is for Solaris's shadow pass struc */
187 static struct spwd *spwd;
188 char    *ttypmt = NULL;
189 char    *d_tz = NULL;
190 char    *d_dev= NULL;
191 static int authenticated_remote_user = 0;
192 static char rhost[64], rusername[10], lusername[10];
193 #endif
194 #ifdef  AFS_SUN_ENV
195 int     usererr = -1;
196 #endif
197
198 /* For setting of TZ environment on HPUX */
199 #ifdef AFS_HPUX_ENV
200 #define MAX_TZ_LEN 256
201 static char TZ[MAX_TZ_LEN];
202 #endif /* AFS_HPUX_ENV */
203
204 #ifdef AFS_KERBEROS_ENV
205 extern char *ktc_tkt_string();
206 #endif
207
208 #if !defined(AIX) && !defined(AFS_HPUX_ENV)
209 struct  tchars tc = {
210 /*      CINTR, CQUIT, CSTART, CSTOP, 000, 000 */
211         CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
212 };
213
214 struct  ltchars ltc = {
215         CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
216 };
217 #endif
218
219 #ifdef  AFS_OSF_ENV
220 #include <sia.h>
221 #include <paths.h>
222 SIAENTITY *entity=NULL;
223
224 #ifdef  AFS_OSF20_ENV
225 #include <sys/security.h>
226 #endif
227 #include <prot.h>
228 #endif
229
230 #ifndef NOPAG
231 #define NOPAG   0xffffffff
232 #endif
233
234 /* For avoiding making an osi_audit call when non-root */
235 osi_audit() 
236 {
237 return 0;
238 }
239
240 static void
241 timedout(x)
242 {
243         fprintf(stderr, "Login timed out after %d seconds\n", timeout);
244         exit(0);
245 }
246
247 char *cv2string(ttp, aval)
248     register char *ttp;
249     register unsigned long aval;
250 {
251     register char *tp = ttp;
252     register int  i;
253     int any = 0;
254     
255     *(--tp) = 0;
256     while (aval != 0) {
257         i = aval % 10;
258         *(--tp) = '0' + i;
259         aval /= 10;
260         any = 1;
261     }
262     if (!any)
263         *(--tp) = '0';
264     return tp;
265 }
266
267 #include "AFS_component_version_number.c"
268
269
270 #ifdef  AFS_SUN5_ENV
271 struct utmpx utmp;
272 #else
273 struct utmp utmp;
274 #endif
275
276 #if     defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
277 /* the following utmp field is used for user counting: */
278 #define how_to_count ut_exit.e_exit
279 char *ttyntail;
280 #define SUBLOGIN        "<!sublogin>"
281 int sublogin;
282 main(argc, argv, renvp)
283 char **renvp;
284 #else
285 main(argc, argv)
286 #endif
287         int argc;
288         char **argv;
289 {
290         extern int errno, optind;
291         extern char *optarg, **environ;
292         struct group *gr, *getgrnam();
293         register int ch;
294         register char *p;
295         int ask, fflag, hflag, rflag, pflag, cnt, locl, zero = 0, dflag=0, rlog=0;
296         int quietlog, passwd_req, ioctlval;
297         char *domain, *salt, *envinit[2], *ttyn=0, *pp;
298         char tbuf[MAXPATHLEN + 2];
299         char *ttyname(), *stypeof(), *crypt(), *getpass();
300         extern off_t lseek();
301         int local, code = 0;
302         char *lcell;                    /* local cellname */
303         char  realm[MAXKTCREALMLEN];
304         char buf1[256], **envp;
305         afs_int32 j, pagval = NOPAG, ngroups, groups[NGROUPS_MAX];
306         long password_expires = -1;
307         extern  char*   AFSVersion;     /* generated version */
308         int afsLoginFail=0;
309         char *reason;
310
311 #if defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
312         char retry_chdir = 0;
313 #endif /* AFS_SUN5_ENV || AFS_HPUX_ENV */
314
315 #ifdef  AFS_OSF_ENV
316         char tname[sizeof(_PATH_TTY) + 10], *loginname=NULL;
317         int oargc = argc;
318         char **oargv = argv;
319
320 #else
321 #ifdef  AFS_SUN5_ENV
322
323         defaults();                                     /* Set up Defaults and flags */
324         if (Umask < 0 || ((mode_t) 0777) < Umask)       /* Set up default umask */
325             Umask = DEFUMASK;
326         (void) umask(Umask);
327
328         if (Def_timeout > MAX_TIMEOUT)                  /* Set up default timeouts and delays */
329             Def_timeout = MAX_TIMEOUT;
330         if (Sleeptime < 0 || Sleeptime > 5)
331             Sleeptime = SLEEPTIME;
332         (void) alarm(Def_timeout);
333 #else
334         (void)alarm((u_int)timeout);
335 #endif
336         (void)signal(SIGALRM, timedout);
337 #endif
338         (void)signal(SIGQUIT, SIG_IGN);
339         (void)signal(SIGINT, SIG_IGN);
340 #if !defined(AIX) && !defined(AFS_HPUX_ENV)
341         (void)setpriority(PRIO_PROCESS, 0, 0);
342 #endif
343 #ifdef Q_SETUID
344         (void)quota(Q_SETUID, 0, 0, 0);
345 #endif /* Q_SETUID */
346         
347         /*
348          * -p is used by getty to tell login not to destroy the environment
349          * -f is used to skip a second login authentication 
350          * -h is used by other servers to pass the name of the remote
351          *    host to login so that it may be placed in utmp and wtmp
352          */
353         (void)gethostname(tbuf, sizeof(tbuf));
354         domain = strchr(tbuf, '.');
355
356 #ifdef  AFS_HPUX_ENV
357         /*
358          * Set flag to disable the pid check if you find that you are
359          * a subsystem login.
360          */
361         sublogin = 0;
362         if (*renvp && strcmp(*renvp,SUBLOGIN) == 0)
363                 sublogin = 1;
364 #endif
365         fflag = hflag = pflag = rflag = 0;
366         memset(&utmp, '\0', sizeof(utmp));
367         passwd_req = 1;
368 #ifdef  AFS_SUN_ENV
369 #ifdef  AFS_SUN5_ENV
370         while ((ch = getopt(argc, argv, "fh:prd")) != -1) {
371 #else
372         while ((ch = getopt(argc, argv, "fh:pr")) != -1) {
373 #endif
374 #else
375         while ((ch = getopt(argc, argv, "fh:p")) != EOF) {
376 #endif
377 /*printf("ch='%c'\n", ch);*/
378                 switch (ch) {
379                 case 'f':
380                         fflag = 1;
381                         break;
382                 case 'h':
383 #ifdef  AFS_SUN_ENV
384                         if (hflag || rflag) {
385                             fprintf(stderr,"Only one of -r and -h allowed\n");
386                             exit(1);
387                         }
388 #endif
389                         if (getuid()) {
390                                 fprintf(stderr,
391                                     "login: -h for super-user only.\n");
392
393                                 exit(1);
394                         }
395                         rlog = 1;
396                         hflag = 1;
397                         if (domain && (p = strchr(optarg, '.')) &&
398                             strcasecmp(p, domain) == 0)
399                                 *p = 0;
400                         hostname = optarg;
401                         break;
402 #ifdef  AFS_SUN_ENV
403                 case 'r':
404                         if (hflag || rflag) {
405                             fprintf(stderr,"Only one of -r and -h allowed\n");
406                             exit(1);
407                         }
408                         if (argv[2] == 0)
409                                 exit(1);
410 #ifndef AFS_SUN5_ENV
411 /*                      fflag = 1;*/
412 #endif
413                         rflag = 1;
414 #ifndef AFS_SUN5_ENV
415                         usererr = doremotelogin(argv[2]);
416                         strncpy(utmp.ut_host, argv[2], sizeof(utmp.ut_host));
417                         argc -= 2;
418                         argv += 2;
419 #endif
420                         continue;
421
422                         break;
423 #ifdef  AFS_SUN5_ENV
424                 case 'd':       /* Ignode the '-d device' option for now!!! */
425                         dflag = 0;      /* XXX */
426                         d_dev = *++argv;
427                         argc--;
428                         break;
429 #endif
430 #endif
431                 case 'p':
432                         pflag = 1;
433                         break;
434                 case '?':
435                 default:
436                         fprintf(stderr, "usage: login [-fp] [username]\n");
437                         exit(1);
438                 }
439             }
440         argc -= optind;
441         argv += optind;
442 #ifdef  AFS_SUN5_ENV
443         if (rflag)
444             strcpy(rhost, *argv++);
445         if (hflag) {
446             if ( argv[0] && (*argv[0] != '-')) {
447                 if ((!strncmp(*argv, "TERM=", strlen("TERM=")))) {
448                     strncpy(term, &((*argv)[strlen("TERM=")]), sizeof(term));
449                 }
450             }
451             ask = 1;
452         } else
453 #endif
454 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
455         if (!rflag && *argv) {
456 #else
457         if (*argv) {
458 #endif
459 #ifdef  AFS_OSF_ENV
460                 memset(ousername,'\0',sizeof(ousername));
461                 strcpy(ousername,*argv);
462                 loginname=ousername;
463 #else
464                 username = *argv;
465 #endif
466                 ask = 0;
467         } else {
468 #ifdef  AFS_SUN5_ENV
469             ttypmt = getenv("TTYPROMPT");
470             if (ttypmt && (*ttypmt != '\0')) {
471                 extern char **getargs();
472                 /*
473                  * if ttyprompt is set, there should be data on the stream already. 
474                  */
475                 if ((envp = getargs(buf1)) != (char**)NULL) {
476                     username =  *envp;
477                 }
478             }
479             ask = 0;
480 #else
481 #ifdef  AFS_SUN_ENV
482             if (rflag)
483                 ask = 0;
484             else
485 #endif
486             ask = 1;
487 #endif
488         }
489         ioctlval = 0;
490 #if !defined(AIX) && !defined(AFS_HPUX_ENV) && !defined(AFS_OSF_ENV)
491         (void)ioctl(0, TIOCLSET, &ioctlval);
492
493         (void)ioctl(0, TIOCNXCL, 0);
494
495         (void)fcntl(0, F_SETFL, ioctlval);
496         (void)ioctl(0, TIOCGETP, &sgttyb);
497 #ifdef  AFS_SUN_ENV
498         (void)ioctl(0, FIONBIO, &zero);
499         (void)ioctl(0, FIOASYNC, &zero);
500         (void)ioctl(0, TIOCLGET, &locl);
501         /*
502          * If talking to an rlogin process,
503          * propagate the terminal type and
504          * baud rate across the network.
505          */
506 #ifdef  AFS_SUN5_ENV
507         if (rflag) {
508             doremotelogin();
509 #else
510         if (rflag || rlog) {
511                 doremoteterm(term, &sgttyb);
512 #endif
513             }
514         locl &= LPASS8;
515         locl |= LCRTBS|LCTLECH|LDECCTQ;
516         if (sgttyb.sg_ospeed >= B1200)
517                 locl |= LCRTERA|LCRTKIL;
518         (void)ioctl(0, TIOCLSET, &locl);
519 #endif
520         sgttyb.sg_erase = CERASE;
521         sgttyb.sg_kill = CKILL;
522         (void)ioctl(0, TIOCSLTC, &ltc);
523         (void)ioctl(0, TIOCSETC, &tc);
524 #ifdef  AFS_SUN5_ENV
525         if (!rflag)
526 #endif
527         (void)ioctl(0, TIOCSETP, &sgttyb);
528 #endif /* AIX  */
529         for (cnt = getdtablesize(); cnt > 2; cnt--)
530                 close(cnt);
531 #ifdef  AFS_SUN52_ENV
532         if (dflag) {
533             ttyn = d_dev;
534         } else
535 #endif
536         if (ttyn == NULL) {
537         ttyn = ttyname(0);
538         if (ttyn == NULL || *ttyn == '\0') {
539 #ifdef  AFS_OSF_ENV
540                 (void)sprintf(tname, "%s??", _PATH_TTY);
541                 ttyn = tname;
542 #else
543                 ttyn = "/dev/tty??";
544 #endif
545
546         }
547         }
548 #ifdef  AFS_HPUX_ENV
549         ttyntail = ttyn + sizeof("/dev/") - 1;
550 #endif
551         if (tty = strrchr(ttyn, '/'))
552                 ++tty;
553         else
554                 tty = ttyn;
555
556         openlog("login", LOG_ODELAY, LOG_AUTH);
557
558 #ifdef  AFS_OSF_ENV
559 #define _PATH_HUSHLOGIN ".hushlogin"
560 #define _PATH_MAILDIR   "/var/spool/mail"
561 #ifndef _PATH_DEFPATH
562 #define _PATH_DEFPATH   "/usr/bin:."
563 #endif
564     {
565         int cnt;
566         int authret=0, doafs=0;
567         char    shell[PATH_MAX+1] = _PATH_BSHELL, *pass, user[40], ouser[40];
568         int (*sia_collect)()=sia_collect_trm;
569         int getloginp(), uid;
570         struct passwd *pwd;
571
572 /*printf("loginname=%s,  ttyn=%s, fflag=%d\n", loginname, ttyn, fflag);*/
573         quietlog=0;
574         if((sia_ses_init(&entity, oargc, oargv, hostname, loginname, ttyn, 1, NULL)) == SIASUCCESS) {
575             static int useGetPass = 0;
576             int cnt1 = 0, first=0;
577             char *prompt, *reason, pword[BUFSIZ];
578             /***** SIA SESSION AUTHENTICATION *****/
579             if(!fflag) {
580                 for(cnt=5; cnt; cnt--) {
581                     doafs = 0;
582                     if (first++ || !entity->name) {
583                         clean_entity_pwd(entity);
584                         if (getloginp(entity) < 0) {
585                             printf("Illegal login name\n");
586                             doafs = -1;
587                             break;
588                         }
589                     }
590                     strcpy(user, entity->name);
591                     prompt = "Password:";
592                     if ((pwd = getpwnam(user))) {
593                         if (!strcmp(pwd->pw_passwd, "X")) {
594                             doafs = 1;
595                         }
596                     }
597                     if (useGetPass) {
598                         pass = getpass(prompt);
599                     } else {
600                         code = ka_UserReadPassword(prompt, pword, sizeof(pword), &reason);
601                         pass = pword;
602                         if (code) {
603                             if (code != KANULLPASSWORD) {
604                                 if (++cnt1 > 3)
605                                     useGetPass = 1;
606                             }
607                             fprintf(stderr, "Unable to read password because %s\n", reason);
608                             continue;
609                         }
610                     }
611
612                     if (!pwd) {
613                        printf("Login incorrect\n"); fflush(stdout);
614                        continue;
615                     }
616
617                     if (doafs || ((authret=sia_ses_authent(sia_collect,pass,entity)) == SIASUCCESS)) {
618                         if (doafs) {
619                             uid = pwd->pw_uid;
620                             sia_make_entity_pwd(pwd, entity);
621                         } else {
622                             uid = entity->pwd->pw_uid;
623                             pwd = entity->pwd;          
624                         }
625 doafs:
626                             authret = do_afs_auth(pwd, pass, doafs);
627                             if (!authret) {
628                                 strcpy(ouser, user);                            
629                                 printf("Login incorrect\n"); fflush(stdout);
630                                 continue;
631                             }
632
633                         printf("AFS (R) %s Login\n", AFSVersion);
634
635                         if (uid) {
636                             groups[0] = groups[1] = 0;
637                             ngroups = getgroups(NGROUPS, groups);
638                             pagval = get_pag_from_groups(groups[0], groups[1]);
639                         }
640                         break;
641                     } else if (authret & SIASTOP) {
642                         break;
643                     }
644                     else if ( authret == SIAFAIL ) {
645                                                         /* why did it fail ? */
646                         struct ttyent *ptr;
647                         setttyent();
648                         /* 
649                         ** if the "ptys" command does not exist in the
650                         ** /etc/securettys file, then root login's are
651                         ** allowed only from the console
652                         */
653                         if ( !pwd->pw_uid )             /* for root */
654                             if (((ptr=getttynam("ptys"))==NULL) || 
655                                 !( ptr->ty_status & TTY_SECURE))
656                             {
657                                 printf("root login refused on this terminal\n");
658                                 continue;
659                             }
660                     }
661                     if (doafs || (authret != SIASUCCESS)) {
662                         uid = pwd->pw_uid;
663                         sia_make_entity_pwd(pwd, entity);
664                         goto doafs;
665                     }
666                     printf("login incorrect\n");
667                 }
668                 if(cnt <= 0 || (doafs == -1)) {
669                     sia_ses_release(&entity);
670                     exit(1);
671                 }
672             }
673             /***** SIA SESSION ESTABLISHMENT *****/
674             if(sia_ses_estab(sia_collect,entity) == SIASUCCESS) {
675                 /*
676                  * Display and update lastlog file entry.  -DAL003
677                  */
678                 quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
679                 if(!quietlog)
680                     quietlog = !*entity->pwd->pw_passwd && !usershell(entity->pwd->pw_shell);
681                 if (!entity->tty)
682                     dolastlog(quietlog);
683                 /* END DAL003 */
684 #ifdef AFS_KERBEROS_ENV
685                 (void)chown(ktc_tkt_string(), pwd->pw_uid, pwd->pw_gid);
686 #endif /* AFS_KERBEROS_ENV */
687                 /***** SIA LAUNCHING SESSION *****/
688                 if(sia_ses_launch(sia_collect,entity) == SIASUCCESS) {
689                     ngroups = getgroups(NGROUPS, groups);
690                     if ((pagval != NOPAG) && 
691                         (afs_get_pag_from_groups(groups[0], groups[1])) == NOPAG) {
692                         /* we will have to shift grouplist to make room for pag */
693                         if (ngroups + 2 > NGROUPS) {
694                             perror("Too many groups");          /* XXX */
695                             exit (3);
696                         }
697                         for (j = ngroups - 1; j >= 0; j--) {
698                             groups[j + 2] = groups[j];
699                         }
700                         ngroups += 2;
701                         get_groups_from_pag(pagval, &groups[0], &groups[1]);
702                         seteuid(0);     /* Since the seteuid was set the user already */
703                         if (setgroups(ngroups, groups) == -1) {
704                             perror("setgroups");
705                             exit(3);
706                         }
707                         seteuid(entity->pwd->pw_uid);   /* Set euid back */
708                     }
709                     /****** Nothing left to fail *******/
710                     if(setreuid(geteuid(),geteuid()) < 0) {
711                         perror("setreuid()");
712                         exit(3);
713                     }
714                     /****** set up environment   *******/
715                     /* destroy environment unless user has requested preservation */
716                     envinit[0] = envinit[1] = 0;
717                     if (environ) for (cnt = 0; environ[cnt] != NULL; cnt++)
718                         if (!strncmp(environ[cnt], "TERM=", 5)) {
719                             envinit[0] = environ[cnt];
720                             break;
721                         }
722                     if (!pflag)
723                         environ = envinit;
724                     (void)setenv("HOME", entity->pwd->pw_dir, 1);
725                     if(entity->pwd->pw_shell && *entity->pwd->pw_shell)
726                         strncpy(shell, entity->pwd->pw_shell, sizeof shell);
727                     (void)setenv("SHELL", shell, 1);
728                     if (term[0] == '\0')
729                         (void)strncpy(term, stypeof(tty), sizeof(term));
730                     (void)setenv("TERM", term, 0);
731                     (void)setenv("USER", entity->pwd->pw_name, 1);
732                     (void)setenv("LOGNAME", entity->pwd->pw_name, 1);
733                     (void)setenv("PATH", _PATH_DEFPATH, 0);
734 #ifdef AFS_KERBEROS_ENV
735                     (void)setenv("KRBTKFILE", ktc_tkt_string(), 0);
736 #endif /* AFS_KERBEROS_ENV */
737                     if (!quietlog) {
738                         struct stat st;
739                                 
740                         motd();
741                         (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, entity->pwd->pw_name);
742                         if (stat(tbuf, &st) == 0 && st.st_size != 0)
743                             (void)printf("You have %smail.\n", (st.st_mtime > st.st_atime) ?  "new " : "");
744                     }
745                     /******* Setup default signals **********/
746                     (void)signal(SIGALRM, SIG_DFL);
747                     (void)signal(SIGQUIT, SIG_DFL);
748                     (void)signal(SIGINT, SIG_DFL);
749                     (void)signal(SIGTSTP, SIG_IGN);
750                     
751                     tbuf[0] = '-';
752                     (void)strcpy(tbuf + 1, (p = rindex(shell, '/')) ? p + 1 : shell);
753                     sia_ses_release(&entity);
754                     execlp(shell, tbuf, 0);
755                     (void)printf("login: no shell: %s.\n", strerror(errno));
756                     exit(0);
757                 }
758                 /***** SIA session launch failure *****/
759             }
760             /***** SIA session establishment failure *****/
761         }
762         if (entity != NULL) {
763             sia_ses_release(&entity);
764         }
765         syslog(LOG_ERR, " LOGIN FAILURE ");
766         exit(1);
767     }
768 #else /* AFS_OSF_ENV */
769 #ifdef AFS_HPUX_ENV
770         {   /* This block sets TZ environment on HPUX */
771             /* First set TZ environment here, so that
772                LOGIN FAILURE will get correct time stamp.
773                For logins from console, -p flag is not set,
774                the TZ environment set here will be cleared later.
775                We're gonna set it once again later after it's cleared.
776             */ 
777             FILE *fp;
778             char buf[MAX_TZ_LEN];
779             char *env_p=NULL;
780             int tz_incorrect=0;
781
782             /* set TZ only if tz_incorrect
783                (*env_p==0 or env_p==0 ) and there is a correct /etc/TIMEZONE
784                otherwise, just let it be default (US eastern on HP)
785             */
786             env_p = getenv("TZ");
787             if (!env_p)
788                 tz_incorrect = 1;
789             else if (!(*env_p)) 
790                 tz_incorrect = 1;
791             
792             if (tz_incorrect) {
793                 /* HP UX 10.0 or later has different file format */
794 #ifdef AFS_HPUX100_ENV
795                 /* /etc/TIMEZONE file example (HP-UX 10 or later)
796                    TZ=EST5EDT
797                    export TZ
798                 */
799                 fp = fopen ("/etc/TIMEZONE","r");
800                 if (fp) {
801                     if ( (fgets (buf, sizeof(buf), fp)) != NULL ) {
802                         buf[strlen(buf)-1] = 0;
803                         if (!strncmp (buf, "TZ=", 3)) {
804                             strncpy (TZ, buf, MAX_TZ_LEN);
805                             putenv (TZ);
806                         }
807                     }
808                     fclose(fp);
809                 }
810 #else /* AFS_HPUX100_ENV */
811                 /* /etc/src.sh file example (HP-UX 9 or earlier)
812                    SYSTEM_NAME=myname; export SYSTEM_NAME
813                    TZ=EST5EDT; export TZ
814                 */
815                 fp = fopen ("/etc/src.sh","r");
816                 if (fp) {
817                     while ( (fgets (buf, sizeof(buf), fp)) != NULL ) {
818                         buf[strlen(buf)-1] = 0;
819                         if (!strncmp (buf, "TZ=", 3)) {
820                             char *p = strchr (buf, ';');
821                             if (p) *p = 0;
822                             strncpy (TZ, buf, MAX_TZ_LEN);
823                             putenv (TZ);
824                         }
825                     }
826                     fclose(fp);
827                 }
828 #endif /* AFS_HPUX100_ENV */
829             }
830             else {
831                 *TZ = 0;
832             }
833         }
834 #endif /* AFS_HPUX_ENV */
835         for (cnt = 0;; ask = 1) {
836                 ioctlval = 0;
837 #if !defined(AIX) && !defined(AFS_HPUX_ENV)
838                 (void)ioctl(0, TIOCSETD, &ioctlval);
839 #endif /* !AIX and !hpux */
840
841                 if (ask | !username) {
842                         fflag = 0;
843                         getloginname(1);
844                 }
845                 /*
846                  * Note if trying multiple user names;
847                  * log failures for previous user name,
848                  * but don't bother logging one failure
849                  * for nonexistent name (mistyped username).
850                  */
851                 if (failures && strcmp(tbuf, username)) {
852                         if (failures > (pwd ? 0 : 1))
853                                 badlogin(tbuf);
854                         failures = 0;
855                 }
856                 (void)strcpy(tbuf, username);
857                 salt = "xx";
858 #ifdef  AFS_SUN5_ENV
859                 if ((pwd = getpwnam(username)) && (spwd = getspnam(username))) {
860                     initgroups(username, pwd->pw_gid);  /* XXX */
861                     salt = spwd->sp_pwdp;
862                 }
863 #else /* if !SUN5 */
864                 if (pwd = getpwnam(username))
865                         salt = pwd->pw_passwd;
866 #endif /* else !SUN5 */
867
868                 /* if user not super-user, check for disabled logins */
869                 if (pwd == NULL || pwd->pw_uid) {
870                         checknologin();
871                     }
872
873                 /*
874                  * Disallow automatic login to root; if not invoked by
875                  * root, disallow if the uid's differ.
876                  */
877                 if (fflag && pwd) {
878                         uid_t uid = getuid();
879
880                         /*
881                          *  allow f flag only if user running login is
882                          *  same as target user or superuser
883                          */
884                         fflag = (uid == 0) || (uid == pwd->pw_uid);
885                         if (fflag) passwd_req = 0;
886 /*                      passwd_req = pwd->pw_uid == 0 || (uid && uid != pwd->pw_uid);*/
887                 }
888
889                 /*
890                  * If no pre-authentication and a password exists
891                  * for this user, prompt for one and verify it.
892                  */
893                 if (!passwd_req || (pwd && !*pwd->pw_passwd)) {
894                         break;
895                     }
896 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
897                 if (!usererr) 
898                     break;
899 #endif
900 #if !defined(AIX) && !defined(AFS_HPUX_ENV)
901                 setpriority(PRIO_PROCESS, 0, -4);
902 #endif
903
904                 /*
905                  * The basic model for logging in now, is that *if* there
906                  * is a kerberos record for this individual user we will
907                  * trust kerberos (provided the user really has an account
908                  * locally.)  If there is no kerberos record (or the password
909                  * were typed incorrectly.) we would attempt to authenticate
910                  * against the local password file entry.  Naturally, if
911                  * both fail we use existing failure code.
912                  */
913                 if(pwd)
914                   {
915                     char pword[BUFSIZ];
916                     int cnt1 =0;
917                     static int useGetPass = 0;
918
919                     if(useGetPass) {
920                         pp = getpass("Password:");
921                         memcpy(pword, pp, 8);
922                     } else {
923                         code = ka_UserReadPassword("Password:",
924                                                         pword,
925                                                         sizeof(pword),
926                                                         &reason);
927                         
928                         if(code) {
929                             if (code != KANULLPASSWORD) {
930                                 if (++cnt1 > 5)
931                                     useGetPass = 1;
932                             }
933                             fprintf(stderr,
934                                     "Unable to read password because %s\n",
935                                     reason);
936                             goto loginfailed;
937                         }
938                     }
939                     pp = pword;
940                     if(ka_UserAuthenticateGeneral(
941                            KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
942                            pwd->pw_name, /* kerberos name */
943                            (char *)0, /* instance */
944                            (char *)0, /* realm */
945                             pp, /* password */
946                             0, /* default lifetime */
947                             &password_expires,
948                             0, /* spare 2 */
949                             &reason /* error string */
950                             )) {
951
952                         afsLoginFail = 1;
953                         pword[8] = '\0';
954                     } else {
955                         if(strcmp(pwd->pw_passwd,"*"))
956                             break; /* out of for loop */
957 #if !defined(AIX) && !defined(AFS_HPUX_ENV)
958                         (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL);
959 #endif /* AIX */
960                         goto loginfailed;
961                       }
962                 } else {
963                     pp = getpass("Password:");
964                 }
965
966                 p = crypt(pp, salt);
967                 (void) memset(pp, '\0', strlen(pp));
968 #ifdef  AFS_SUN5_ENV
969                 if (spwd && !strcmp(p, spwd->sp_pwdp))
970 #else
971                 if (pwd && !strcmp(p, pwd->pw_passwd))
972 #endif
973                 {
974                    /* Only print this if local authentication is successful */
975                    if (afsLoginFail) {
976                       printf("Unable to authenticate to AFS because %s\n", reason);
977                       printf("proceeding with local authentication...\n");
978                    }
979                    afsLoginFail = 0;
980                    break;
981                 }
982                 afsLoginFail = 0;
983
984               loginfailed:
985                 printf("Login incorrect\n");
986                 failures++;
987                 /* we allow 10 tries, but after 3 we start backing off */
988                 if (++cnt > 3) {
989                         if (cnt >= 6) {
990                                 badlogin(username);
991 #if !defined(AIX) && !defined(AFS_HPUX_ENV)
992                                 (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL);
993 #endif /* AIX */
994                                 (void)close(0);
995                                 (void)close(1);
996                                 (void)close(2);
997                                 sleep(10);
998                                 exit(1);
999                         }
1000                         sleep((u_int)((cnt - 3) * 5));
1001                 }
1002             }
1003 #if !defined(AIX) && !defined(AFS_HPUX_ENV)
1004         setpriority(PRIO_PROCESS, 0, 0);
1005 #endif /* AIX */
1006 #ifdef  AFS_SUN5_ENV
1007         /*  Exits if root login not on system console. */
1008         if (pwd->pw_uid == 0) {
1009             if ((Console != NULL) && (strcmp(ttyn, Console) != 0)) {
1010                 (void) printf("Not on system console\n");
1011                 exit(10);
1012             }
1013             if (Def_supath != NULL)
1014                 Def_path = Def_supath;
1015             else
1016                 Def_path = DEF_SUPATH;
1017         }
1018 #endif /* AFS_SUN5_ENV */
1019
1020         printf("AFS (R) %s Login\n", AFSVersion); /* generated version */
1021
1022         /* committed to login -- turn off timeout */
1023         (void)alarm((u_int)0);
1024
1025         /*
1026          * If valid so far and root is logging in, see if root logins on
1027          * this terminal are permitted.
1028          */
1029 #if !defined(AIX) && !defined(AFS_SUN5_ENV)
1030 #ifdef  AFS_HPUX_ENV
1031          /* This is the /etc/securetty feature.  We wanted to 1st prompt for a
1032          * password even if we know that this is not a securetty because
1033          * we don't want to give any clue if the potential intruder guesses
1034          * the correct password.
1035          */
1036         if ((pwd->pw_uid == 0) && !rootterm(ttyn+sizeof("/dev/")-1)) {
1037 #else
1038         if (pwd->pw_uid == 0 && !rootterm(tty)) {
1039 #endif
1040                 if (hostname)
1041                         syslog(LOG_NOTICE, "ROOT LOGIN REFUSED FROM %s",
1042                             hostname);
1043                 else
1044                         syslog(LOG_NOTICE, "ROOT LOGIN REFUSED ON %s", tty);
1045                 printf("Login incorrect\n");
1046
1047                 /*
1048                 Reset tty line.
1049                 */
1050
1051                 (void)chmod(ttyn,0666);
1052
1053                 sleepexit(1);
1054         }
1055 #endif /* !AIX & !SUN5 */
1056 #ifdef Q_SETUID
1057         if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
1058                 switch(errno) {
1059                 case EUSERS:
1060                         fprintf(stderr,
1061                 "Too many users logged on already.\nTry again later.\n");
1062                         break;
1063                 case EPROCLIM:
1064                         fprintf(stderr,
1065                             "You have too many processes running.\n");
1066                         break;
1067                 default:
1068                         perror("quota (Q_SETUID)");
1069                 }
1070
1071                 /*
1072                 Reset tty line.
1073                 */
1074
1075                 (void)chmod(ttyn,0666);
1076
1077                 sleepexit(0);
1078         }
1079 #endif /* Q_SETUID */
1080
1081         /* For Solaris and HP, we might want to chdir later for remotely 
1082            mounted home directory because home direcotry may be
1083            protected now
1084         */
1085         if (chdir(pwd->pw_dir) < 0) {
1086 #if !defined(AFS_SUN5_ENV) && !defined(AFS_HPUX_ENV)
1087                 printf("No directory %s!\n", pwd->pw_dir);
1088 #endif /* !defined(AFS_SUN5_ENV) && !defined(AFS_HPUX_ENV) */
1089                 if (chdir("/"))
1090                 {
1091
1092                         /*
1093                         Reset tty line.
1094                         */
1095
1096                         (void)chmod(ttyn,0666);
1097
1098                         exit(0);
1099                 }
1100
1101 #if !defined(AFS_SUN5_ENV) && !defined(AFS_HPUX_ENV)
1102                 pwd->pw_dir = "/";
1103                 printf("Logging in with home = \"/\".\n");
1104 #else /* !defined(AFS_SUN5_ENV) && !defined(AFS_HPUX_ENV) */
1105                 retry_chdir = 1;
1106 #endif /* !defined(AFS_SUN5_ENV) && !defined(AFS_HPUX_ENV) */
1107         }
1108
1109         /* nothing else left to fail -- really log in */
1110         {
1111 #ifdef  AFS_SUN5_ENV
1112                 long tlen;
1113                 struct utmpx *utx, *getutxent(), *pututxline();
1114 #endif
1115 #if defined(AFS_HPUX_ENV)
1116                 register struct utmp *u = (struct utmp *) 0;
1117                 extern pid_t getpid();
1118 #endif
1119
1120 #ifdef  AFS_SUN5_ENV
1121                 (void)time(&utmp.ut_tv.tv_sec);
1122 #else
1123                 (void)time(&utmp.ut_time);
1124 #endif
1125                 strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
1126 #if !defined(AIX) /*&& !defined(AFS_SUN5_ENV)*/
1127                 if (hostname)
1128                         strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
1129 #endif
1130                 strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
1131 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1132                 utmp.ut_type = USER_PROCESS;
1133                 if (!strncmp(ttyn, "/dev/", strlen("/dev/"))) {
1134                   strncpy(utmp.ut_line, &(ttyn[strlen("/dev/")]), sizeof(utmp.ut_line));
1135                 }
1136
1137                 utmp.ut_pid = getpid();
1138                 if ((!strncmp(tty, "tty", strlen("tty"))) ||
1139                     (!strncmp(tty, "pty", strlen("pty"))) ) {
1140                   strncpy(utmp.ut_id, &(tty[strlen("tty")]), sizeof(utmp.ut_id));
1141                 }
1142 #endif /* AFS_HPUX_ENV */
1143 #ifdef  AFS_HPUX_ENV
1144                 /*
1145                  * Find the entry for this pid (or line if we are a sublogin)
1146                  * in the utmp file.
1147                  */
1148                 while ((u = getutent()) != NULL) {
1149                     if ( (u->ut_type == INIT_PROCESS ||
1150                           u->ut_type == LOGIN_PROCESS ||
1151                           u->ut_type == USER_PROCESS)
1152                         && ( (sublogin &&
1153                               strncmp(u->ut_line,ttyntail,sizeof(u->ut_line))==0) ||
1154                             u->ut_pid == utmp.ut_pid) ) {
1155
1156                         /*
1157                          * Copy in the name of the tty minus the
1158                          * "/dev/", the id, and set the type of entry
1159                          * to USER_PROCESS.
1160                          */
1161                         (void) strncpy(utmp.ut_line, ttyntail, sizeof(utmp.ut_line));
1162                         utmp.ut_id[0] = u->ut_id[0];
1163                         utmp.ut_id[1] = u->ut_id[1];
1164                         utmp.ut_id[2] = u->ut_id[2];
1165                         utmp.ut_id[3] = u->ut_id[3];
1166                         utmp.ut_type = USER_PROCESS;
1167                         utmp.how_to_count = add_count();
1168
1169                         /*
1170                          * Copy remote host information
1171                          */
1172                         strncpy(utmp.ut_host, u->ut_host, sizeof(utmp.ut_host));
1173                         utmp.ut_addr = u->ut_addr;
1174
1175                         /* Return the new updated utmp file entry. */
1176                         pututline(&utmp);
1177                         break;
1178                 }
1179         }
1180         endutent();             /* Close utmp file */
1181 #endif
1182 #ifdef  AFS_SUN5_ENV
1183                 utmp.ut_syslen = (tlen = strlen(utmp.ut_host)) ? min(tlen+1, sizeof(utmp.ut_host)) : 0;
1184                 strncpy(utmp.ut_user, username, sizeof(utmp.ut_user));
1185                 while ((utx = getutxent()) != NULL) {
1186                     if ((utx->ut_type == INIT_PROCESS || utx->ut_type == LOGIN_PROCESS ||
1187                          utx->ut_type == USER_PROCESS) && (utx->ut_pid == utmp.ut_pid)) {
1188                         strncpy(utmp.ut_line,(ttyn+sizeof("/dev/")-1), sizeof(utmp.ut_line));
1189                         utmp.ut_id[0] = utx->ut_id[0];
1190                         utmp.ut_id[1] = utx->ut_id[1];
1191                         utmp.ut_id[2] = utx->ut_id[2];
1192                         utmp.ut_id[3] = utx->ut_id[3];
1193                         utmp.ut_type = USER_PROCESS;
1194                         pututxline(&utmp);
1195                         break;
1196                     }
1197                 }
1198                 endutxent();            /* Close utmp file */
1199                 if (!utx) {
1200                     printf("No utmpx entry.  You must exec 'login' from the lowest level 'sh'\n");
1201                     exit(1);
1202                 } else 
1203                     updwtmpx(WTMPX_FILE, &utmp);
1204 #else
1205                 login(&utmp);
1206 #endif
1207         }
1208
1209         quietlog = access(HUSHLOGIN, F_OK) == 0;
1210         dolastlog(quietlog);
1211
1212 #if !defined(AIX) && !defined(AFS_HPUX_ENV)
1213 #ifdef  AFS_SUN_ENV
1214         if (!hflag && !rflag) {                                 /* XXX */
1215 #else
1216         if (!hflag) {                                   /* XXX */
1217 #endif
1218                 static struct winsize win = { 0, 0, 0, 0 };
1219
1220                 (void)ioctl(0, TIOCSWINSZ, &win);
1221         }
1222 #endif /* !AIX and !hpux */
1223
1224 #ifdef  AFS_SUN5_ENV
1225         /*
1226          * Set the user's ulimit
1227          */
1228         if (Def_ulimit > 0L && ulimit(SET_FSIZ, Def_ulimit) < 0L)
1229             (void) printf("Could not set ULIMIT to %ld\n", Def_ulimit);
1230
1231 #endif
1232 #if     defined(AFS_SUN_ENV)
1233         /*
1234          * Set owner/group/permissions of framebuffer devices
1235          */
1236         (void) set_fb_attrs(ttyn, pwd->pw_uid, pwd->pw_gid);
1237 #endif
1238
1239         (void)chown(ttyn, pwd->pw_uid,
1240             (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
1241
1242
1243         (void)chmod(ttyn, 0620);
1244         (void)setgid(pwd->pw_gid);
1245
1246 #ifdef  AFS_HPUX_ENV
1247         if ((pwd->pw_gid < 0) || (pwd->pw_gid > MAXUID)) {
1248             printf("Bad group id.\n");
1249             exit(1);
1250         }
1251         if ((pwd->pw_uid < 0) || (pwd->pw_uid > MAXUID)) {
1252             printf("Bad user id.\n");
1253             exit(1);
1254         }
1255 #endif
1256
1257 #ifdef AFS_KERBEROS_ENV
1258         (void)chown(ktc_tkt_string(), pwd->pw_uid, pwd->pw_gid);
1259
1260 #endif
1261
1262         groups[0] = groups[1] = 0;
1263         ngroups = getgroups(NGROUPS_MAX, groups);
1264         pagval = get_pag_from_groups(groups[0], groups[1]);
1265         initgroups(username, pwd->pw_gid);
1266         ngroups = getgroups(NGROUPS_MAX, groups);
1267         if ((pagval != NOPAG) && 
1268             (afs_get_pag_from_groups(groups[0], groups[1])) == NOPAG) {
1269             /* we will have to shift grouplist to make room for pag */
1270             if (ngroups + 2 > NGROUPS_MAX) 
1271                 return E2BIG;           /* XXX */
1272             for (j = ngroups - 1; j >= 0; j--) {
1273                 groups[j + 2] = groups[j];
1274             }
1275             ngroups += 2;
1276             get_groups_from_pag(pagval, &groups[0], &groups[1]);
1277             if (setgroups(ngroups, groups) == -1) {
1278                 perror("setgroups");
1279                 return -1;
1280             }
1281         }
1282
1283 #ifdef Q_DOWARN
1284         quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
1285 #endif /* Q_DOWARN */
1286
1287         /* destroy environment unless user has requested preservation */
1288         if (!pflag) {
1289             envinit[0] = (char *)0;
1290             envinit[1] = (char *)0;
1291             environ = envinit;
1292         }
1293         (void)setuid(pwd->pw_uid);
1294
1295 #if defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
1296         /* This is the time to retry chdir for Solaris and HP
1297         */
1298         if (retry_chdir && chdir(pwd->pw_dir)<0) {
1299             printf ("No directory %s!\n", pwd->pw_dir);
1300             if (chdir("/")<0) {
1301                 /* reset tty line and exit */
1302                 (void)chmod(ttyn, 0666);
1303                 exit(0);
1304             }
1305             pwd->pw_dir = "/";
1306             printf ("Logging with home = \"/\".\n");
1307         }
1308 #endif /* AFS_SUN5_ENV || AFS_HPUX_ENV */
1309
1310         if (*pwd->pw_shell == '\0')
1311                 pwd->pw_shell = BSHELL;
1312 #if !defined(AIX) && !defined(AFS_HPUX_ENV) 
1313         /* turn on new line discipline for the csh */
1314         else if (!strcmp(pwd->pw_shell, "/bin/csh")) {
1315                 ioctlval = NTTYDISC;
1316                 (void)ioctl(0, TIOCSETD, &ioctlval);
1317         }
1318 #endif /* AIX */
1319 #ifdef  AFS_SUN5_ENV
1320          else {
1321             if (Altshell != NULL && strcmp(Altshell, "YES") == 0) {
1322                 (void)setenv("SHELL", pwd->pw_shell, 1);
1323             }
1324         }
1325         if (Def_tz != NULL) {
1326             tmp_tz = Def_tz;
1327         }
1328         Def_tz = getenv("TZ");
1329         if (Def_tz) {
1330             setenv("TZ", Def_tz, 1);
1331         } else {
1332             if (tmp_tz) {
1333                 Def_tz = tmp_tz;
1334                 setenv("TZ", Def_tz, 1);
1335             }
1336         }
1337         if (Def_hertz == NULL)
1338             (void)setenv("HZ", HZ, 1);
1339         else
1340             (void)setenv("HZ", Def_hertz, 1);
1341
1342 #endif
1343
1344 #ifdef AFS_HPUX_ENV
1345         /* if pflag is not set
1346            the TZ environment was cleared moments ago */
1347         if (*TZ && !pflag) {
1348             setenv ("TZ", &TZ[3], 1); 
1349         }
1350 #endif /* AFS_HPUX_ENV */
1351
1352         (void)setenv("HOME", pwd->pw_dir, 1);
1353         (void)setenv("SHELL", pwd->pw_shell, 1);
1354         if (term[0] == '\0')
1355                 strncpy(term, stypeof(tty), sizeof(term));
1356         (void)setenv("TERM", term, 0);
1357         (void)setenv("USER", pwd->pw_name, 1);
1358         (void)setenv("LOGNAME", pwd->pw_name, 1);
1359 #ifdef  AFS_SUN5_ENV
1360         if (Def_path == NULL)
1361             (void)setenv("PATH", DEF_PATH, 0);
1362         else
1363             (void)setenv("PATH", Def_path, 0);
1364 #else
1365         (void)setenv("PATH", "/usr/ucb:/bin:/usr/bin:", 0);
1366 #endif
1367
1368 #if     defined(AFS_SUN5_ENV) || defined(AFS_HPUX100_ENV)
1369 #ifndef NO_MAIL
1370         /* Sol, HP: set MAIL only if NO_MAIL is not set */
1371         sprintf (mail, "%s%s", MAILDIR, pwd->pw_name);
1372         (void)setenv("MAIL", mail, 0);
1373 #endif /* NO_MAIL */
1374 #endif /* AFS_SUN5_ENV || AFS_HPUX100_ENV */
1375
1376 #ifdef AFS_KERBEROS_ENV
1377         (void)setenv("KRBTKFILE", ktc_tkt_string(), 0);
1378 #endif
1379
1380         if (password_expires >= 0) {
1381             char sbuffer[100];
1382           (void)setenv("PASSWORD_EXPIRES", cv2string(&sbuffer[100], password_expires), 1);
1383         }
1384
1385         if (tty[sizeof("tty")-1] == 'd')
1386                 syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
1387         if (pwd->pw_uid == 0)
1388                 if (hostname)
1389                         syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s",
1390                             tty, hostname);
1391                 else
1392                         syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty);
1393
1394         if (!quietlog) {
1395                 struct stat st;
1396
1397 #if     ! defined(AFS_SUN5_ENV) && (! defined(AFS_HPUX_ENV))
1398                 /* In Solaris the shell displays motd */
1399                 /* On hp700s /etc/profile also does it so it's redundant here too */
1400                 motd();
1401                 /* Don't check email either, should be done in shell */
1402                 (void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name);
1403                 if (stat(tbuf, &st) == 0 && st.st_size != 0)
1404                         printf("You have %smail.\n",
1405                             (st.st_mtime > st.st_atime) ? "new " : "");
1406 #endif
1407         }
1408
1409         (void)signal(SIGALRM, SIG_DFL);
1410         (void)signal(SIGQUIT, SIG_DFL);
1411         (void)signal(SIGINT, SIG_DFL);
1412 #if !defined(AIX) && !defined(AFS_HPUX_ENV)
1413         (void)signal(SIGTSTP, SIG_IGN);
1414 #endif /* AIX */
1415
1416         tbuf[0] = '-';
1417         strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
1418             p + 1 : pwd->pw_shell);
1419         execlp(pwd->pw_shell, tbuf, 0);
1420         fprintf(stderr, "login: no shell: ");
1421         perror(pwd->pw_shell);
1422         exit(0);
1423 #endif /* else AFS_OSF_ENV */
1424 }
1425
1426 getloginname(prompt)
1427 int prompt;
1428 {
1429         register int ch;
1430         register char *p;
1431         static char nbuf[UT_NAMESIZE + 1];
1432
1433         for (;;) {
1434                 if (prompt) {
1435                     printf("login: ");
1436                     prompt = 0;
1437                 }
1438                 for (p = nbuf; (ch = getchar()) != '\n'; ) {
1439                         if (ch == EOF) {
1440                                 badlogin(username);
1441                                 exit(0);
1442                         }
1443                         if (p < nbuf + UT_NAMESIZE)
1444                                 *p++ = ch;
1445                 }
1446                 if (p > nbuf) {
1447                         if (nbuf[0] == '-')
1448                                 fprintf(stderr,
1449                                     "login names may not start with '-'.\n");
1450                         else {
1451                                 *p = '\0';
1452                                 username = nbuf;
1453                                 break;
1454                         }
1455                     } else prompt = 1;
1456         }
1457 }
1458
1459
1460 #ifdef  AFS_HPUX_ENV
1461 rootterm(tty)
1462 char *tty;
1463 {
1464     register FILE *fd;
1465     char buf[100];
1466
1467     /*
1468      * check to see if /etc/securetty exists, if it does then scan
1469      * file to see if passwd tty is in the file.  Return 1 if it is, 0 if not.
1470      */
1471     if ((fd = fopen(SECURETTY_FILE, "r")) == NULL)
1472         return(1);
1473     while (fgets(buf, sizeof buf, fd) != NULL) {
1474         buf[strlen(buf)-1] = '\0';
1475         if (strcmp(tty, buf) == 0) {
1476             fclose(fd);
1477             return(1);
1478         }
1479     }
1480     fclose(fd);
1481     return(0);
1482 }
1483 #endif
1484 #if !defined(AIX) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV)
1485 rootterm(ttyn)
1486         char *ttyn;
1487 {
1488         struct ttyent *t;
1489
1490         return((t = getttynam(ttyn)) && t->ty_status&TTY_SECURE);
1491 }
1492 #endif 
1493
1494 jmp_buf motdinterrupt;
1495
1496 motd()
1497 {
1498         register int fd, nchars;
1499         void (*oldint)();
1500         void sigint();
1501         char tbuf[8192];
1502
1503         if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0)
1504                 return;
1505         oldint = signal(SIGINT, sigint);
1506         if (setjmp(motdinterrupt) == 0)
1507                 while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
1508                         (void)write(fileno(stdout), tbuf, nchars);
1509         (void)signal(SIGINT, oldint);
1510         (void)close(fd);
1511 }
1512
1513 void
1514 sigint()
1515 {
1516         longjmp(motdinterrupt, 1);
1517 }
1518
1519 checknologin()
1520 {
1521         register int fd, nchars;
1522         char tbuf[8192];
1523
1524         if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) {
1525                 while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
1526                         (void)write(fileno(stdout), tbuf, nchars);
1527                 sleepexit(0);
1528         }
1529 }
1530
1531 #if defined(AIX) || defined(AFS_HPUX_ENV) || defined(AFS_AIX32_ENV)
1532 dolastlog(quiet)
1533         int quiet;
1534 {
1535   return 0;
1536 }
1537 #else
1538 #ifdef  AFS_OSF_ENV
1539 dolastlog(quiet)
1540     int quiet;
1541 {
1542 #define _PATH_LASTLOG   "/var/adm/lastlog"
1543     struct lastlog ll;
1544     int fd;
1545     struct passwd *pwd;
1546
1547     pwd = entity->pwd;
1548     if ((fd = open(_PATH_LASTLOG, (O_RDWR|O_CREAT), 0666)) < 0)
1549         fprintf(stderr, "Can't open %s", _PATH_LASTLOG);
1550     else {
1551         (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
1552         if (!quiet) {
1553             if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && ll.ll_time != 0) {
1554                 (void)printf("Last login: %.*s ", 24-5, (char *)ctime(&ll.ll_time));
1555                 if (*ll.ll_host != '\0')
1556                     (void)printf("from %.*s\n", sizeof(ll.ll_host), ll.ll_host);
1557                 else
1558                     (void)printf("on %.*s\n", sizeof(ll.ll_line), ll.ll_line);
1559             }
1560         }
1561         (void)close(fd);
1562     }
1563 }
1564 #else
1565 dolastlog(quiet)
1566         int quiet;
1567 {
1568         struct lastlog ll;
1569         int fd;
1570
1571         if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) {
1572                 (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
1573                 if (!quiet) {
1574                         if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
1575                             ll.ll_time != 0) {
1576                                 printf("Last login: %.*s ",
1577                                     24-5, (char *)ctime(&ll.ll_time));
1578                                 if (*ll.ll_host != '\0')
1579                                         printf("from %.*s\n",
1580                                             sizeof(ll.ll_host), ll.ll_host);
1581                                 else
1582                                         printf("on %.*s\n",
1583                                             sizeof(ll.ll_line), ll.ll_line);
1584                         }
1585                         (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
1586                 }
1587                 memset(&ll, '\0', sizeof(ll));
1588                 (void)time(&ll.ll_time);
1589                 strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
1590                 if (hostname)
1591                         strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
1592                 (void)write(fd, (char *)&ll, sizeof(ll));
1593                 (void)close(fd);
1594         }
1595 }
1596 #endif
1597 #endif /* AIX */
1598
1599 badlogin(name)
1600         char *name;
1601 {
1602         if (failures == 0)
1603                 return;
1604         if (hostname)
1605                 syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s",
1606                     failures, failures > 1 ? "S" : "", hostname, name);
1607         else
1608                 syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s",
1609                     failures, failures > 1 ? "S" : "", tty, name);
1610 }
1611
1612 #undef  UNKNOWN
1613 #ifdef  AFS_SUN5_ENV
1614 #define UNKNOWN "sun"
1615 #else
1616 #define UNKNOWN "su"
1617 #endif
1618
1619 #if defined(AIX) || defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1620 char *
1621 stypeof(ttyid)
1622         char *ttyid;
1623 {
1624         return(UNKNOWN);
1625 }
1626 #else
1627 char *
1628 stypeof(ttyid)
1629         char *ttyid;
1630 {
1631         struct ttyent *t;
1632
1633         return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
1634 }
1635 #endif
1636
1637 getstr(buf, cnt, err)
1638         char *buf, *err;
1639         int cnt;
1640 {
1641         char ch;
1642
1643         do {
1644                 if (read(0, &ch, sizeof(ch)) != sizeof(ch))
1645                         exit(1);
1646                 if (--cnt < 0) {
1647                         fprintf(stderr, "%s too long\r\n", err);
1648                         sleepexit(1);
1649                 }
1650                 *buf++ = ch;
1651         } while (ch);
1652 }
1653
1654 sleepexit(eval)
1655         int eval;
1656 {
1657         sleep((u_int)5);
1658         exit(eval);
1659 }
1660
1661     
1662 int get_pag_from_groups(g0, g1)
1663 afs_uint32 g0, g1;
1664 {
1665         afs_uint32 h, l, result;
1666
1667         g0 -= 0x3f00;
1668         g1 -= 0x3f00;
1669         if (g0 < 0xc000 && g1 < 0xc000) {
1670                 l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
1671                 h = (g0 >> 14);
1672                 h = (g1 >> 14) + h + h + h;
1673                 result =  ((h << 28) | l);
1674                 /* Additional testing */        
1675                 if (((result >> 24) & 0xff) == 'A')
1676                         return result;
1677                 else
1678                         return NOPAG;
1679         }
1680         return NOPAG;
1681 }
1682
1683
1684 get_groups_from_pag(pag, g0p, g1p)
1685 afs_uint32 pag;
1686 afs_uint32 *g0p, *g1p;
1687 {
1688         unsigned short g0, g1;
1689
1690         pag &= 0x7fffffff;
1691         g0 = 0x3fff & (pag >> 14);
1692         g1 = 0x3fff & pag;
1693         g0 |= ((pag >> 28) / 3) << 14;
1694         g1 |= ((pag >> 28) % 3) << 14;
1695         *g0p = g0 + 0x3f00;
1696         *g1p = g1 + 0x3f00;
1697 }
1698
1699
1700 #if     defined(AFS_SUN_ENV)
1701 /*
1702  * set_fb_attrs -- change owner/group/permissions of framebuffers
1703  *                 listed in /etc/fbtab.
1704  *
1705  * Note:
1706  * Exiting from set_fb_attrs upon error is not advisable
1707  * since it would disable logins on console devices.
1708  *
1709  * File format:
1710  * console mode device_name[:device_name ...]
1711  * # begins a comment and may appear anywhere on a line.
1712  *
1713  * Example:
1714  * /dev/console 0660 /dev/fb:/dev/cgtwo0:/dev/bwtwo0
1715  * /dev/console 0660 /dev/gpone0a:/dev/gpone0b
1716  *
1717  * Description:
1718  * The example above sets the owner/group/permissions of the listed
1719  * devices to uid/gid/0660 if ttyn is /dev/console
1720  */
1721
1722 #define FIELD_DELIMS    " \t\n"
1723 #define COLON           ":"
1724 #define COLON_C         ':'
1725 #define WILDCARD        "/*"
1726 #define WILDCARD_LEN    2
1727 #define MAX_LINELEN     256
1728 #ifdef AFS_SUN5_ENV
1729 #define FBTAB           "/etc/logindevperm"
1730 #else
1731 #define FBTAB           "/etc/fbtab"
1732 #endif
1733
1734
1735 set_fb_attrs(ttyn, uid, gid)
1736         char *ttyn;
1737         int uid;
1738         int gid;
1739 {
1740         char line[MAX_LINELEN];
1741         char *console;
1742         char *mode_str;
1743         char *dev_list;
1744         char *device;
1745         char *ptr;
1746         int  mode;
1747         long strtol();
1748         FILE *fp;
1749
1750         if ((fp = fopen(FBTAB, "r")) == NULL)
1751                 return;
1752         while (fgets(line, MAX_LINELEN, fp)) {
1753                 if (ptr = strchr(line, '#'))
1754                         *ptr = '\0';    /* handle comments */
1755                 if ((console = strtok(line, FIELD_DELIMS)) == NULL)
1756                         continue;       /* ignore blank lines */
1757                 if (strcmp(console, ttyn) != 0)
1758                         continue;       /* ignore non-consoles */
1759                 mode_str = strtok((char *)NULL, FIELD_DELIMS);
1760                 if (mode_str == NULL) {
1761                         (void) fprintf(stderr, "%s: invalid entry -- %s\n",
1762                                 FBTAB, line);
1763                         continue;
1764                 }
1765                 /* convert string to octal value */
1766                 mode = (int) strtol(mode_str, (char **)NULL, 8);
1767                 if (mode < 0 || mode > 0777) {
1768                         (void) fprintf(stderr, "%s: invalid mode -- %s\n",
1769                                 FBTAB, mode_str);
1770                         continue;
1771                 }
1772                 dev_list = strtok((char *)NULL, FIELD_DELIMS);
1773                 if (dev_list == NULL) {
1774                         (void) fprintf(stderr, "%s: %s -- empty device list\n",
1775                                 FBTAB, console);
1776                         continue;
1777                 }
1778 #ifdef  AFS_SUN5_ENV
1779                 device = strtok(dev_list, COLON);
1780                 while (device) {
1781                     ptr = strstr(device, WILDCARD);
1782                     if (ptr && 
1783                         (strlen(device) - (ptr - &device[0])) == WILDCARD_LEN){
1784                         /* The device was a (legally-specified) directory. */
1785                         DIR           *dev_dir;
1786                         struct dirent *dir_e;
1787                         char dev_file[MAXPATHLEN];
1788                         
1789                         *ptr = '\0'; /* Remove the wildcard from the dir name. */
1790                         if ((dev_dir = opendir(device)) == (DIR *) NULL) {
1791                             syslog(LOG_ERR, "bad device %s%s in %s, ignored",
1792                                    device, WILDCARD, FBTAB);
1793                             continue;
1794                         }
1795                         
1796                         /* Directory is open; alter its files. */
1797                         /* Must link with /usr/lib/libc.a before 
1798                            /usr/ucblib/libucb.a or the d_name structs
1799                            miss the first two characters of the filename */
1800                         while (dir_e = readdir(dev_dir)) {
1801                             if (strcmp(dir_e->d_name, "..") &&
1802                                 strcmp(dir_e->d_name, ".")) {
1803                                 strcpy(dev_file, device);
1804                                 strcat(dev_file, "/");
1805                                 strcat(dev_file, dir_e->d_name);
1806                                 (void) chown(dev_file, uid, gid);
1807                                 (void) chmod(dev_file, mode);
1808                             }
1809                         }
1810                         (void) closedir(dev_dir);
1811                     } else {
1812                         /* 'device' was not a directory, so we can just do it. */
1813                         (void) chown(device, uid, gid);
1814                         (void) chmod(device, mode);
1815                     }
1816                     device = strtok((char *)NULL, COLON); /* Move thru list. */
1817 #else
1818                 device = strtok(dev_list, COLON);
1819                 while (device) {
1820                         (void) chown(device, uid, gid);
1821                         (void) chmod(device, mode);
1822                         device = strtok((char *)NULL, COLON);
1823 #endif
1824                 }
1825         }
1826         (void) fclose(fp);
1827 }
1828 #endif
1829
1830
1831 #ifdef  AFS_SUN5_ENV
1832 static int quotec()
1833 {
1834         register int c, i, num;
1835
1836         switch( c = getc(stdin)) {
1837         case 'n':
1838                 c = '\n';
1839                 break;
1840         case 'r':
1841                 c = '\r';
1842                 break;
1843         case 'v':
1844                 c = '\013';
1845                 break;
1846         case 'b':
1847                 c = '\b';
1848                 break;
1849         case 't':
1850                 c = '\t';
1851                 break;
1852         case 'f':
1853                 c = '\f';
1854                 break;
1855         case '0':
1856         case '1':
1857         case '2':
1858         case '3':
1859         case '4':
1860         case '5':
1861         case '6':
1862         case '7':
1863                 for( num=0,i=0; i<3; i++ ) {
1864                     num = num * 8 + (c - '0');
1865                     if ((c = getc(stdin)) < '0' || c > '7')
1866                         break;
1867                 }
1868                 ungetc(c,stdin);
1869                 c = num & 0377;
1870                 break;
1871         default:
1872                 break;
1873         }
1874         return(c);
1875 }
1876
1877 static char **getargs(inline)
1878     char *inline;
1879 {
1880     static char envbuf[256];
1881     static char *args[63];
1882     register char *ptr,**answer;
1883     register int c;
1884     int state;
1885     extern int quotec();
1886
1887     for (ptr= envbuf; ptr < &envbuf[sizeof(envbuf)];) *ptr++ = '\0';
1888     for (answer= args; answer < &args[63];) *answer++ = (char *)NULL;
1889     for (ptr= envbuf,answer= &args[0],state = 0; (c = getc(stdin)) != EOF;) {
1890         *(inline++) = c;
1891         switch (c) {
1892           case '\n':
1893             if (ptr == &envbuf[0]) return((char **)NULL);
1894             else return(&args[0]);
1895           case ' ':
1896           case '\t':
1897             if (state == 1) {
1898                 *ptr++ = '\0';
1899                 state = 0;
1900             }
1901             break;
1902           case '\\':
1903             c = quotec();
1904           default:
1905             if (state == 0) {
1906                 *answer++ = ptr;
1907                 state = 1;
1908             }
1909             *ptr++ = c;
1910         }
1911         if (ptr == &envbuf[sizeof(envbuf)-1]) {
1912             ungetc('\n',stdin);
1913             putc('\n',stdout);
1914         }
1915     }
1916     exit(0);
1917 }
1918 #endif
1919
1920 #ifdef  AFS_SUN_ENV
1921 #ifdef  AFS_SUN5_ENV
1922 doremotelogin()
1923 {
1924     static struct passwd nouser = { "", "no:password", ~0 };
1925
1926     getstr(rusername, sizeof (rusername), "remuser");
1927     getstr(lusername, sizeof (lusername), "locuser");
1928     if (!username) username = lusername;
1929     getstr(term, sizeof (term), "Terminal type");
1930     if (getuid()) {
1931         pwd = &nouser;
1932         goto out;
1933
1934     }
1935     pwd = getpwnam(lusername);
1936     if (pwd == NULL) {
1937         pwd = &nouser;
1938         goto out;
1939     }
1940  out:
1941     doremoteterm(term);
1942     return;
1943 }
1944 #else
1945 doremotelogin(host)
1946     char *host;
1947 {
1948     int code;
1949     static char  rusername[100], lusername[100];
1950     static struct passwd nouser = { "", "no:password", ~0 };
1951
1952     getstr(rusername, sizeof (rusername), "remuser");
1953     getstr(lusername, sizeof (lusername), "locuser");
1954     if (!username) username = lusername;
1955     getstr(term, sizeof (term), "Terminal type");
1956     if (getuid()) {
1957         pwd = &nouser;
1958         return -1;
1959     }
1960     pwd = getpwnam(lusername);
1961     if (pwd == NULL) {
1962         pwd = &nouser;
1963         return -1;
1964     }
1965     code = ruserok(host, (pwd->pw_uid == 0), rusername, lusername);
1966 /*printf("DOREM=%d, host=%s, uid=%d, ruser=%s, luser=%s\n", code, host, pwd->pw_uid, rusername, lusername);*/
1967     return code;
1968 }
1969 #endif
1970
1971 char    *speeds[] =
1972         { "0", "50", "75", "110", "134", "150", "200", "300",
1973         "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
1974 #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0]))
1975
1976 #ifdef  AFS_SUN5_ENV
1977 doremoteterm(terminal)
1978 #else
1979 doremoteterm(terminal, tp)
1980     struct sgttyb *tp;
1981 #endif
1982     char *terminal;
1983 {
1984 #ifdef  AFS_SUN5_ENV
1985     struct termios tp;
1986 #endif
1987     register char *cp = strchr(terminal, '/'), **cpp;
1988     char *speed;
1989
1990 #ifdef  AFS_SUN5_ENV
1991     (void) ioctl(0, TCGETS, &tp);
1992 #endif
1993     if (cp) {
1994         *cp++ = '\0';
1995         speed = cp;
1996         cp = strchr(speed, '/');
1997         if (cp)
1998             *cp++ = '\0';
1999         for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
2000             if (strcmp(*cpp, speed) == 0) {
2001 #ifdef  AFS_SUN5_ENV
2002                 tp.c_cflag = ((tp.c_cflag & ~CBAUD) | ((cpp-speeds) & CBAUD));
2003 #else
2004                 tp->sg_ispeed = tp->sg_ospeed = cpp-speeds;
2005 #endif
2006                 break;
2007             }
2008     }
2009 #ifdef  AFS_SUN5_ENV
2010     tp.c_lflag = ECHO|ICANON|IGNPAR|ICRNL;
2011     (void) ioctl(0, TCSETS, &tp);
2012 #else
2013     tp->sg_flags = ECHO|CRMOD|ANYP|XTABS;
2014 #endif
2015 }
2016 #endif
2017
2018 #ifdef AFS_OSF_ENV
2019 /*
2020  *  Check if the specified program is really a shell (e.g. "sh" or "csh").
2021  */
2022 usershell(shell)
2023         char *shell;
2024 {
2025         register char *p;
2026         char *getusershell();
2027
2028         setusershell();
2029         while ((p = getusershell()) != NULL)
2030                 if (strcmp(p, shell) == 0)
2031                         break;
2032         endusershell();
2033         return(!!p);
2034 }
2035
2036 static char *getlinep(const char *string, int size, FILE *stream) {
2037     extern int errno;
2038     int c;
2039     char *cp;
2040
2041     errno = 0;
2042     if(!fgets(string, size, stream) || ferror(stream) || errno == EINTR)
2043         return NULL;
2044     else
2045         if(cp=index(string, '\n'))
2046             *cp = '\0';
2047         else
2048             while((c=getc(stdin)) != '\n' && c != EOF && errno != EINTR)
2049                 ;
2050     return string;
2051 }
2052
2053 clean_entity_pwd(SIAENTITY *entity) 
2054 {
2055     if (entity->acctname != NULL) {
2056         free(entity->acctname);
2057         entity->acctname = NULL;
2058     }
2059     if (entity->pwd != NULL) {
2060         if (entity->pwd->pw_name) {
2061             memset(entity->pwd->pw_name,'\0',strlen(entity->pwd->pw_name));
2062             free(entity->pwd->pw_name);
2063             entity->pwd->pw_name = NULL;
2064         }
2065         if (entity->pwd->pw_passwd) {
2066             memset(entity->pwd->pw_passwd,'\0',strlen(entity->pwd->pw_passwd));
2067             free(entity->pwd->pw_passwd);
2068             entity->pwd->pw_passwd = NULL;
2069         }
2070         if (entity->pwd->pw_comment) {
2071             memset(entity->pwd->pw_comment,'\0',strlen(entity->pwd->pw_comment));
2072             free(entity->pwd->pw_comment);
2073             entity->pwd->pw_comment = NULL;
2074         }
2075         if (entity->pwd->pw_gecos) {
2076             memset(entity->pwd->pw_gecos,'\0',strlen(entity->pwd->pw_gecos));
2077             free(entity->pwd->pw_gecos);
2078             entity->pwd->pw_gecos = NULL;
2079         }
2080         if (entity->pwd->pw_dir) {
2081             memset(entity->pwd->pw_dir,'\0',strlen(entity->pwd->pw_dir));
2082             free(entity->pwd->pw_dir);
2083             entity->pwd->pw_dir = NULL;
2084         }
2085         if (entity->pwd->pw_shell) {
2086             memset(entity->pwd->pw_shell,'\0',strlen(entity->pwd->pw_shell));
2087             free(entity->pwd->pw_shell);
2088             entity->pwd->pw_shell = NULL;
2089         }
2090         free(entity->pwd);
2091         entity->pwd = NULL;
2092     }
2093 }
2094
2095 int getloginp(entity)
2096     SIAENTITY *entity;
2097 {
2098     char result[100];
2099
2100     fputs("login: ", stdout);
2101     if (getlinep(result,sizeof result,stdin) == (char *) NULL) {
2102         return (-1);
2103     }
2104     entity->name = (char *)malloc(SIANAMEMIN+1);        
2105     if (entity->name == NULL)
2106         return (-1);
2107     strcpy((unsigned char *)entity->name, result); 
2108     return(1);
2109 }
2110
2111 #ifdef AFS_KERBEROS_ENV
2112 extern char *ktc_tkt_string();
2113 #endif
2114
2115 int do_afs_auth(pwd, pass, doafs) 
2116 struct passwd *pwd;
2117 char *pass;
2118 int doafs; {
2119     char *namep;
2120     int code, afsLoginFail=0;
2121     char *lcell, realm[MAXKTCREALMLEN], *pword, prompt[256];
2122     char *shell, *reason;
2123
2124 loop:
2125     if (pass) {
2126         pword = pass;
2127     } else {
2128         sprintf(prompt, "Enter AFS password: ");
2129         pword = getpass(prompt);
2130         if (strlen(pword) == 0) {
2131             printf("Unable to read password because zero length password is illegal\n");
2132             printf("Login incorrect\n"); fflush(stdout);
2133             goto loop;
2134         }
2135     }
2136
2137     if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
2138                                    pwd->pw_name, /* kerberos name */
2139                                    (char *)0, /* instance */
2140                                    (char *)0, /* realm */
2141                                    pword, /* password */
2142                                    0, /* default lifetime */
2143                                    0, /* spare 1 */
2144                                    0, /* spare 2 */
2145                                    &reason /* error string */)) {
2146         afsLoginFail = 1;
2147         if (doafs) return 0;
2148     } else {
2149         if (pwd->pw_passwd && strcmp(pwd->pw_passwd,"*")) 
2150             return 1;   /* Success */
2151     }
2152
2153     if (!pwd->pw_passwd) return 0;
2154     namep = crypt(pword, pwd->pw_passwd);
2155     code = strcmp(namep, pwd->pw_passwd) == 0 ? 1 : 0 ;
2156     if ((code == 1) && afsLoginFail) {
2157        /* Only print this if local authentication is successful */
2158        printf("Unable to authenticate to AFS because %s\n", reason);
2159        printf("proceeding with local authentication...\n");
2160     }
2161     return code;
2162 }
2163
2164
2165 #endif
2166
2167 #ifdef  AFS_SUN5_ENV
2168 static void defaults()
2169 {
2170     extern int defopen(), defcntl();
2171     register int  flags;
2172     register char *ptr;
2173
2174     if (defopen(Pndefault) == 0) {
2175         /*
2176          * ignore case
2177          */
2178         flags = defcntl(DC_GETFLAGS, 0);
2179         TURNOFF(flags, DC_CASE);
2180         defcntl(DC_SETFLAGS, flags);
2181
2182         if ((Console = defread("CONSOLE=")) != NULL)
2183             Console = strdup(Console);
2184         if ((Altshell = defread("ALTSHELL=")) != NULL)
2185             Altshell = strdup(Altshell);
2186         if ((Passreq = defread("PASSREQ=")) != NULL)
2187             Passreq = strdup(Passreq);
2188         if ((Def_tz = defread("TIMEZONE=")) != NULL)
2189             Def_tz = strdup(Def_tz);
2190         if ((Def_hertz = defread("HZ=")) != NULL)
2191             Def_hertz = strdup(Def_hertz);
2192         if ((Def_path   = defread("PATH=")) != NULL)
2193             Def_path = strdup(Def_path);
2194         if ((Def_supath = defread("SUPATH=")) != NULL)
2195             Def_supath = strdup(Def_supath);
2196         if ((ptr = defread("ULIMIT=")) != NULL)
2197             Def_ulimit = atol(ptr);
2198         if ((ptr = defread("TIMEOUT=")) != NULL)
2199             Def_timeout = (unsigned) atoi(ptr);
2200         if ((ptr = defread("UMASK=")) != NULL)
2201             if (sscanf(ptr, "%lo", &Umask) != 1)
2202                 Umask = DEFUMASK;
2203         if ((ptr = defread("IDLEWEEKS=")) != NULL)
2204             Idleweeks = atoi(ptr);
2205         if ((ptr = defread("SLEEPTIME=")) != NULL)
2206             Sleeptime = atoi(ptr);
2207         (void) defopen(NULL);
2208     }
2209     return;
2210 }
2211 #endif
2212
2213 #ifdef  AFS_HPUX_ENV
2214 /*
2215  * returns 1 if user should be counted as 1 user;
2216  * returns 3 if user should be counted as a pty
2217  * may return other stuff in the future
2218  */
2219 int
2220 add_count()
2221 {
2222     if (isapty()) {
2223         if (is_nlio())
2224             return(1);
2225         else
2226             return(3);
2227     } else
2228         return(1);
2229 }
2230
2231 /*
2232  * returns 1 if user is a pty, 0 otherwise
2233  */
2234 #define SSTRPTYMAJOR 157        /* major number for Streams slave pty's */
2235 #define SPTYMAJOR 17            /* major number for slave  pty's */
2236 #define PTYSC     0x00          /* select code for pty's         */
2237 #define select_code(x) (((x) & 0xff0000) >> 16)
2238 isapty()
2239 {
2240     struct stat sbuf;
2241     static int firsttime = 1;
2242     static int retval;
2243
2244     if (firsttime) {
2245         firsttime = 0;
2246         if (fstat(0, &sbuf) != 0 ||                /* can't stat */
2247             (sbuf.st_mode & S_IFMT) != S_IFCHR ||  /* not char special */
2248             major(sbuf.st_rdev) != SPTYMAJOR ||    /* not pty major num */
2249             select_code(sbuf.st_rdev) != PTYSC) {  /* not pty minor num */
2250                 /* Check to see if it is a Streams PTY */
2251                 if (major(sbuf.st_rdev) == SSTRPTYMAJOR) {
2252                         retval = 1;
2253                 }
2254                 else
2255                         retval = 0;     /* neither a BSD nor a Streams PTY */
2256         } else {
2257             retval = 1;
2258 #ifdef TRUX
2259             if (ISB1 && !remote_login)
2260                 retval=0;               /* local pty for td tty simulation */
2261 #endif /* TRUX */
2262         }
2263     }
2264     return(retval);
2265 }
2266
2267 #define NLIOUCOUNT      _IO('K',28)     /* _IO(K, 28) */
2268 #define NLIOSERV        0x4b33          /* (('K' << 8) + 51 */
2269
2270 /*
2271  * returns 1 if user is an NL server, else returns 0
2272  */
2273 is_nlio()
2274 {
2275     if (ioctl(0, NLIOUCOUNT) == NLIOSERV)
2276         return(1);
2277     else
2278         return(0);
2279 }
2280 #endif