aboutsummaryrefslogtreecommitdiff
path: root/riemann.fmi.uni-sofia.bg/programs/nlogin-0.3-pre/nlogin.c
blob: ab0128b8a00ca983d1e68ba9e0ee7831c43029b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* login.c */
#define LOGIN_PROGRAM
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <termios.h>
#include "config.h"
#include "str_defs.h"
#include "pw_defs.h"
#include "utmp_defs.h"
#include "prot_defs.h"

#define SD(A,B) !str_diffn(A, B, sizeof(A))
#define SC(A,B) str_copynz(A, B, sizeof(A))

static void myexit(int n,char *s) 
  { write(2,s,str_len(s)); write(2,"\n",1); _exit(n); }

int main(int argc, char **argv, char **env) {
  struct passwd *pw=0;
  struct spwd *spwd;
  char buf[1200], lastlog[96];
  char *tty, *dev_tty=0, *program, *username=0, *p;
  char *arg[8] = {buf,0,0,0, 0,0,0,0};
  int fd,r,OK=0,flag_auto=0;
  struct termios oldtermios;

  if (ioctl(0, TCGETS, &oldtermios)) _exit(100);
  oldtermios.c_lflag &= ~(ECHO|ISIG);
  tcsetattr(0,TCSAFLUSH,&oldtermios);

  if ((dev_tty=ttyname(0)) && !str_diffn("/dev/",dev_tty,5)) tty=dev_tty+5;
  else { dev_tty = 0; tty="UNKNOWN"; }

  program=strip_slash(argv[0]);
  argv++; (void)argc;
  while ((p=argv[0]) && p[0] == '-') {
    if (p[1]=='f') {
      if (getuid()) goto do_it;

      if (p[2]) p += 2;
      else p=argv[1];

      if (p && *p && *p != '-') { 
	flag_auto=1;
	argv[0]=p;
	break;
      } else 
	goto do_it;
    }
    argv++;
  }
  
  if (argv[0] == 0) goto do_it;
  if (flag_auto == 0)
    if (read_password(buf)) goto do_it;

  pw = nv_getpwnam(argv[0]);
  if (pw) {
    username = pw->pw_name;
    if (pw->pw_passwd[0]=='*' || 
	pw->pw_passwd[0]=='!') goto do_it;
  }
  if (!username || *username == 0)  goto do_it;

  if (flag_auto==1) OK=1;
  else {
    if ((spwd = nv_getspnam(username))==0) goto do_it;
    OK = pass_check(buf, spwd->sp_pwdp);
  }

 do_it:
  byte_zero(buf,sizeof(buf));
  oldtermios.c_lflag |= ECHO;
  tcsetattr(0, TCSAFLUSH, &oldtermios);
  if (!username) username="UNKNOWN";

  log_do(buf,OK, program,username,tty);

  if (!OK) { sleep(1); myexit(100,"Sorry :-)"); }
  utmp_do(username, tty, getpid());
  lastlog_do(lastlog, pw->pw_uid, tty);
  get_tz(0,-1);

  if (dev_tty) {
    struct group *gr = nv_getgrnam("tty");
    chown(dev_tty, pw->pw_uid, gr ? gr->gr_gid : pw->pw_gid);
    chmod(dev_tty, 0620);
  }

  p = 0;
  if (nv_initgroups(pw->pw_name,pw->pw_gid) == -1) p = "groups";
  else if (setgid(pw->pw_gid) == -1) p = "gid";
  else if (setuid(pw->pw_uid) == -1) p = "uid";
  if (p) {
    mycat(buf, "unable to set", p);
    myexit(111, buf);
  }

  if (chdir(pw->pw_dir)) {
    r = mycat(buf,"unable to chdir: ",pw->pw_dir); buf[r++] = '\n';
    write(1,buf,r);
    chdir("/");
  }
  
  if ((fd=open(".hushlogin", O_RDONLY)) >=0) {
    close(fd);
  } else {
    if ((fd=open("/etc/motd", O_RDONLY)) != -1) {
      while ((r=read(fd,buf,sizeof buf)) >0) write(1,buf,r);
      close(fd);
    }
    write(1, lastlog, str_len(lastlog));
  }
 
  p=buf;     p += 1 + mycat(p,"-",strip_slash(pw->pw_shell));
  arg[2]=p;  p += 1 + mycat(p,"HOME=",pw->pw_dir);
  arg[3]=p;  p += 1 + mycat(p,"USER=",pw->pw_name);
  arg[4]=p;  p += 1 + mycat(p,"SHELL=",pw->pw_shell);
  for (; *env; env++)
    if (!str_diffn(*env,"TERM=",5)) {arg[5]=*env; break;}  /* arg[7] */

  oldtermios.c_lflag |= ISIG;
  tcsetattr(0, TCSAFLUSH, &oldtermios);
  execve(pw->pw_shell,arg,arg+2);
  return(1);
}