📄 deslogind.c
字号:
cpuUsed = cpuTime(); loginTime = time((time_t *) 0) - loginTime; if (res != 0) { log( "%s: Logout %s on %u(%ld%c%ld) sec(CPU), %lu/%lu bytes in/out\n", progName, userName, loginTime, cpuUsed / 10, '.', cpuUsed % 10, inBytes, outBytes); } else { log("%s: Logout %s on %u(%ld%c%ld) sec(CPU), %lu/%lu bytes in/out (idle %u sec)\n", progName, userName, loginTime, cpuUsed / 10, '.', cpuUsed % 10, inBytes, outBytes, connTimeout / 1000); } exit(0); } /* child */ setProgName(); if (generic) { cargv[1] = loginArg1; cargv[2] = rhostName; } else { tz = getenv("TZ"); /* may fail by returning NULL; OK though */ if (uid == 0) { /* root user gets special path */ path = SYSTEMPATH; } cenv = setupEnv(userName, shell, cwd, path, tz, rhostName); res = chdir(cwd); if (res != 0) { log("%s: chdir to %s failed \"%s\"--%s\n", progName, cwd, ERRMSG); return 1; } oldmask = umask(newmask); /* documentation says umask cannot fail! */ /* * This code must be placed only in the child because of the atexit call * in the parent for updating utmp. This changes the uid, and gid now. */ setupUser(uid, gid, userName); /* exits if failure */ } if ((chp = strrchr(shell, '/')) == (char *) 0) chp = shell-1; chp++; arg0 = (char *) malloc(strlen(chp)+2); if (arg0 == (char *) 0) { log("%s: couldn't allocate %d bytes for arg0\n", progName, strlen(chp)+2); exit(1); } arg0[0] = '-'; /* make this a login shell */ memcpy(&arg0[1], chp, strlen(chp)+1); cargv[0] = arg0; /* * Sect4.3.2:157-177: * If the calling process is not a process group leader, the setsid() * function shall create a new session. The calling process shall be * the session leader of this new session, shall be be the process * group leader of a new process group, and shall have no controlling * terminal. The process group ID of the calling process shall be * set equal to the process ID of the calling process. The calling * process shall be the only process in the new proccess group and the * only process in the new session. * Upon successful completion, the setsid() function returns the value * of the process group ID of the calling process. Otherwise, a value of * -1 is returned and errno is set to indicate the error. * * EPERM - The calling process is already a process group leader, or * the process group ID of a process other than the calling process * matches the process id of the calling process * * D.A.B.: the fork() made sure that pgid != pid, and * we're not a pg leader because we didn't call setpgid. * * NOTE: getpgrp() expects an argument on BSD, but not POSIX. If * if you have BSD, (DEC MIPS, SunOS4.1), you should pass it 0. */ if (debug > 1) { log("%s: getpid: %ld\n", progName, (long) getpid()); log("%s: getpgrp: %ld\n", progName, (long) getpgrp()); } pid = setsid(); /* break control terminal affiliation; get sid */ /* * Any open of a terminal device after setsid without O_NOCCTY will likely * become the controlling terminal. */ if (pid == -1) { log("%s: setsid failed--%s\n", progName, ERRMSG); return 1; } if (debug > 1) { log("%s: setsid: %ld\n", progName, (long) pid); log("%s: getpid: %ld\n", progName, (long) getpid()); log("%s: getpgrp: %ld\n", progName, (long) getpgrp()); } close(0); /* actually, we should close ALL fd's here */ close(1); /* this should be all of them */ close(2); /* we made sure none of these are needed below */ close(nfd); /* they must be free for dup's to work */ if (pty) { close(masterpty); /* * This was designed to prevent someone from hooking upto the slave before * the child could. It doesn't. I've moved the close before the fork. */#if 0 /* must be as close as possible to the open * to reduce the race condition for someone hijacking the slave pty * before this process can get it. There needs to be a better way. * * There was a bug here if the parent still opened the slave as * a controlling terminal, and it hasn't closed slavepty before we do * here. That's why O_NOCTTY is specified to openPty above. */ close(slavepty); #endif /* * Sect7.2.3:753-765: * Upon successful completion, tcgetpgrp() returns the process group ID * of the foreground process group associated with the terminal. If * there is no foreground process group, tcgetpgrp() shall return a value * greater than 1 that does not match the process group ID of any * existing process group. Otherwise, a value of -1 is returned and * errno is set to indicate the error. * * EBADF - The filedes argument is not a valid file descriptor * ENOSYS - The tcgetprgp() function is not supported in this * implementation * ENOTTY - The calling process does not have a controlling terminal, * or the file is not the controlling terminal. */ /* * Establish a new control terminal by being the first process without * a controlling terminal to open a tty device. Non-POSIX, but * very common. * * The close must happen as close as possible with the open to prevent * hijacking of the slave side of the pty. Note that on some systems * this may cause the master to get notified and abort prematurely. I * don't think this exists now because of SIGCHLD being used instead. * * AnnexB:3884-3887: * POSIX.1 does not specify a mechanism by which to allocate a * controlling terminal...Historical implementations allocate controlling * terminals on certain open() calls...Some historical implementations * deallocate a controlling terminal on its last systemwide close. * This behavior is neither required nor prohibited. Even on * implementations that do provide this behavior, applications cannot * depend on it due to its systemwide nature. * * Sect5:204-206: O_NOCTTY if set, and path identifies a terminal device, * the open() function shall not cause the terminal device to become the * controlling terminal for the process (see 7.1.1.3) * * Sect7.1.1.3:42-68: * ...The controlling terminal for a session is allocated by the session * leader in an implementation-defined manner. If a session leader has * no controlling terminal and opens a terminal device file that is not * already associated with a session without using the O_NOCTTY option * (see 5.3.1), it is implementation defined whethere the terminal * becomes the controlling terminal of the session leader. If a process * that is not a session leader opens a terminal file, or the O_NOCTTY * option is used on open(), that terminal shall not become the the * controlling terminal of the calling process. When a controlling * terminal becomes associated with a session, its foreground process * group shall be set to the process group of the session leader. * The controlling terminal is inherited by the child process during a * fork() function call. A process relinquishes its controlling terminal * when it creates a new session with the setsid() function; other * processes remaining in the old session that had this terminal as * their controlling terminal continue to have it. Upon the close of * the last file descriptor in the system (whether or not it is in the * current session) associated with the cntrolling terminal, it is * unspecified whether all process that had the terminal cease to have * any controlling terminal. Whether and how a session leader can * reacquire a controlling terminal after the controlling terminal has * been relinquished in this fashion is unspecified. A process does not * relinquish its controlling terminal simply by closing all of its * file descriptiors associated with the controlling terminal if other * processes continue to have it open. * When a controlling process terminates, the controlling terminal * is disassociated from the current session, allowing it to be acquired * by a new session leader. Subsequent access to the terminal by other * processes in the earlier session may be denied, with attempts to * access the terminal treated as if a modem disconnect had been sensed. * * Sect7.2.4:775-800 * If the process has a controlling terminal, the tcsetpgrp() function * shall set the foreground process group ID associated with the * terminal to pgrp_id. The file associated with filedes must be the * controlling terminal of the calling process, and the controlling * terminal must be currently associated with the session of the * calling process. The value of pgrp_id must match a process * group ID of a process in the same session as the calling process. * Upon successful completion, tcsetpgrp() returns a value of zero. * Othewise, a value of -1 is returned, and errno is set to indicate the * error. * EBADF - The filedes argument is not a valid file descriptor. * EINVAL - The value of pgrp_id argument is not supported by the * implementation. * ENOSYS - The tcsetpgrp() function is not supported in this * implementation. * ENOTTY - The calling process does not have a controlling terminal, or * the file is not the controlling terminal, or the controlling * terminal is no longer associated with the session of the * calling process. * EPERM - The value of pgrp_id is a value supported by the * implementation, but does not mmatch the process group ID of a * process in the same session as the calling process. * * HP-UX_9.0:termio(7) man page states: * A terminal can belong to a process as its controlling terminal. Each * process of a session that has a controlling terminal has the same * controlling terminal. A terminal can be the controlling terminal for * at most one session. The controlling terminal for a session is * allocated by the session leader. If a session leader has no * controlling terminal and opens a terminal device file that is not * already associated with a session without using the O_NOCTTY option * (see open(2), the terminal becomes the controlling terminal of the * session and the controlling terminal's foreground process group is set * to the process group of the session leader. While a controlling * terminal is associated with a session, the session leader is said to * be the controlling process of the controlling terminal. * The controlling terminal is inherited by a child process during a * fork() (see fork(2)). A process relinquishes its controlling terminal * if it creates a new session with setsid() or setpgrp() (see setsid(2) * and setpgrp(2)), or when all file descriptors associated with the * controlling terminal have been closed. * When the controlling process terminates, the controlling terminal is * disassociated from the current session, allowing it to be acquired by * a new session leader. A SIGHUP signal is sent to all processes in the * foreground process group of the controlling terminal. Subsequent * access to the terminal by other processes in the earlier session can * be denied (see Terminal Access Control) with attempts to access the * terminal treated as if a modem disconnect had been sensed. * * Ultrix4.3pty(4): The slave device can be opened multiple times, while * the master half can be opened only once. [EIO] An attempt to open * the slave side of the pty was made before opening the master side of * the pty. */ sin = openSlavePty(sname, O_RDWR); if (sin < 0) { log("%s: open slave pty \"%s\" for read-write failed--%s\n", progName, sname, ERRMSG); exit(1); /* sends SIGCHLD to parent */ } res = mkCtrlTty(sin, 1); if (debug > 1) { log("%s: mkCtrlTty(%d, %d) returned %d\n", progName, sin, 1, res); } if (res < 0) { log( "%s: mkCtrlTty(%d) didn't acquire %s as contrlling terminal--%s\n", progName, sin, sname, ERRMSG); exit(1); } res = tcsetpgrp(sin, pid); if (debug > 1) { log("%s: tcsetpgrp(%d, %d) returned %d\n", progName, sin, pid, res); } if (res < 0) { log("%s: could not acquire fd %d (%s) as controlling terminal--%s\n", progName, sin, sname, ERRMSG); exit(1); } res = setTtyAscii(sin); /* initialize modes for ASCII I/O */ res = mkReady(sin, buf, 1, SETUP_TIMEOUT); if (debug > 1) { log("%s: mkReady(%d,%d)=%d\n", progName, sin, SETUP_TIMEOUT, res); } if (res < 0) { log("%s: slave pty handshake failed--%s\n", progName, ERRMSG); exit(1); } if (res == 0) { log("%s: slave pty handshake failed.\n", progName); exit(1); } sout = dupFd(sin, sname, O_WRONLY); serr = dupFd(sin, sname, O_RDWR); res = fcntl(sin, F_SETFL, O_RDONLY); if (res < 0) { log("%s: fcntl of \"%s\" for read-only failed--%s\n", progName, sname, ERRMSG); exit(1); } if (debug > 1) { log("%s: STDIN = %d, STDOUT = %d, STDERR = %d\n", progName, sin, sout, serr); } /* * Make sure open(ctermid(NULL)) works. * * If you get a compile time error here on linux, it's because linux * forgot to add an extern for ctermid in unistd.h. Fix your include * file or add "extern char *ctermid();" above. Hopefully, linux will * fix this error in the next release. */ chp = ctermid((char *) 0); /* In POSIX <unistd.h> */ if (chp == (char *) 0 || *chp == (char) 0) { log("%s: WARNING--ctermid(0) failed --%s\n", progName, ERRMSG); } else { ttyfd = open(chp, O_RDWR); if (ttyfd == -1) { log("%s: WARNING--open(\"%s\", O_RDWR) failed --%s\n", progName, chp, ERRMSG); } close(ttyfd); } /* * Make sure getlogin works. If not, setlogin didn't work. You will * need to repair setlogin.c. This call can still fail if the parent * still hasn't called setlogin by now. */ chp = (char *) getlogin(); if (chp == (char *) 0) { log("%s: WARNING--getlogin returned NULL\n", progName); } else { if (debug > 1) { log("%s: getlogin returned \"%s\"\n", progName, chp); } } } else { /* pipe */ close(pipe0[0]); close(pipe1[1]); sin = dupFd(pipe1[0], "pipe1[0]", O_RDONLY); close(pipe1[0]); sout = dupFd(pipe0[1], "pipe0[1]", O_WRONLY); close(pipe0[1]); serr = dupFd(sin, "serr", O_RDWR); } /* * Effect of exec: * * Unchanged: * POSIX State: * open files and state (including locks) * pid, pgid, ppid, sid, ruid, rgid, * * chroot(), chdir(), umask(), getlogin(), ctermid() * getgroups() * times() * alarm(), sigpending(), sigprocmask(), * * Note that fork() updates: * pid, ppid, times(), alarm(), sigpending(), file locks, * own copy of fd's, directory streams; alarm cleared. * * Non-posix state: * ptrace(), semop(). * ulimit() nice() rtprio() * semop() * ptrace() * setitimer() * * Changed: * euid, egid, suid, sgid - changed if exec file has setuid/gid * caught signals are set to SIG_DFL * * shmop(2) - none attached * profil(2) - profiling disabled */ if (debug) { if (generic) { log("%s: exec \"%s\" as \"%s %s %s\"\n", progName, shell, cargv[0], cargv[1], cargv[2]); } else { log("%s: exec \"%s\" as \"%s\"\n", progName, shell, cargv[0]); } if (debug > 1) { log("%s: env:\n", progName); showEnv(" ", cenv); } } closeLog(); res = execve(shell, cargv, cenv); if (res < 0) { return 1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -