📄 init.c
字号:
/* * init.c * * This is the install type init * * Erik Troan (ewt@redhat.com) * Jeremy Katz (katzj@redhat.com) * * Copyright 1996 - 2004 Red Hat, Inc. * * This software may be freely redistributed under the terms of the GNU * general public license. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#if USE_MINILIBC#include "minilibc.h"#ifndef SOCK_STREAM# define SOCK_STREAM 1#endif #else#include <ctype.h>#include <dirent.h>#include <errno.h>#include <fcntl.h>#include <net/if.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <sys/klog.h>#include <sys/mount.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/swap.h>#include <sys/time.h>#include <sys/types.h>#include <sys/un.h>#include <sys/wait.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/reboot.h>#include <linux/vt.h>#include <termios.h>#include <libgen.h>#include "devt.h"#include "devices.h"#define syslog klogctl#endif#include <asm/types.h>#include <linux/cdrom.h>#include <linux/serial.h>#ifndef MS_REMOUNT#define MS_REMOUNT 32#endif#define ENV_PATH 0#define ENV_LD_LIBRARY_PATH 1#define ENV_HOME 2#define ENV_TERM 3#define ENV_DEBUG 4#define ENV_TERMINFO 5#define ENV_PYTHONPATH 6#define ENV_MALLOC_CHECK 7#define ENV_MALLOC_PERTURB 8/* * Snakes On A Plane... * * Define this macro if you want init to launch /bin/bash instead of loader. * You will want to populate initrd.img with bash, libraries, other commands * like strace or something, and whatever else you want. This is purely for * debugging loader. Things you will likely want in a debugging initrd: * /lib/libc.so.6 * /lib/libtermcap.so.2 * /lib/ld-linux.so.2 * /lib/libdl.so.2 * /bin/bash * /bin/strace * You get the idea. Be creative. Be imaginative. Be bold. */#undef SNAKES_ON_A_PLANE/* #define SNAKES_ON_A_PLANE 1 */char * env[] = { "PATH=/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sysimage/bin:" "/mnt/sysimage/usr/bin:/mnt/sysimage/usr/sbin:/mnt/sysimage/sbin:" "/mnt/sysimage/usr/X11R6/bin", /* we set a nicer ld library path specifically for bash -- a full one makes anaconda unhappy */#if defined(__x86_64__) || defined(__s390x__) || defined(__ppc64__) "LD_LIBRARY_PATH=/lib64:/usr/lib64:/lib:/usr/lib",#else "LD_LIBRARY_PATH=/lib:/usr/lib",#endif "HOME=/", "TERM=linux", "DEBUG=", "TERMINFO=/etc/linux-terminfo", "PYTHONPATH=/tmp/updates", "_MALLOC_CHECK=2", "MALLOC_PERTURB_=204", NULL};/* * this needs to handle the following cases: * * 1) run from a CD root filesystem * 2) run from a read only nfs rooted filesystem * 3) run from a floppy * 4) run from a floppy that's been loaded into a ramdisk * */int testing=0;void unmountFilesystems(void);void disableSwap(void);void shutDown(int noKill, int doReboot, int doPowerOff);static int getNoKill(void);struct termios ts;static int mystrstr(char *str1, char *str2) { char *p; int rc=0; for (p=str1; *p; p++) { if (*p == *str2) { char *s, *t; rc = 1; for (s=p, t=str2; *s && *t; s++, t++) if (*s != *t) { rc = 0; p++; } if (rc) return rc; } } return rc;}static void printstr(char * string) { int ret; ret = write(1, string, strlen(string));}static void fatal_error(int usePerror) {/* FIXME */#if 0 if (usePerror) perror("failed:"); else#endif printf("failed.\n"); printf("\nI can't recover from this.\n"); if (testing) exit(0);#if !defined(__s390__) && !defined(__s390x__) while (1) ;#endif}static int logChunk(int len, char *inbuf, char *outbuf) { int inctr, outctr; for (inctr = 0, outctr = 0; inctr < len; inctr++) { /* If the character is a NULL that's immediately followed by a open * bracket, we've found the beginning of a new kernel message. Put in * a line separator. */ if (inbuf[inctr] == '\0' && inctr+1 < len && inbuf[inctr+1] == '<') { outbuf[outctr] = '\n'; outctr++; } /* Or, if we see a NULL right before the end of the chunk, that's also * a good place to add a separator. */ else if (inbuf[inctr] == '\0' && inctr+1 == len) { outbuf[outctr] = '\n'; outctr++; } /* Otherwise, simply output the character as long as it's not NULL. */ else if (inbuf[inctr] != '\0') { outbuf[outctr] = inbuf[inctr]; outctr++; } } return outctr;}static void doklog(char * fn) { fd_set readset, unixs; int in, out, i; int log; socklen_t s; int sock = -1; struct sockaddr_un sockaddr; char inbuf[1024], outbuf[1024]; int readfd; int ret; in = open("/proc/kmsg", O_RDONLY,0); if (in < 0) { /* FIXME: was perror */ printstr("open /proc/kmsg"); return; } out = open(fn, O_WRONLY, 0); if (out < 0) printf("couldn't open %s for syslog -- still using /tmp/syslog\n", fn); log = open("/tmp/syslog", O_WRONLY | O_CREAT, 0644); if (log < 0) { /* FIXME: was perror */ printstr("error opening /tmp/syslog"); sleep(5); close(in); return; } /* if we get this far, we should be in good shape */ if (fork()) { /* parent */ close(in); close(out); close(log); return; } close(0); close(1); close(2); dup2(1, log);#if defined(USE_LOGDEV) /* now open the syslog socket */ sockaddr.sun_family = AF_UNIX; strcpy(sockaddr.sun_path, "/dev/log"); sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { printf("error creating socket: %d\n", errno); sleep(5); } printstr("got socket\n"); if (bind(sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr.sun_family) + strlen(sockaddr.sun_path))) { printf("bind error: %d\n", errno); sleep(5); } printstr("bound socket\n"); chmod("/dev/log", 0666); if (listen(sock, 5)) { printf("listen error: %d\n", errno); sleep(5); }#endif syslog(8, NULL, 1); FD_ZERO(&unixs); while (1) { memcpy(&readset, &unixs, sizeof(unixs)); if (sock >= 0) FD_SET(sock, &readset); FD_SET(in, &readset); i = select(20, &readset, NULL, NULL, NULL); if (i <= 0) continue; if (FD_ISSET(in, &readset)) { i = read(in, inbuf, sizeof(inbuf)); if (i > 0) { int loggedLen = logChunk(i, inbuf, outbuf); if (out >= 0) ret = write(out, outbuf, loggedLen); ret = write(log, outbuf, loggedLen); } } for (readfd = 0; readfd < 20; ++readfd) { if (FD_ISSET(readfd, &readset) && FD_ISSET(readfd, &unixs)) { i = read(readfd, inbuf, sizeof(inbuf)); if (i > 0) { int loggedLen = logChunk(i, inbuf, outbuf); if (out >= 0) ret = write(out, outbuf, loggedLen); ret = write(log, outbuf, loggedLen); } else if (i == 0) { /* socket closed */ close(readfd); FD_CLR(readfd, &unixs); } } } if (sock >= 0 && FD_ISSET(sock, &readset)) { s = sizeof(sockaddr); readfd = accept(sock, (struct sockaddr *) &sockaddr, &s); if (readfd < 0) { if (out >= 0) ret = write(out, "error in accept\n", 16); ret = write(log, "error in accept\n", 16); close(sock); sock = -1; } else { FD_SET(readfd, &unixs); } } } }static int setupTerminal(int fd) { struct winsize winsize; int fdn, len; char buf[65535]; if (ioctl(fd, TIOCGWINSZ, &winsize)) { printf("failed to get winsize"); fatal_error(1); } winsize.ws_row = 24; winsize.ws_col = 80; if (ioctl(fd, TIOCSWINSZ, &winsize)) { printf("failed to set winsize"); fatal_error(1); } /* use the no-advanced-video vt100 definition */ env[ENV_TERM] = "TERM=vt100-nav"; /* unless the user specifies that they want utf8 */ if ((fdn = open("/proc/cmdline", O_RDONLY, 0)) != -1) { len = read(fdn, buf, sizeof(buf) - 1); close(fdn); if (len > 0 && mystrstr(buf, "utf8")) env[ENV_TERM] = "TERM=vt100"; } return 0;}#if !defined(__s390__) && !defined(__s390x__)static int termcmp(struct termios *a, struct termios *b) { if (a->c_iflag != b->c_iflag || a->c_oflag != b->c_oflag || a->c_cflag != b->c_cflag || a->c_lflag != b->c_lflag || a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed) return 1; return memcmp(a->c_cc, b->c_cc, sizeof(a->c_cc));}#endif/* Recursive -- copied (and tweaked)from loader2/method.c */ static int copyDirectory(char * from, char * to) { DIR * dir; struct dirent * ent; int fd, outfd; char buf[4096]; int i; struct stat sb; char filespec[256]; char filespec2[256]; char link[1024]; int ret; mkdir(to, 0755); if (!(dir = opendir(from))) { printf("Failed to read directory %s: %s", from, strerror(errno)); return 1; } errno = 0; while ((ent = readdir(dir))) { if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; sprintf(filespec, "%s/%s", from, ent->d_name); sprintf(filespec2, "%s/%s", to, ent->d_name); lstat(filespec, &sb); if (S_ISDIR(sb.st_mode)) { if (copyDirectory(filespec, filespec2)) return 1; } else if (S_ISLNK(sb.st_mode)) { i = readlink(filespec, link, sizeof(link) - 1); link[i] = '\0'; if (symlink(link, filespec2)) { printf("failed to symlink %s to %s: %s", filespec2, link, strerror(errno)); } } else { fd = open(filespec, O_RDONLY); if (fd == -1) { printf("failed to open %s: %s", filespec, strerror(errno)); return 1; } outfd = open(filespec2, O_RDWR | O_TRUNC | O_CREAT, 0644); if (outfd == -1) { printf("failed to create %s: %s", filespec2, strerror(errno)); } else { fchmod(outfd, sb.st_mode & 07777); while ((i = read(fd, buf, sizeof(buf))) > 0) ret = write(outfd, buf, i); close(outfd); } close(fd); } errno = 0; } closedir(dir); return 0;}static void createDevices(void) { int i; for (i = 0; devnodes[i].devname != NULL; i++) { char devname[64]; int type = -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -