home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / BOOTPCMD.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  16KB  |  711 lines

  1. /*************************************************/
  2. /* Center for Information Technology Integration */
  3. /*             The University of Michigan          */
  4. /*                      Ann Arbor                  */
  5. /*                                                 */
  6. /* Dedicated to the public domain.                 */
  7. /* Send questions to info@citi.umich.edu         */
  8. /*                                                 */
  9. /* BOOTP is documented in RFC 951 and RFC 1048     */
  10. /*************************************************/
  11.  
  12. /****************************************************************************
  13. *    $Id: bootpcmd.c 1.2 93/07/16 11:43:05 ROOT_DOS Exp $
  14. *    08 May 93    1.2     GT    Fix warnings.                                    *
  15. ****************************************************************************/
  16.  
  17.  
  18. #include <stdio.h>
  19. #include <sys\types.h>
  20. #include <sys\stat.h>
  21. #include <time.h>
  22. #include <ctype.h>
  23. #ifdef    ANSIPROTO
  24. #include <stdarg.h>
  25. #endif
  26. #include "global.h"
  27. #include "config.h"
  28. #include "cmdparse.h"
  29. #include "bootpd.h"
  30. #include "netuser.h"
  31. #include "iface.h"
  32. #include "udp.h"
  33. #include "arp.h"
  34.  
  35. #define BP_DEFAULT_TAB "bootptab"
  36. #define BP_DEFAULT_LOG "bootplog"
  37. #define BP_DEFAULT_DIR "bpfiles"
  38. #define BP_DEFAULT_FILE "boot"
  39.  
  40. static char    *bootptab = BP_DEFAULT_TAB;
  41. static FILE    *bootfp;                 /* bootptab fp */
  42. static long     modtime;            /* last modification time of bootptab */
  43.  
  44. static char    bootplog[64] = BP_DEFAULT_LOG;
  45. static int    LogInFile = 0;        /* Should bp_log log in a file? */
  46. static int    LogOnScreen = 0;    /* Should bp_log log on screen? */
  47.  
  48. static char    *line;             /* line buffer for reading bootptab */
  49. static int       linenum;          /* current ilne number in bootptab */
  50.  
  51. extern int    Nhosts;          /* number of hosts in host structure */
  52. extern struct host hosts[MHOSTS];
  53.  
  54. extern char    homedir[64];      /* bootfile homedirectory */
  55. extern char    defaultboot[64];  /* default file to boot */
  56. extern int32   bp_DefaultDomainNS[BP_MAXDNS]; /* default domain name server */
  57. extern int    Nhosts;
  58. extern struct udp_cb *Bootpd_cb;
  59.  
  60.  
  61.  
  62.  
  63.  
  64. static int bp_Homedir            __ARGS((int argc,char *argv[],void *p));
  65. static int bp_DefaultFile        __ARGS((int argc,char *argv[],void *p));
  66. static int bp_DynamicRange        __ARGS((int argc,char *argv[],void *p));
  67. static int bp_donothing         __ARGS((int argc,char *argv[],void *p));
  68. static int bp_Host            __ARGS((int argc,char *argv[],void *p));
  69. static int bp_rmHost        __ARGS((int argc,char *argv[],void *p));
  70. static int bp_DomainNS            __ARGS((int argc,char *argv[],void *p));
  71. static int bp_Start             __ARGS((int argc,char *argv[],void *p));
  72. static int bp_Stop                __ARGS((int argc,char *argv[],void *p));
  73. static int bp_logFile        __ARGS((int argc,char *argv[],void *p));
  74. static int bp_logScreen             __ARGS((int argc,char *argv[],void *p));
  75. static void dumphosts __ARGS((void));
  76.  
  77. void bootpd __ARGS((struct iface *iface, struct udp_cb *sock, int cnt));
  78.  
  79. static struct cmds BootpdCmds[] = {
  80.     { "",             bp_donothing,            0, 0, NULLCHAR },
  81.     { "start",    bp_Start,        0, 0, NULLCHAR },
  82.     { "stop",     bp_Stop,        0, 0, NULLCHAR },
  83.     { "dns",        bp_DomainNS,        0, 0, NULLCHAR },
  84.     { "dynip",        bp_DynamicRange,        0, 0, NULLCHAR },
  85.     { "host",     bp_Host,        0, 0, NULLCHAR },
  86.     { "rmhost",    bp_rmHost,        0, 0, NULLCHAR },
  87.     { "homedir",        bp_Homedir,             0, 0, NULLCHAR },
  88.     { "defaultfile",    bp_DefaultFile,         0, 0, NULLCHAR },
  89.     { "logfile",    bp_logFile,     0, 0, NULLCHAR },
  90.     { "logscreen",    bp_logScreen,        0, 0, NULLCHAR },
  91.     { NULLCHAR,        NULLFP,                 0, 0, NULLCHAR }
  92. };
  93.  
  94.  
  95.  
  96. int 
  97. bootpdcmd (argc, argv, p)
  98. int argc;
  99. char *argv[];
  100. void *p;
  101. {
  102.     return subcmd (BootpdCmds, argc, argv, p);
  103. }
  104.  
  105.  
  106. /* Start up bootp service */
  107. static int
  108. bp_Start (argc,argv,p)
  109. int argc;
  110. char *argv[];
  111. void *p;
  112. {
  113.  
  114.         struct socket lsock;
  115.         time_t tloc;
  116.     char *usage = "bootpd start\n";
  117.  
  118.     if (argc != 1) {
  119.         tprintf (usage);
  120.         return (-1);
  121.     }
  122.  
  123.     time(&tloc);
  124.         bp_log ("\n\n####BOOTP server starting at %s\n", ctime(&tloc));
  125.  
  126.         lsock.address = INADDR_ANY;
  127.         lsock.port = IPPORT_BOOTPS;
  128.  
  129.         /* This way is better than recvfrom because it passes the iface in bootpd call */
  130.        /* Listen doesn't work for datagrams. */
  131.  
  132.         if (Bootpd_cb == NULLUDP) {
  133.                 if ((Bootpd_cb = open_udp(&lsock, bootpd)) == NULLUDP) {
  134.             tprintf ("bootpd: can't open_udp\n");   
  135.             return (-1);
  136.         }
  137.         }
  138.  
  139.         /*
  140.          * Read the bootptab file once immediately upon startup.
  141.          */
  142.  
  143.         da_init();
  144.  
  145.         readtab();
  146.  
  147.         return (0);
  148. }
  149.  
  150.  
  151.  
  152. /* Stop bootp service */
  153. static int
  154. bp_Stop (argc, argv, p)
  155. int argc;
  156. char *argv[];
  157. void *p;
  158. {
  159.     time_t now;
  160.     char *usage = "bootpd stop\n";
  161.  
  162.     if (argc != 1) {
  163.         tprintf (usage);
  164.         return -1;
  165.     }
  166.  
  167.     time (&now);
  168.  
  169.         Nhosts = 0;
  170.         da_shut();
  171.         readtab_shut();
  172.         del_udp (Bootpd_cb);
  173.         Bootpd_cb = NULLUDP;
  174.  
  175.     bp_log ("Bootpd shutdown %s", ctime (&now));
  176.         return (0);
  177. };
  178.  
  179.  
  180.  
  181. static int
  182. bp_logFile (argc, argv, p)
  183. int argc;
  184. char *argv[];
  185. void *p;
  186. {
  187.     int i;
  188.     time_t now;
  189.     char *usage = "bootpd logfile [<file_name> | default] [on | off] \n"; 
  190.  
  191.     time (&now);
  192.  
  193.     if (argc == 1) {
  194.         if (LogInFile)
  195.                     tprintf ("Bootpd logging to file '%s' turned on.\n", bootplog);
  196.         else 
  197.                     tprintf ("Bootpd logging to file '%s' turned off.\n", bootplog);
  198.     }
  199.     else {
  200.         for (i = 1; i < argc; i++) {
  201.  
  202.             if (strcmp ("?", argv[i]) == 0) 
  203.                 tprintf (usage);
  204.  
  205.             else if (strcmp ("off", argv[i]) == 0) {
  206.                 bp_log ("Stopping file logging at %s", ctime(&now));
  207.                 LogInFile = 0;
  208.             }
  209.             else if (strcmp ("on", argv[i]) == 0) {
  210.                 LogInFile = 1;
  211.                 bp_log ("Starting file logging at %s", ctime(&now));
  212.             }
  213.             else if (strcmp ("default", argv[i]) == 0) {
  214.                 strcpy (bootplog, BP_DEFAULT_LOG);
  215.                 bp_log ("File for logging set to %s\n", bootplog);
  216.             }
  217.             else {
  218.                 strcpy (bootplog, argv[1]);
  219.                 bp_log ("File for logging set to %s\n", bootplog);
  220.             }   
  221.         }
  222.     }
  223.     return 0;
  224. }
  225.  
  226.  
  227. static int
  228. bp_logScreen (argc, argv, p)
  229. int argc;
  230. char *argv[];
  231. void *p;
  232. {
  233.     char *usage = "bootpd logscreen [on | off]\n";  
  234.  
  235.         if (argc == 1)
  236.         if (LogOnScreen)    
  237.                     tprintf ("Bootpd logging on screen turned on.\n");
  238.         else 
  239.                     tprintf ("Bootpd logging on screen turned off.\n");
  240.  
  241.         else if (argc == 2)  {
  242.                 if    (strcmp ("on", argv[1]) == 0)
  243.                         LogOnScreen = 1;
  244.                 else if  (strcmp ("off", argv[1]) == 0)
  245.                         LogOnScreen = 0;
  246.         else tprintf (usage);
  247.     }
  248.     else tprintf (usage);
  249.     return 0;
  250. }
  251.  
  252.  
  253.  
  254.  
  255. static int
  256. bp_DomainNS (argc, argv, p)
  257. int argc;
  258. char *argv[];
  259. void *p;
  260. {
  261.     int a0, a1, a2, a3;
  262.     int i;
  263.     char *usage = "bootpd dns [<IP addr of domain name server>...]\n";
  264.  
  265.     if (argc == 1) {
  266.         tprintf ("Bootp domain name servers: ");
  267.         for (i=0; (i < BP_MAXDNS) && (bp_DefaultDomainNS[i] != 0); i++) 
  268.             tprintf (" %s", inet_ntoa (bp_DefaultDomainNS[i]));
  269.         tprintf ("\n");
  270.         return (0);
  271.     }
  272.  
  273.     if (argc > 1) {
  274.         if ((argc == 2) && (strcmp ("?", argv[1]) == 0)) {
  275.             tprintf (usage);
  276.             return 0;
  277.         }
  278.             
  279.         /* A list of name servers has been given */
  280.         /* reset the domain name server list */
  281.         for (i= 0; i < BP_MAXDNS; i++) 
  282.             bp_DefaultDomainNS[i] = 0;
  283.  
  284.         /* get ip address */
  285.         for (i = 1; (i < argc) && (i < BP_MAXDNS); i++) {
  286.                     if (4 != sscanf (argv[i], "%d.%d.%d.%d", &a0, &a1, &a2, &a3)) {
  287.                             tprintf("bad internet address: %s\n", argv[1], linenum);
  288.                 return    -1;
  289.                     }
  290.                 bp_DefaultDomainNS[i-1] = aton(argv[i]);
  291.         }
  292.     }
  293.     /* record for the loggers sake */
  294.     bp_log ("Bootp domain name servers: ");
  295.     for (i=0; (i < BP_MAXDNS) && (bp_DefaultDomainNS[i] != 0); i++) 
  296.         bp_log (" %s", inet_ntoa (bp_DefaultDomainNS[i]));
  297.     bp_log ("\n");
  298.     return 0;
  299. }
  300.  
  301.  
  302.  
  303. static int
  304. bp_rmHost (argc, argv, p)
  305. int argc;
  306. char *argv[];
  307. void *p;
  308. {
  309.     int i;
  310.     struct host *hp = NULLHOST;
  311.     struct host *cp = NULLHOST;
  312.     char *usage = "bootpd rmhost <host name>\n";
  313.  
  314.  
  315.     if (argc == 2) {
  316.         
  317.         /* Find the host record */
  318.         for (i=0; i < Nhosts; i++) {
  319.             if (strcmp (hosts[i].name, argv[1]) == 0) {
  320.                 hp = &(hosts[i]);
  321.                 break;
  322.             }
  323.         }   
  324.         /* Return if not found */
  325.         if (hp == NULLHOST) {
  326.             tprintf ("Host %s not in host tables.\n", argv[1]);
  327.             return -1;
  328.         }
  329.         bp_log ("Host %s removed from host table\n", hp->name);
  330.         cp = &(hosts [Nhosts - 1]);
  331.         if (hp < cp) 
  332.             memcpy ((char *) hp, (char *) cp, sizeof (struct host));
  333.         Nhosts--;
  334.         return 0;
  335.     }
  336.     else tprintf (usage);
  337.     return 0;
  338. }
  339.  
  340.  
  341. /*
  342.  * Printout the hosts table.
  343. */
  344. static void
  345. dumphosts()
  346. {
  347.         int i;
  348.         struct host *hp;
  349.     struct arp_type *at;
  350.  
  351.         tprintf ("\n\nStatus of host table\n");
  352.  
  353.         if (Nhosts == 0) {
  354.                 tprintf ("       No hosts in host table\n");
  355.                 return;
  356.         }
  357.         for (i = 0; i <= Nhosts-1; i++) {
  358.                 hp = &hosts[i];
  359.         at = &Arp_type[hp->htype];
  360.         
  361.                 tprintf ("%s  %s  %s  %s  '%s'\n",
  362.                         hp->name, ArpNames[hp->htype], (*at->format)(bp_ascii, hp->haddr),
  363.                         inet_ntoa ((int32)hp->iaddr.s_addr),
  364.                         hp->bootfile);
  365.  
  366.         }
  367. }
  368.  
  369.  
  370. static int
  371. bp_Host (argc, argv, p)
  372. int argc;
  373. char *argv[];
  374. void *p;
  375. {
  376.     struct host *hp;
  377.     int a0, a1, a2, a3;
  378.     struct arp_type *at;
  379.     char *usage = "bootpd host [<hostname> <hardware type> <hardware addr> <ip addr> [boot file]]\n";
  380.  
  381.     switch (argc) {
  382.     case 1: 
  383.         dumphosts();
  384.         break;
  385.     case 5:
  386.     case 6:
  387.     
  388.         hp = &hosts[Nhosts];
  389.         
  390.         /* get host name */
  391.         strncpy (hp->name, argv[1], sizeof (hp->name));
  392.  
  393.         /* get hardware type */
  394.         /* This code borrowed from Phil Karn's arpcmd.c */
  395.         /* This is a kludge. It really ought to be table driven */
  396.         switch(tolower(argv[2][0])){
  397.             case 'n':        /* Net/Rom pseudo-type */
  398.                 hp->htype = ARP_NETROM;
  399.                 break;
  400.             case 'e': /* "ether" */
  401.                 hp->htype = ARP_ETHER;
  402.                 break;
  403.             case 'a': /* "ax25" */
  404.                 hp->htype = ARP_AX25;
  405.                 break;
  406.             case 'm': /* "mac appletalk" */
  407.                 hp->htype = ARP_APPLETALK;
  408.                 break;
  409.             default:
  410.                 tprintf("unknown hardware type \"%s\"\n",argv[2]);
  411.                 return -1;
  412.         }
  413.  
  414.         at = &Arp_type[hp->htype];
  415.         if(at->scan == NULLFP){
  416.             return 1;
  417.         }
  418.         /* Destination address */
  419.         (*at->scan)(hp->haddr,argv[3]);
  420.  
  421.  
  422.         /* get ip address */
  423.                 if (4 != sscanf (argv[4], "%d.%d.%d.%d", &a0, &a1, &a2, &a3))
  424.                 {
  425.                         tprintf("bad internet address: %s\n", argv[1], linenum);
  426.                         return (0);
  427.                 }
  428.             hp->iaddr.s_addr = aton(argv[4]);
  429.  
  430.         /* get the bootpfile */
  431.         if (argc == 6) strncpy (hp->bootfile, argv[5], sizeof (hp->bootfile));
  432.         else hp->bootfile[0] = 0;
  433.  
  434.                 bp_log ("Host added: %s  %s  %s  %s  '%s'\n",
  435.                         hp->name, ArpNames[hp->htype], (*at->format)(bp_ascii, hp->haddr),
  436.                         inet_ntoa ((int32)hp->iaddr.s_addr),
  437.                         hp->bootfile);
  438.  
  439.  
  440.         Nhosts++;
  441.         break;
  442.     
  443.     default:
  444.         tprintf (usage);
  445.         break;
  446.     }
  447.     return 0;
  448. }
  449.  
  450.  
  451.  
  452. static int  
  453. bp_Homedir (argc, argv, p)
  454. int argc;
  455. char *argv[];
  456. void *p;
  457. {
  458.     char *usage = "bootpd homedir [<name of home directory> | default]\n";
  459.  
  460.     if (argc == 1)  
  461.         tprintf ("Bootp home directory: '%s'\n", homedir);
  462.     else if (argc == 2) {
  463.         if (strcmp (argv[1], "?") == 0)
  464.             tprintf (usage);
  465.         else if (strcmp (argv[1], "default") == 0) {
  466.             strcpy (homedir, BP_DEFAULT_DIR);
  467.             bp_log ("Bootp home directory set to: '%s'\n", homedir);
  468.         }
  469.         else {
  470.             strcpy (homedir, argv[1]);
  471.             bp_log ("Bootp home directory set to: '%s'\n", homedir);
  472.         }
  473.     }
  474.     else tprintf (usage);
  475.     return (0);
  476. };
  477.  
  478.  
  479.  
  480. static int
  481. bp_DefaultFile (argc, argv, p)
  482. int argc;
  483. char *argv[];
  484. void *p;
  485. {
  486.     char *usage = "bootpd defaultfile [<name of default boot file> | default]\n";
  487.  
  488.         if (argc == 1)
  489.                 tprintf ("Bootp default boot file:    '%s'\n", defaultboot);
  490.         else if (argc == 2) {
  491.         if (strcmp (argv[1], "?") == 0)
  492.                         tprintf (usage);
  493.                 else if (strcmp (argv[1], "default") == 0)
  494.                         strcpy (defaultboot, BP_DEFAULT_FILE);
  495.                 else {
  496.                         strcpy (defaultboot, argv[1]);
  497.                     bp_log ("Bootp default boot file set to:  '%s'\n", defaultboot);
  498.         }
  499.         }
  500.     else
  501.                 tprintf (usage);
  502.  
  503.     return    (0);
  504. };
  505.  
  506.  
  507. static int
  508. bp_DynamicRange (argc, argv, p)
  509. int argc;
  510. char *argv[];
  511. void *p;
  512. {
  513.     int i0, i1, i2, i3;
  514.     int32 start, end;
  515.     struct iface *iface;
  516.     char *usage = "bootpd dynip [<net name> | <netname>  <IP address> <IP address> | <netname> off]\n";
  517.  
  518.     if (argc == 1) {
  519.         da_status (NULLIF);
  520.         return 0;
  521.     }
  522.     if ((argc == 2) && (strcmp ("?", argv[1]) == 0)) {
  523.             tprintf (usage);
  524.             return 0;
  525.     }
  526.  
  527.     /* get the interface */
  528.     iface = if_lookup (argv[1]);
  529.     if (iface == NULLIF) {
  530.         tprintf ("network '%s' not found\n", argv[1]);
  531.         return    (-1);
  532.     }
  533.     if (argc == 2) {
  534.         da_status (iface);
  535.         return 0;
  536.     }
  537.     if (argc == 3) {
  538.         if (strcmp ("off", argv[2]) == 0) 
  539.             da_done_net (iface);
  540.         else tprintf (usage);
  541.     }
  542.     else if (argc == 4) {
  543.         
  544.             /* get ip address */
  545.                 /* check the ip address - isaddr isn't a ka9q function */
  546.                 if ((4 != sscanf (argv[2], "%d.%d.%d.%d", &i0, &i1, &i2, &i3)) || 
  547.             (i0 > 255) || (i1 > 255) || (i2 > 255) || (i3 > 255)
  548.         )
  549.                 {
  550.                     tprintf("bad internet address: %s\n", argv[2], linenum);
  551.                         return (-1);
  552.                 }
  553.  
  554.                 if ((4 != sscanf (argv[3], "%d.%d.%d.%d", &i0, &i1, &i2, &i3)) || 
  555.             (i0 > 255) || (i1 > 255) || (i2 > 255) || (i3 > 255)
  556.         )
  557.                 {
  558.                     tprintf("bad internet address: %s\n", argv[3], linenum);
  559.                         return (-1);
  560.                 }
  561.  
  562.                 start = aton(argv[2]);
  563.                 end = aton(argv[3]);
  564.  
  565.         da_serve_net (iface, start, end);
  566.  
  567.     }
  568.     else {
  569.         tprintf (usage);
  570.         return (0);
  571.     }
  572.  
  573.     return (0);
  574. };
  575.  
  576.  
  577. static int
  578. bp_donothing (argc, argv, p)
  579. int argc;
  580. char *argv[];
  581. void *p;
  582. {
  583.         return (0);
  584. }
  585.  
  586.  
  587. /*
  588.  * Read bootptab database file.  Avoid rereading the file if the
  589.  * write date hasn't changed since the last time we read it.
  590.  */
  591. int
  592. readtab()
  593. {
  594.         struct stat st;
  595.  
  596.         /* If the file hasn't been opened, open it. */
  597.         if (bootfp == 0) {
  598.                 if ((bootfp = fopen(bootptab, "r")) == NULLFILE) {
  599.                         bp_log("Can't open bootptab file: %s\n", bootptab);
  600.                         return (-1);
  601.                 }
  602.         }
  603.  
  604.         /* Only reread if modified */
  605.         stat (bootptab, &st);
  606.         if (st.st_mtime == modtime && st.st_nlink) {
  607.                 return (0); /* hasnt been modified or deleted yet */
  608.         }
  609.         /* It's been changed, reread. */
  610.  
  611.         if ((bootfp = fopen(bootptab, "r")) == NULLFILE) {
  612.                 bp_log("Can't open %s\n", bootptab);
  613.                 return (-1);
  614.         }
  615.         fstat(fileno(bootfp), &st);
  616.         bp_log("(re)reading %s\n", bootptab);
  617.         modtime = st.st_mtime;
  618.  
  619.         /*
  620.          * read and parse each line in the file.
  621.          */
  622.  
  623.     line = mallocw(BUFSIZ); 
  624.     
  625.     while (fgets(line, BUFSIZ, bootfp) != NULLCHAR) {
  626.         linenum++;
  627.  
  628.  
  629.         if ((line[0] == 0) || (line[0] == '#') || (line[0] == ' '))
  630.             continue;
  631.  
  632.                 if (cmdparse (BootpdCmds, line, NULL) ==  -1)
  633.                          continue;
  634.  
  635.         }
  636.         fclose(bootfp);
  637.     free (line);
  638.     return (0);
  639. }
  640.  
  641. void
  642. readtab_shut()
  643. {
  644.     modtime = 0;
  645. }
  646.  
  647. /*
  648.  * log an error message
  649.  *
  650.  */
  651. #if defined(ANSIPROTO)
  652. void
  653. bp_log(char *fmt,...)
  654. {
  655.         FILE *fp;
  656.     va_list ap;
  657.  
  658.         if (LogOnScreen) {
  659.         va_start(ap,fmt);
  660.         vprintf(fmt, ap);
  661.         va_end(ap);
  662.         fflush (stdout);
  663.     }
  664.         if (LogInFile) {
  665.                 if ((fp = fopen(bootplog, "a+")) == NULL) {
  666.                         tprintf ("Cannot open bootplog.\n");
  667.                         return;
  668.                 }
  669.         va_start(ap,fmt);
  670.         vfprintf(fp, fmt, ap);
  671.         va_end(ap);
  672.                 fflush(fp);
  673.                 fclose(fp);
  674.         }
  675. }
  676. #else
  677. void
  678. bp_log(fmt, argv1, argv2, argv3, argv4, argv5, argv6, argv7, argv8, argv9, argv10)
  679. char *fmt;
  680. char *argv1;
  681. char *argv2;
  682. char *argv3;
  683. char *argv4;
  684. char *argv5;
  685. char *argv6;
  686. char *argv7;
  687. char *argv8;
  688. char *argv9;
  689. char *argv10;
  690. {
  691.         FILE *fp;
  692.  
  693.         if (LogOnScreen) {
  694.                 printf(fmt, argv1, argv2, argv3, argv4, argv5, argv6, argv7,
  695.                         argv8, argv9, argv10);
  696.         fflush (stdout);
  697.     }
  698.  
  699.         if (LogInFile) {
  700.                 if ((fp = fopen(bootplog, "a+")) == NULL) {
  701.                         tprintf ("Cannot open bootplog.\n");
  702.                         return;
  703.                 }
  704.                 fprintf(fp, fmt, argv1, argv2, argv3, argv4, argv5, argv6, argv7,
  705.                         argv8, argv9, argv10);
  706.                 fflush (fp);
  707.                 fclose(fp);
  708.         }
  709. }
  710. #endif
  711.