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