Guest User

Python implementation of initrd's INIT script

a guest
Jun 8th, 2011
296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.38 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. import os
  4. import sys
  5. import subprocess
  6.  
  7. # 参数表,内核参数和全局变量
  8. opts = {
  9.     "root"  :   "",
  10.     "init"  :   "/sbin/init",
  11.     "rootdelay" :   10
  12. }
  13.  
  14. # 输出普通信息
  15. def msg (s):
  16.     if opts.get("quiet") == False:
  17.         print(s)
  18.  
  19. # 输出错误信息
  20. def err (s):
  21.     print("ERROR: %s" % s)
  22.  
  23. # 检查设备是否存在
  24. def poll_device (c1, c2):
  25.     device=c1
  26.     seconds=c2 if c2>=0 else 10
  27.  
  28.     if opts["udevd_running"]:
  29.         import time
  30.         import stat
  31.         msg("Waiting %d seconds for device %s ..." % (seconds, device))
  32.         while seconds>0:
  33.             try:
  34.                 if stat.S_ISBLK(os.stat(device)[stat.ST_MODE]):
  35.                     break
  36.             except OSError:
  37.                 seconds-=1
  38.  
  39.     return os.path.lexists(device)
  40.  
  41. # 交互式命令行界面
  42. def launch_interactive_shell ():
  43.     import code
  44.  
  45.     class FileCacher:
  46.         def __init__(self): self.reset()
  47.         def reset(self): self.out = []
  48.         def write(self,line): self.out.append(line)
  49.         def flush(self):
  50.             output = '\n'.join(self.out)
  51.             self.reset()
  52.             return output
  53.  
  54.     class Shell(code.InteractiveConsole):
  55.         def __init__(self):
  56.             self.stdout = sys.stdout
  57.             self.cache = FileCacher()
  58.             code.InteractiveConsole.__init__(self)
  59.             return
  60.  
  61.         def get_output(self): sys.stdout = self.cache
  62.         def return_output(self): sys.stdout = self.stdout
  63.  
  64.         def push(self,line):
  65.             self.get_output()
  66.             code.InteractiveConsole.push(self,line)
  67.             self.return_output()
  68.             output = self.cache.flush()
  69.             print(output, end='')
  70.             #print(output)
  71.  
  72.     sh = Shell()
  73.     sh.interact()
  74.  
  75. # 处理内核参数
  76. def parse_cmdline ():
  77.     cmds = open("/proc/cmdline", "r").read().split()
  78.     for item in cmds:
  79.         try:
  80.             (name, value) = item.split('=')
  81.         except ValueError:
  82.             name = item
  83.             value = False
  84.         try:
  85.             opts[name] = int(value)
  86.         except ValueError:
  87.             opts[name] = value.strip()
  88.  
  89. # 从文件获取变量
  90. def get_env_from (path):
  91.     for line in open(path, "r"):
  92.         exp = line.split("#")[0]
  93.         if len(exp)>0:
  94.             name = exp.split('=')[0].strip()
  95.             try:
  96.                 opts[name] = exp.split('=')[1].strip()
  97.             except IndexError:
  98.                 opts[name] = ""
  99.  
  100. # 挂载根目录
  101. def default_mount_handler (dest):
  102.     if not poll_device(opts["root"], opts["rootdelay"]):
  103.             err("Root device '%s' doesn't exist." % opts["root"])
  104.             print("You are now being dropped into an emergency shell.")
  105.             launch_interactive_shell()
  106.  
  107.     try:
  108.         fstype=opts["rootfstype"]
  109.     except:
  110.         fstype=subprocess.check_output( \
  111.             ["/sbin/blkid","-u","filesystem","-o","value","-s","TYPE","-p",opts["root"]]) \
  112.             .decode("ascii").strip()
  113.         if len(fstype) == 0:
  114.             err("Unable to determine the file system type of %s:" % opts["root"])
  115.             print("Either it contains no filesystem, an unknown filesystem,")
  116.             print("or more than one valid file system signature was found.")
  117.             print()
  118.             print("Try adding")
  119.             print("     rootfstype=your_filesystem_type")
  120.             print("to the kernel command line.")
  121.             print()
  122.             print("You are now being dropped into an emergency shell.")
  123.             launch_interactive_shell()
  124.             msg("Trying to continue (this will most likely fail) ...")
  125.  
  126.     flags=''
  127.     if opts.get("rootflags"):
  128.         if opts.get("rw")!=None:
  129.             flags=opts.get("rootflags")+",rw"
  130.         elif opts.get("ro")!=None:
  131.             flags=opts.get("rootflags")+",ro"
  132.     else:
  133.         if opts.get("rw")!=None:
  134.             flags="rw"
  135.         elif opts.get("ro")!=None:
  136.             flags="ro"
  137.  
  138.     if flags=='':
  139.         flags="ro"
  140.  
  141.     subprocess.call(["/bin/mount", "-t", fstype, "-o", flags, opts["root"], dest])
  142.  
  143. # 主程序
  144. if __name__ == "__main__":
  145.     subprocess.call(["/bin/busybox", "--install", "-s"])
  146.     subprocess.call(["/bin/mount", "-t", "proc", "proc", "/proc", "-o", "nosuid,noexec,nodev"])
  147.     subprocess.call(["/bin/mount", "-t", "sysfs", "sys", "/sys", "-o", "nosuid,noexec,nodev"])
  148.     subprocess.call(["/bin/mount", "-t", "tmpfs", "run", "/run", "-o", "nosuid,noexec,nodev,mode=755,size=10M"])
  149.  
  150.     if open("/proc/filesystems").read().find("devtmpfs") >= 0:
  151.         subprocess.call(["/bin/mount", "-n", "-t", "devtmpfs", "udev", "/dev", "-o", "mode=0755,size=10M,nosuid"])
  152.     else:
  153.         subprocess.call(["/bin/mount", "-n", "-t", "tmpfs", "udev", "/dev", "-o", "mode=0755,size=10M,nosuid"])
  154.         subprocess.call(["/bin/mknod", "/dev/null", "c", "1", "3"])
  155.         subprocess.call(["/bin/mknod", "/dev/zero", "c", "1", "5"])
  156.         subprocess.call(["/bin/mknod", "/dev/console", "c", "5", "1"])
  157.         subprocess.call(["/bin/mknod", "/dev/mem", "c", "1", "1"])
  158.  
  159.     parse_cmdline()
  160.     print("/sbin/modprobe", file=open("/proc/sys/kernel/modprobe", "w"))
  161.  
  162.     if os.path.lexists("/sbin/udevd"):
  163.         msg(":: Starting udevd...")
  164.         subprocess.call(["/sbin/udevd", "--daemon", "--resolve-names=never"])
  165.         opts["udevd_running"]=True
  166.         msg("done.")
  167.     else:
  168.         opts["udevd_running"]=False
  169.  
  170.     if opts.get("disablehooks"):
  171.         for d in opts.get("disablehooks").split(","):
  172.             opts["dishook_"+d]=True
  173.  
  174.     if opts.get("disablemodules"):
  175.         for d in opts.get("disablemodules").split(","):
  176.             opts["dismod_"+d]=True
  177.  
  178.     if opts.get("earlymodules"):
  179.         for m in opts.get("disablehooks").split(","):
  180.             subprocess.call(["/sbin/modprobe", "-q", m])
  181.  
  182.     get_env_from("/config")
  183.  
  184.     if opts.get("MODULES"):
  185.         for m in opts.get("MODULES")[1:-1].split():
  186.             if not opts.get("dismod_"+m):
  187.                 subprocess.call(["/sbin/modprobe", "-q", m])
  188.  
  189.     if os.path.isdir("/hooks") and opts.get("HOOKS"):
  190.         # 还没完全实现,只能处理udev
  191.         if opts.get("HOOKS").find("udev")>0:
  192.             subprocess.call(["/sbin/udevadm", "trigger", "--action=add", "--type=subsystems"])
  193.             subprocess.call(["/sbin/udevadm", "trigger", "--action=add", "--type=devices"])
  194.             subprocess.call(["/sbin/udevadm", "settle"])
  195.  
  196.     if opts.get("break"):
  197.         print(":: Break requested, type 'exit' to resume operation")
  198.         launch_interactive_shell()
  199.  
  200.     if os.path.isfile("/message"):
  201.         msg(file(message, "r").read())
  202.  
  203.     os.mkdir("/new_root")
  204.     default_mount_handler("/new_root")
  205.  
  206.     if not os.path.isfile("/new_root"+opts["init"]):
  207.         err(opts["init"]+" does not exist.")
  208.         print("Bailing out, you are on your own. Good luck.")
  209.         print()
  210.         launch_interactive_shell()
  211.  
  212.     if opts["udevd_running"]:
  213.         subprocess.call(["/sbin/udevadm", "control", "--exit"])
  214.         subprocess.call(["/sbin/udevadm", "info", "--cleanup-db"])
  215.  
  216.     for d in ("/proc", "/sys", "/dev", "/run"):
  217.         if os.path.isdir("/new_root"+d):
  218.             subprocess.call(["/bin/mount", "--move", d, "/new_root"+d])
  219.         else:
  220.             subprocess.call(["/bin/umount", d])
  221.  
  222.     os.execv("/sbin/switch_root", \
  223.         ["/sbin/switch_root", "-c", "/dev/console", "/new_root", opts["init"]])
Advertisement
Add Comment
Please, Sign In to add comment