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