18348Sjkh/* 28348Sjkh * The new sysinstall program. 38348Sjkh * 48348Sjkh * This is probably the last program in the `sysinstall' line - the next 58348Sjkh * generation being essentially a complete rewrite. 68348Sjkh * 750479Speter * $FreeBSD$ 88348Sjkh * 98348Sjkh * Copyright (c) 1995 108348Sjkh * Jordan Hubbard. All rights reserved. 118348Sjkh * 128348Sjkh * Redistribution and use in source and binary forms, with or without 138348Sjkh * modification, are permitted provided that the following conditions 148348Sjkh * are met: 158348Sjkh * 1. Redistributions of source code must retain the above copyright 168881Srgrimes * notice, this list of conditions and the following disclaimer, 178881Srgrimes * verbatim and that no modifications are made prior to this 188348Sjkh * point in the file. 198348Sjkh * 2. Redistributions in binary form must reproduce the above copyright 208348Sjkh * notice, this list of conditions and the following disclaimer in the 218348Sjkh * documentation and/or other materials provided with the distribution. 228348Sjkh * 238348Sjkh * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 248348Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 258348Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 268348Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 278348Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 288348Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 298348Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 308348Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 318348Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 328348Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 338348Sjkh * SUCH DAMAGE. 348348Sjkh * 358348Sjkh */ 368348Sjkh 378348Sjkh#include "sysinstall.h" 388348Sjkh 398348Sjkh#define MAX_NUM_COMMANDS 10 408348Sjkh 418348Sjkhtypedef struct { 428348Sjkh char key[FILENAME_MAX]; 438549Sjkh struct { 448549Sjkh enum { CMD_SHELL, CMD_FUNCTION } type; 458549Sjkh void *ptr, *data; 468549Sjkh } cmds[MAX_NUM_COMMANDS]; 478348Sjkh int ncmds; 488348Sjkh} Command; 498348Sjkh 508348Sjkh#define MAX_CMDS 200 518348Sjkhstatic Command *commandStack[MAX_CMDS]; 528348Sjkhint numCommands; 538348Sjkh 548549Sjkh/* Nuke the command stack */ 558348Sjkhvoid 568348Sjkhcommand_clear(void) 578348Sjkh{ 588348Sjkh int i, j; 598348Sjkh 608348Sjkh for (i = 0; i < numCommands; i++) 618348Sjkh for (j = 0; j < commandStack[i]->ncmds; j++) 628549Sjkh if (commandStack[i]->cmds[j].type == CMD_SHELL) 638549Sjkh free(commandStack[i]->cmds[j].ptr); 648348Sjkh free(commandStack[i]); 658348Sjkh numCommands = 0; 668348Sjkh} 678348Sjkh 6810882Speterstatic void 6910882Speteraddit(char *key, int type, void *cmd, void *data) 708348Sjkh{ 718348Sjkh int i; 728348Sjkh 7312661Speter /* First, look for the key already present and add a command to it if found */ 748348Sjkh for (i = 0; i < numCommands; i++) { 758348Sjkh if (!strcmp(commandStack[i]->key, key)) { 768348Sjkh if (commandStack[i]->ncmds == MAX_NUM_COMMANDS) 7710882Speter msgFatal("More than %d commands stacked up behind %s??", MAX_NUM_COMMANDS, key); 7810882Speter commandStack[i]->cmds[commandStack[i]->ncmds].type = type; 7910882Speter commandStack[i]->cmds[commandStack[i]->ncmds].ptr = cmd; 8010882Speter commandStack[i]->cmds[commandStack[i]->ncmds].data = data; 818549Sjkh ++(commandStack[i]->ncmds); 828348Sjkh return; 838348Sjkh } 848348Sjkh } 858549Sjkh if (numCommands == MAX_CMDS) 868549Sjkh msgFatal("More than %d commands accumulated??", MAX_CMDS); 878549Sjkh 888348Sjkh /* If we fell to here, it's a new key */ 898348Sjkh commandStack[numCommands] = safe_malloc(sizeof(Command)); 908348Sjkh strcpy(commandStack[numCommands]->key, key); 918348Sjkh commandStack[numCommands]->ncmds = 1; 9210882Speter commandStack[numCommands]->cmds[0].type = type; 9310882Speter commandStack[numCommands]->cmds[0].ptr = cmd; 9412661Speter commandStack[numCommands]->cmds[0].data = data; 9512661Speter ++numCommands; 968549Sjkh} 978549Sjkh 988549Sjkh/* Add a shell command under a given key */ 998549Sjkhvoid 10010882Spetercommand_shell_add(char *key, char *fmt, ...) 1018549Sjkh{ 10210882Speter va_list args; 10310882Speter char *cmd; 1048549Sjkh 10512661Speter cmd = (char *)safe_malloc(256); 10610882Speter va_start(args, fmt); 10712661Speter vsnprintf(cmd, 256, fmt, args); 10810882Speter va_end(args); 1098549Sjkh 11010882Speter addit(key, CMD_SHELL, cmd, NULL); 1118348Sjkh} 1128348Sjkh 11310882Speter/* Add a shell command under a given key */ 11410882Spetervoid 11510882Spetercommand_func_add(char *key, commandFunc func, void *data) 11610882Speter{ 11710882Speter addit(key, CMD_FUNCTION, func, data); 11810882Speter} 11910882Speter 1208348Sjkhstatic int 12112661Spetersort_compare(Command *p1, Command *p2) 1228348Sjkh{ 12312661Speter if (!p1 && !p2) 12412661Speter return 0; 12512661Speter else if (!p1 && p2) /* NULL has a "greater" value for commands */ 12612661Speter return 1; 12712661Speter else if (p1 && !p2) 12812661Speter return -1; 12912661Speter else 13012661Speter return strcmp(p1->key, p2->key); 1318348Sjkh} 1328348Sjkh 1338348Sjkhvoid 1348348Sjkhcommand_sort(void) 1358348Sjkh{ 13612661Speter int i, j; 13712661Speter 13812661Speter commandStack[numCommands] = NULL; 13912661Speter /* Just do a crude bubble sort since the list is small */ 14012661Speter for (i = 0; i < numCommands; i++) { 14112661Speter for (j = 0; j < numCommands; j++) { 14212661Speter if (sort_compare(commandStack[j], commandStack[j + 1]) > 0) { 14312661Speter Command *tmp = commandStack[j]; 14412661Speter 14512661Speter commandStack[j] = commandStack[j + 1]; 14612661Speter commandStack[j + 1] = tmp; 14712661Speter } 14812661Speter } 14912661Speter } 1508348Sjkh} 1518348Sjkh 1528549Sjkh/* Run all accumulated commands in sorted order */ 1538348Sjkhvoid 1548348Sjkhcommand_execute(void) 1558348Sjkh{ 1568452Sjkh int i, j, ret; 1578549Sjkh commandFunc func; 1588348Sjkh 1598348Sjkh for (i = 0; i < numCommands; i++) { 1608348Sjkh for (j = 0; j < commandStack[i]->ncmds; j++) { 1618556Sjkh /* If it's a shell command, run system on it */ 1628556Sjkh if (commandStack[i]->cmds[j].type == CMD_SHELL) { 16383844Smurray msgNotify("Doing %s", (char *)commandStack[i]->cmds[j].ptr); 16479304Skris ret = vsystem("%s", (char *)commandStack[i]->cmds[j].ptr); 1658837Sjkh if (isDebug()) 16683844Smurray msgDebug("Command `%s' returns status %d\n", 16783844Smurray (char *)commandStack[i]->cmds[j].ptr, ret); 1688549Sjkh } 1698549Sjkh else { 17083844Smurray /* It's a function pointer - call it with the key and 17183844Smurray the data */ 1728556Sjkh func = (commandFunc)commandStack[i]->cmds[j].ptr; 17312661Speter if (isDebug()) 174106279Skuriyama msgDebug("%p: Execute(%s, %s)\n", 17583844Smurray func, commandStack[i]->key, 17683844Smurray (char *)commandStack[i]->cmds[j].data); 1778589Sjkh ret = (*func)(commandStack[i]->key, commandStack[i]->cmds[j].data); 1788837Sjkh if (isDebug()) 17983844Smurray msgDebug("Function @ %p returns status %d\n", 18083844Smurray commandStack[i]->cmds[j].ptr, ret); 1818549Sjkh } 1828348Sjkh } 1838348Sjkh } 1848348Sjkh} 185