Changeset 44437 in vbox for trunk/src/VBox/Installer/linux
- Timestamp:
- Jan 29, 2013 7:33:05 AM (12 years ago)
- Location:
- trunk/src/VBox/Installer/linux
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Installer/linux/install_service/generate_service_file.cpp
r44070 r44437 18 18 */ 19 19 20 /** 21 * Description of the generation process. 22 * 23 * A template for the service file to be generated is fed into standard input 24 * and the service file is sent to standard output. The following 25 * substitutions are performed based on the command line parameters supplied, 26 * with all quoting appropriate to the format of the template as specified on 27 * the command line. 28 * 29 * %COMMAND% -> path to the service binary or script. 30 * %ARGUMENTS% -> the arguments to pass to the binary when starting the 31 * service. 32 * %SERVICE_NAME% -> the name of the service. 33 * %DESCRIPTION% -> the short description of the service. 34 * %STOP_COMMAND% -> path to the command used to stop the service. 35 * %STOP_ARGUMENTS% -> the arguments for the stop command 36 * %STATUS_COMMAND% -> path to the command used to determine the service 37 * status. 38 * %STATUS_ARGUMENTS% -> the arguments for the status command 39 40 * %NO_STOP_COMMAND% -> if no stop command was specified, this and all text 41 * following it on the line (including the end-of- 42 * line) will be removed, otherwise only the marker 43 * will be removed. 44 * %HAVE_STOP_COMMAND% -> like above, but text on the line will be removed 45 * if a stop command was supplied. 46 * %NO_STATUS_COMMAND% -> Analogue to %NO_STOP_COMMAND% for the status 47 * command. 48 * %HAVE_STATUS_COMMAND% -> Analogue to %HAVE_STOP_COMMAND% for the status 49 * command. 50 * %HAVE_ONESHOT% -> like above, text on the line will be removed unless 51 * --one-shot was specified on the command line. 52 * %HAVE_DAEMON% -> the same if --one-shot was not specified. 53 * 54 * %% will be replaced with a single %. 55 */ 56 20 57 #include <VBox/version.h> 21 58 … … 40 77 #define DESCRIPTION "%DESCRIPTION%" 41 78 #define SERVICE_NAME "%SERVICE_NAME%" 79 #define HAVE_ONESHOT "%HAVE_ONESHOT%" 80 #define HAVE_DAEMON "%HAVE_DAEMON%" 81 #define STOP_COMMAND "%STOP_COMMAND%" 82 #define STOP_ARGUMENTS "%STOP_ARGUMENTS%" 83 #define HAVE_STOP_COMMAND "%HAVE_STOP_COMMAND%" 84 #define NO_STOP_COMMAND "%NO_STOP_COMMAND%" 85 #define STATUS_COMMAND "%STATUS_COMMAND%" 86 #define STATUS_ARGUMENTS "%STATUS_ARGUMENTS%" 87 #define HAVE_STATUS_COMMAND "%HAVE_STATUS_COMMAND%" 88 #define NO_STATUS_COMMAND "%NO_STATUS_COMMAND%" 42 89 43 90 void showLogo(void) … … 62 109 "Usage:\n" 63 110 "\n" 64 " %s --help|-h|-?|--version|-V|<options>\n" 65 "\n" 111 " %s --help|-h|-?|--version|-V|--format <format> <parameters...>\n\n", 112 pcszArgv0); 113 RTPrintf( 66 114 "Read a service file template from standard input and output a service file to\n" 67 115 "standard output which was generated from the template based on parameters\n" 68 116 "passed on the utility's command line. Generation is done by replacing well-\n" 69 "known text sequences in the template with strings based on the parameters. The\n", 70 pcszArgv0); 71 RTPrintf( 72 "exact strings substituted will depend on the format of the template, for\n" 73 "example shell script or systemd unit file. The sequence \"%%%%\" in the template\n" 74 "will be replaced by a single \"%%\" character. The description of the options\n" 75 "also describes the sequences which will be replaced in the template. All\n" 76 "arguments should be in Utf-8 encoding.\n" 77 "\n" 78 "\n"); 117 "known text sequences in the template with strings based on the parameters.\n" 118 "All strings should be in UTF-8 format. Processing will stop if a sequence is\n" 119 "read which cannot be replace based on the parameters supplied.\n\n"); 120 79 121 RTPrintf( 80 122 " --help|-h|-?\n" 81 " Print this help text and exit.\n" 82 "\n" 123 " Print this help text and exit.\n\n" 83 124 " --version|-V\n" 84 " Print version information and exit.\n" 85 "\n"); 86 RTPrintf( 87 "Required options:\n" 88 "\n" 125 " Print version information and exit.\n\n" 89 126 " --format <shell>\n" 90 127 " The format of the template. Currently only \"shell\" for shell script\n" 91 " is supported. This affects escaping of strings substituted.\n" 128 " is supported. This affects escaping of strings substituted.\n\n"); 129 RTPrintf( 130 "Parameters:\n" 92 131 "\n"); 93 showOptions();94 }95 96 /** List the options which make sense to pass through from a wrapper script. */97 void showOptions(void)98 {99 132 RTPrintf( 100 133 " --command <command>\n" 101 134 " The absolute path of the executable file to be started by the service.\n" 102 " No form of quoting should be used here. Substituted for the sequence\n" 103 " \"%%COMMAND%%\" in the template.\n"); 104 RTPrintf( 105 "\n" 135 " No form of quoting should be used here.\n\n"); 136 RTPrintf( 106 137 " --description <description>\n" 107 138 " A short description of the service which can also be used in sentences\n" 108 " like \"<description> failed to start.\", as a single parameter. ASCII\n" 109 " characters 0 to 31 and 127 should not be used. Substituted for the\n" 110 " sequence \"%%DESCRIPTION%%\" in the template.\n" 111 "\n" 112 "Other options:\n" 113 "\n"); 139 " like \"<description> failed to start.\", as a single parameter. Characters\n" 140 " 0 to 31 and 127 should not be used.\n\n" 141 ); 114 142 RTPrintf( 115 143 " --arguments <arguments>\n" 116 144 " The arguments to pass to the executable file when it is started, as a\n" 117 " single parameter. ASCII characters \" \", \"\\\" and \"%%\" must be escaped\n" 118 " with back-slashes and C string-style back-slash escapes are recognised.\n" 119 " Some systemd-style \"%%\" sequences may be added at a future time.\n" 120 " Substituted for the sequence \"%%ARGUMENTS%%\" in the template.\n" 121 "\n"); 145 " single parameter. Characters \" \", \"\\\" and \"%%\" must be escaped with\n" 146 " back-slashes and C string-style back-slash escapes are recognised. Some\n" 147 " systemd-style \"%%\" sequences may be added at a future time.\n\n"); 122 148 RTPrintf( 123 149 " --service-name <name>\n" 124 150 " Specify the name of the service. By default the base name without the\n" 125 151 " extension of the command binary is used. Only ASCII characters 33 to 126\n" 126 " should be used. Substituted for the sequence \"%%SERVICE_NAME%%\" in the\n" 127 " template.\n" 128 "\n"); 152 " should be used.\n\n"); 153 RTPrintf( 154 " --one-shot\n" 155 " The service command is expected to do some work and exit immediately with" 156 " a status indicating success or failure.\n\n" 157 ); 158 RTPrintf( 159 " --stop-command <command>\n" 160 " The command which should be used to stop the service before sending the\n" 161 " termination signal to the main process. No form of quoting should be\n" 162 " used here.\n\n" 163 ); 164 RTPrintf( 165 " --stop-arguments <arguments>\n" 166 " Arguments for the stop command. This may only be used in combination\n" 167 " with \"--stop-command\". Quoting is the same as for \"--arguments\".\n\n" 168 ); 169 RTPrintf( 170 " --status-command <command>\n" 171 " The command which should be used to determine the status of the service.\n" 172 " This may not be respected by all service management systems. The command\n" 173 " should return an LSB status code. No form of quoting should be used.\n\n" 174 ); 175 RTPrintf( 176 " --stop-arguments <arguments>\n" 177 " Arguments for the status command. This may only be used in combination\n" 178 " with \"--status-command\". Quoting is the same as for \"--arguments\".\n\n" 179 ); 129 180 } 130 181 … … 141 192 /** @} */ 142 193 194 struct SERVICEPARAMETERS 195 { 196 enum ENMFORMAT enmFormat; 197 const char *pcszCommand; 198 const char *pcszArguments; 199 const char *pcszDescription; 200 const char *pcszServiceName; 201 bool fOneShot; 202 const char *pcszStopCommand; 203 const char *pcszStopArguments; 204 const char *pcszStatusCommand; 205 const char *pcszStatusArguments; 206 }; 207 143 208 static bool errorIfSet(const char *pcszName, bool isSet); 144 static bool errorIfUnset(const char *pcszName, bool isSet);145 209 static enum ENMFORMAT getFormat(const char *pcszName, const char *pcszValue); 146 210 static bool checkAbsoluteFilePath(const char *pcszName, const char *pcszValue); 147 211 static bool checkPrintable(const char *pcszName, const char *pcszValue); 148 212 static bool checkGraphic(const char *pcszName, const char *pcszValue); 149 static bool createServiceFile(enum ENMFORMAT enmFormat, 150 const char *pcszCommand, 151 const char *pcszArguments, 152 const char *pcszDescription, 153 const char *pcszServiceName); 213 static bool createServiceFile(struct SERVICEPARAMETERS *pParameters); 154 214 155 215 int main(int cArgs, char **apszArgs) … … 161 221 enum 162 222 { 163 OPTION_LIST_OPTIONS = 1, 164 OPTION_FORMAT, 223 OPTION_FORMAT = 1, 165 224 OPTION_COMMAND, 166 225 OPTION_ARGUMENTS, 167 226 OPTION_DESCRIPTION, 168 OPTION_SERVICE_NAME 227 OPTION_SERVICE_NAME, 228 OPTION_ONE_SHOT, 229 OPTION_STOP_COMMAND, 230 OPTION_STOP_ARGUMENTS, 231 OPTION_STATUS_COMMAND, 232 OPTION_STATUS_ARGUMENTS 169 233 }; 170 234 171 235 static const RTGETOPTDEF s_aOptions[] = 172 236 { 173 { "--list-options", OPTION_LIST_OPTIONS,174 RTGETOPT_REQ_NOTHING },175 237 { "--format", OPTION_FORMAT, 176 238 RTGETOPT_REQ_STRING }, … … 182 244 RTGETOPT_REQ_STRING }, 183 245 { "--service-name", OPTION_SERVICE_NAME, 246 RTGETOPT_REQ_STRING }, 247 { "--one-shot", OPTION_ONE_SHOT, 248 RTGETOPT_REQ_NOTHING }, 249 { "--stop-command", OPTION_STOP_COMMAND, 250 RTGETOPT_REQ_STRING }, 251 { "--stop-arguments", OPTION_STOP_ARGUMENTS, 252 RTGETOPT_REQ_STRING }, 253 { "--status-command", OPTION_STATUS_COMMAND, 254 RTGETOPT_REQ_STRING }, 255 { "--status-arguments", OPTION_STATUS_ARGUMENTS, 184 256 RTGETOPT_REQ_STRING } 185 257 }; 186 258 187 259 int ch; 188 enum ENMFORMAT enmFormat = FORMAT_NONE; 189 const char *pcszCommand = NULL; 190 const char *pcszArguments = NULL; 191 const char *pcszDescription = NULL; 192 const char *pcszServiceName = NULL; 260 struct SERVICEPARAMETERS Parameters = { FORMAT_NONE }; 193 261 RTGETOPTUNION ValueUnion; 194 262 RTGETOPTSTATE GetState; … … 209 277 break; 210 278 211 case OPTION_LIST_OPTIONS:212 showOptions();213 return RTEXITCODE_SUCCESS;214 break;215 216 279 case OPTION_FORMAT: 217 if (errorIfSet("--format", enmFormat != FORMAT_NONE)) 218 return(RTEXITCODE_SYNTAX); 219 enmFormat = getFormat("--format", ValueUnion.psz); 220 if (enmFormat == FORMAT_NONE) 280 if (errorIfSet("--format", 281 Parameters.enmFormat != FORMAT_NONE)) 282 return(RTEXITCODE_SYNTAX); 283 Parameters.enmFormat 284 = getFormat("--format", ValueUnion.psz); 285 if (Parameters.enmFormat == FORMAT_NONE) 221 286 return(RTEXITCODE_SYNTAX); 222 287 break; 223 288 224 289 case OPTION_COMMAND: 225 if (errorIfSet("--command", pcszCommand)) 226 return(RTEXITCODE_SYNTAX); 227 pcszCommand = ValueUnion.psz; 228 if (!checkAbsoluteFilePath("--command", pcszCommand)) 290 if (errorIfSet("--command", Parameters.pcszCommand)) 291 return(RTEXITCODE_SYNTAX); 292 Parameters.pcszCommand = ValueUnion.psz; 293 if (!checkAbsoluteFilePath("--command", 294 Parameters.pcszCommand)) 229 295 return(RTEXITCODE_SYNTAX); 230 296 break; 231 297 232 298 case OPTION_ARGUMENTS: 233 if (errorIfSet("--arguments", pcszArguments)) 234 return(RTEXITCODE_SYNTAX); 235 /* Arguments will be checked while writing them out. */ 236 pcszArguments = ValueUnion.psz; 299 if (errorIfSet("--arguments", 300 Parameters.pcszArguments)) 301 return(RTEXITCODE_SYNTAX); 302 /* Quoting will be checked while writing out the string. */ 303 Parameters.pcszArguments = ValueUnion.psz; 237 304 break; 238 305 239 306 case OPTION_DESCRIPTION: 240 if (errorIfSet("--description", pcszDescription)) 241 return(RTEXITCODE_SYNTAX); 242 pcszDescription = ValueUnion.psz; 243 if (!checkPrintable("--description", pcszDescription)) 307 if (errorIfSet("--description", 308 Parameters.pcszDescription)) 309 return(RTEXITCODE_SYNTAX); 310 Parameters.pcszDescription = ValueUnion.psz; 311 if (!checkPrintable("--description", 312 Parameters.pcszDescription)) 244 313 return(RTEXITCODE_SYNTAX); 245 314 break; 246 315 247 316 case OPTION_SERVICE_NAME: 248 if (errorIfSet("--service-name", pcszServiceName)) 249 return(RTEXITCODE_SYNTAX); 250 pcszServiceName = ValueUnion.psz; 251 if (!checkGraphic("--service-name", pcszServiceName)) 252 return(RTEXITCODE_SYNTAX); 317 if (errorIfSet("--service-name", 318 Parameters.pcszServiceName)) 319 return(RTEXITCODE_SYNTAX); 320 Parameters.pcszServiceName = ValueUnion.psz; 321 if (!checkGraphic("--service-name", 322 Parameters.pcszServiceName)) 323 return(RTEXITCODE_SYNTAX); 324 break; 325 326 case OPTION_ONE_SHOT: 327 Parameters.fOneShot = true; 328 break; 329 330 case OPTION_STOP_COMMAND: 331 if (errorIfSet("--stop-command", 332 Parameters.pcszStopCommand)) 333 return(RTEXITCODE_SYNTAX); 334 Parameters.pcszStopCommand = ValueUnion.psz; 335 if (!checkAbsoluteFilePath("--stop-command", 336 Parameters.pcszStopCommand)) 337 return(RTEXITCODE_SYNTAX); 338 break; 339 340 case OPTION_STOP_ARGUMENTS: 341 if (errorIfSet("--stop-arguments", 342 Parameters.pcszStopArguments)) 343 return(RTEXITCODE_SYNTAX); 344 /* Quoting will be checked while writing out the string. */ 345 Parameters.pcszStopArguments = ValueUnion.psz; 346 break; 347 348 case OPTION_STATUS_COMMAND: 349 if (errorIfSet("--status-command", 350 Parameters.pcszStatusCommand)) 351 return(RTEXITCODE_SYNTAX); 352 Parameters.pcszStatusCommand = ValueUnion.psz; 353 if (!checkAbsoluteFilePath("--status-command", 354 Parameters.pcszStatusCommand)) 355 return(RTEXITCODE_SYNTAX); 356 break; 357 358 case OPTION_STATUS_ARGUMENTS: 359 if (errorIfSet("--status-arguments", 360 Parameters.pcszStatusArguments)) 361 return(RTEXITCODE_SYNTAX); 362 /* Quoting will be checked while writing out the string. */ 363 Parameters.pcszStatusArguments = ValueUnion.psz; 253 364 break; 254 365 … … 257 368 } 258 369 } 259 if ( errorIfUnset("--format", enmFormat != FORMAT_NONE)260 || errorIfUnset("--command", pcszCommand)261 || errorIfUnset("--description", pcszDescription))370 if (Parameters.enmFormat == FORMAT_NONE) 371 { 372 RTStrmPrintf(g_pStdErr, "--format must be specified.\n"); 262 373 return(RTEXITCODE_SYNTAX); 263 return createServiceFile(enmFormat, pcszCommand, pcszArguments, 264 pcszDescription, pcszServiceName) 374 } 375 if (Parameters.pcszArguments && !Parameters.pcszCommand) 376 { 377 RTStrmPrintf(g_pStdErr, "--arguments requires --command to be specified.\n"); 378 return(RTEXITCODE_SYNTAX); 379 } 380 if (Parameters.pcszStopArguments && !Parameters.pcszStopCommand) 381 { 382 RTStrmPrintf(g_pStdErr, "--stop-arguments requires --stop-command to be specified.\n"); 383 return(RTEXITCODE_SYNTAX); 384 } 385 if (Parameters.pcszStatusArguments && !Parameters.pcszStatusCommand) 386 { 387 RTStrmPrintf(g_pStdErr, "--status-arguments requires --status-command to be specified.\n"); 388 return(RTEXITCODE_SYNTAX); 389 } 390 return createServiceFile(&Parameters) 265 391 ? RTEXITCODE_SUCCESS 266 392 : RTEXITCODE_FAILURE; … … 273 399 RTStrmPrintf(g_pStdErr, "%s may only be specified once.\n", pcszName); 274 400 return isSet; 275 }276 277 /** Print an error and return true if an option is not set. */278 bool errorIfUnset(const char *pcszName, bool isSet)279 {280 if (!isSet)281 RTStrmPrintf(g_pStdErr, "%s must be specified.\n", pcszName);282 return !isSet;283 401 } 284 402 … … 335 453 336 454 static bool createServiceFileCore(char **ppachTemplate, 337 enum ENMFORMAT enmFormat, 338 const char *pcszCommand, 339 const char *pcszArguments, 340 const char *pcszDescription, 341 const char *pcszServiceName); 455 struct SERVICEPARAMETERS 456 *pParamters); 342 457 343 458 /** … … 347 462 * allocation without requiring a single point of exit. 348 463 */ 349 bool createServiceFile(enum ENMFORMAT enmFormat, 350 const char *pcszCommand, 351 const char *pcszArguments, 352 const char *pcszDescription, 353 const char *pcszServiceName) 464 bool createServiceFile(struct SERVICEPARAMETERS *pParameters) 354 465 { 355 466 char *pachTemplate = NULL; 356 bool rc = createServiceFileCore(&pachTemplate, enmFormat, pcszCommand, 357 pcszArguments, pcszDescription, 358 pcszServiceName); 467 bool rc = createServiceFileCore(&pachTemplate, pParameters); 359 468 RTMemFree(pachTemplate); 360 469 return rc; 361 470 } 362 471 472 static bool getSequence(const char *pach, size_t cch, size_t *pcchRead, 473 const char *pcszSequence, size_t cchSequence); 363 474 static bool writeCommand(enum ENMFORMAT enmFormat, const char *pcszCommand); 364 static bool write Arguments(enum ENMFORMAT enmFormat, const char *pcszArguments);475 static bool writeQuoted(enum ENMFORMAT enmFormat, const char *pcszQuoted); 365 476 static bool writePrintableString(enum ENMFORMAT enmFormat, 366 477 const char *pcszString); 478 static void skipLine(const char *pach, size_t cch, size_t *pcchRead); 367 479 368 480 /** The actual implemenation code for @a createServiceFile. */ 369 481 bool createServiceFileCore(char **ppachTemplate, 370 enum ENMFORMAT enmFormat, 371 const char *pcszCommand, 372 const char *pcszArguments, 373 const char *pcszDescription, 374 const char *pcszServiceName) 482 struct SERVICEPARAMETERS *pParameters) 375 483 { 376 484 /* The size of the template data we have read. */ … … 428 536 /* And substitute any of our well-known strings. We favour code 429 537 * readability over efficiency here. */ 430 if ( cchTemplate - cchWritten >= sizeof(COMMAND) - 1 431 && !RTStrNCmp(*ppachTemplate + cchWritten, COMMAND, 432 sizeof(COMMAND) - 1)) 433 { 434 if (!writeCommand(enmFormat, pcszCommand)) 435 return false; 436 cchWritten += sizeof(COMMAND) - 1; 437 } 438 else if ( cchTemplate - cchWritten >= sizeof(ARGUMENTS) - 1 439 && !RTStrNCmp(*ppachTemplate + cchWritten, ARGUMENTS, 440 sizeof(ARGUMENTS) - 1)) 441 { 442 if (pcszArguments && !writeArguments(enmFormat, pcszArguments)) 443 return false; 444 cchWritten += sizeof(ARGUMENTS) - 1; 445 } 446 else if ( cchTemplate - cchWritten >= sizeof(DESCRIPTION) - 1 447 && !RTStrNCmp(*ppachTemplate + cchWritten, DESCRIPTION, 448 sizeof(DESCRIPTION) - 1)) 449 { 450 if (!writePrintableString(enmFormat, pcszDescription)) 451 return false; 452 cchWritten += sizeof(DESCRIPTION) - 1; 453 } 454 else if ( cchTemplate - cchWritten >= sizeof(SERVICE_NAME) - 1 455 && !RTStrNCmp(*ppachTemplate + cchWritten, SERVICE_NAME, 456 sizeof(SERVICE_NAME) - 1)) 457 { 458 if (pcszServiceName) 538 if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 539 COMMAND, sizeof(COMMAND) - 1)) 540 { 541 if (!pParameters->pcszCommand) 459 542 { 460 if (!writePrintableString(enmFormat, pcszServiceName)) 543 RTStrmPrintf(g_pStdErr, "--command not specified.\n"); 544 return false; 545 } 546 if (!writeCommand(pParameters->enmFormat, 547 pParameters->pcszCommand)) 548 return false; 549 } 550 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 551 ARGUMENTS, sizeof(ARGUMENTS) - 1)) 552 { 553 if ( pParameters->pcszArguments 554 && !writeQuoted(pParameters->enmFormat, 555 pParameters->pcszArguments)) 556 return false; 557 } 558 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 559 DESCRIPTION, sizeof(DESCRIPTION) - 1)) 560 { 561 if (!pParameters->pcszDescription) 562 { 563 RTStrmPrintf(g_pStdErr, "--description not specified.\n"); 564 return false; 565 } 566 if (!writePrintableString(pParameters->enmFormat, 567 pParameters->pcszDescription)) 568 return false; 569 } 570 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 571 SERVICE_NAME, sizeof(SERVICE_NAME) - 1)) 572 { 573 if ( !pParameters->pcszCommand 574 && !pParameters->pcszServiceName) 575 { 576 RTStrmPrintf(g_pStdErr, "Neither --command nor --service-name specified.\n"); 577 return false; 578 } 579 if (pParameters->pcszServiceName) 580 { 581 if (!writePrintableString(pParameters->enmFormat, 582 pParameters->pcszServiceName)) 461 583 return false; 462 584 } 463 585 else 464 586 { 465 const char *pcszFileName = RTPathFilename(pcszCommand); 466 const char *pcszExtension = RTPathExt(pcszCommand); 587 const char *pcszFileName = 588 RTPathFilename(pParameters->pcszCommand); 589 const char *pcszExtension = 590 RTPathExt(pParameters->pcszCommand); 467 591 char *pszName = RTStrDupN(pcszFileName, 468 592 pcszExtension … … 475 599 return false; 476 600 } 477 fRc = writePrintableString(enmFormat, pszName); 601 fRc = writePrintableString(pParameters->enmFormat, 602 pszName); 478 603 RTStrFree(pszName); 479 604 if (!fRc) 480 605 return false; 481 606 } 482 cchWritten += sizeof(SERVICE_NAME) - 1; 483 } 484 else if ( cchTemplate - cchWritten > 1 485 && *(*ppachTemplate + cchWritten + 1) == '%') 607 } 608 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 609 HAVE_ONESHOT, sizeof(HAVE_ONESHOT) - 1)) 610 { 611 if (!pParameters->fOneShot) 612 skipLine(*ppachTemplate, cchTemplate, &cchWritten); 613 } 614 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 615 HAVE_DAEMON, sizeof(HAVE_DAEMON) - 1)) 616 { 617 if (pParameters->fOneShot) 618 skipLine(*ppachTemplate, cchTemplate, &cchWritten); 619 } 620 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 621 STOP_COMMAND, sizeof(STOP_COMMAND) - 1)) 622 { 623 if ( pParameters->pcszStopCommand 624 && !writeCommand(pParameters->enmFormat, 625 pParameters->pcszStopCommand)) 626 return false; 627 } 628 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 629 STOP_ARGUMENTS, sizeof(STOP_ARGUMENTS) - 1)) 630 { 631 if ( pParameters->pcszStopArguments 632 && !writeQuoted(pParameters->enmFormat, 633 pParameters->pcszStopArguments)) 634 return false; 635 } 636 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 637 HAVE_STOP_COMMAND, sizeof(HAVE_STOP_COMMAND) - 1)) 638 { 639 if (!pParameters->pcszStopCommand) 640 skipLine(*ppachTemplate, cchTemplate, &cchWritten); 641 } 642 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 643 NO_STOP_COMMAND, sizeof(NO_STOP_COMMAND) - 1)) 644 { 645 if (pParameters->pcszStopCommand) 646 skipLine(*ppachTemplate, cchTemplate, &cchWritten); 647 } 648 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 649 STATUS_COMMAND, sizeof(STATUS_COMMAND) - 1)) 650 { 651 if ( pParameters->pcszStatusCommand 652 && !writeCommand(pParameters->enmFormat, 653 pParameters->pcszStatusCommand)) 654 return false; 655 } 656 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 657 STATUS_ARGUMENTS, sizeof(STATUS_ARGUMENTS) - 1)) 658 { 659 if ( pParameters->pcszStatusArguments 660 && !writeQuoted(pParameters->enmFormat, 661 pParameters->pcszStatusArguments)) 662 return false; 663 } 664 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 665 HAVE_STATUS_COMMAND, 666 sizeof(HAVE_STATUS_COMMAND) - 1)) 667 { 668 if (!pParameters->pcszStatusCommand) 669 skipLine(*ppachTemplate, cchTemplate, &cchWritten); 670 } 671 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 672 NO_STATUS_COMMAND, sizeof(NO_STATUS_COMMAND) - 1)) 673 { 674 if (pParameters->pcszStatusCommand) 675 skipLine(*ppachTemplate, cchTemplate, &cchWritten); 676 } 677 else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, 678 "%%", 2)) 486 679 { 487 680 rc = RTStrmPutCh(g_pStdOut, '%'); … … 491 684 return false; 492 685 } 493 cchWritten += 2;494 686 } 495 687 else … … 502 694 } 503 695 return true; 696 } 697 698 bool getSequence(const char *pach, size_t cch, size_t *pcchRead, 699 const char *pcszSequence, size_t cchSequence) 700 { 701 if ( cch - *pcchRead >= cchSequence 702 && !RTStrNCmp(pach + *pcchRead, pcszSequence, cchSequence)) 703 { 704 *pcchRead += cchSequence; 705 return true; 706 } 707 return false; 504 708 } 505 709 … … 582 786 }; 583 787 584 bool write Arguments(enum ENMFORMAT enmFormat, const char *pcszArguments)788 bool writeQuoted(enum ENMFORMAT enmFormat, const char *pcszQuoted) 585 789 { 586 790 /* Was the last character seen a back slash? */ … … 593 797 if (!outputCharacter('\'')) 594 798 return false; 595 for (; *pcsz Arguments; ++pcszArguments)799 for (; *pcszQuoted; ++pcszQuoted) 596 800 { 597 801 if (fEscaped) … … 602 806 /* One-letter escapes. */ 603 807 for (pachEscapes = aachEscapes; (*pachEscapes)[0]; ++pachEscapes) 604 if (*pcsz Arguments== (*pachEscapes)[0])808 if (*pcszQuoted == (*pachEscapes)[0]) 605 809 { 606 810 if (!escapeAndOutputCharacter(enmFormat, (*pachEscapes)[1])) … … 611 815 continue; 612 816 /* Octal. */ 613 if (*pcsz Arguments >= '0' && *pcszArguments<= '7')817 if (*pcszQuoted >= '0' && *pcszQuoted <= '7') 614 818 { 615 819 uint8_t cNum; … … 617 821 char achDigits[4]; 618 822 int rc; 619 RTStrCopy(achDigits, sizeof(achDigits), pcsz Arguments);823 RTStrCopy(achDigits, sizeof(achDigits), pcszQuoted); 620 824 rc = RTStrToUInt8Ex(achDigits, &pchNext, 8, &cNum); 621 825 if (rc == VWRN_NUMBER_TOO_BIG) 622 826 { 623 827 RTStrmPrintf(g_pStdErr, "Invalid octal sequence at \"%.16s\"\n", 624 pcsz Arguments- 1);828 pcszQuoted - 1); 625 829 return false; 626 830 } 627 831 if (!escapeAndOutputCharacter(enmFormat, cNum)) 628 832 return false; 629 pcsz Arguments+= pchNext - achDigits - 1;833 pcszQuoted += pchNext - achDigits - 1; 630 834 continue; 631 835 } 632 836 /* Hexadecimal. */ 633 if (*pcsz Arguments== 'x')837 if (*pcszQuoted == 'x') 634 838 { 635 839 uint8_t cNum; … … 637 841 char achDigits[3]; 638 842 int rc; 639 RTStrCopy(achDigits, sizeof(achDigits), pcsz Arguments+ 1);843 RTStrCopy(achDigits, sizeof(achDigits), pcszQuoted + 1); 640 844 rc = RTStrToUInt8Ex(achDigits, &pchNext, 16, &cNum); 641 845 if ( rc == VWRN_NUMBER_TOO_BIG … … 644 848 { 645 849 RTStrmPrintf(g_pStdErr, "Invalid hexadecimal sequence at \"%.16s\"\n", 646 pcsz Arguments- 1);850 pcszQuoted - 1); 647 851 return false; 648 852 } 649 853 if (!escapeAndOutputCharacter(enmFormat, cNum)) 650 854 return false; 651 pcsz Arguments+= pchNext - achDigits;855 pcszQuoted += pchNext - achDigits; 652 856 continue; 653 857 } 654 858 /* Output anything else non-zero as is. */ 655 if (*pcsz Arguments)859 if (*pcszQuoted) 656 860 { 657 if (!escapeAndOutputCharacter(enmFormat, *pcsz Arguments))861 if (!escapeAndOutputCharacter(enmFormat, *pcszQuoted)) 658 862 return false; 659 863 continue; … … 663 867 } 664 868 /* Argument separator. */ 665 if (*pcsz Arguments== ' ')869 if (*pcszQuoted == ' ') 666 870 { 667 871 if (!fNextArgument && !outputArgumentSeparator(enmFormat)) … … 673 877 fNextArgument = false; 674 878 /* Start of escape sequence. */ 675 if (*pcsz Arguments== '\\')879 if (*pcszQuoted == '\\') 676 880 { 677 881 fEscaped = true; … … 679 883 } 680 884 /* Anything else. */ 681 if (!outputCharacter(*pcsz Arguments))885 if (!outputCharacter(*pcszQuoted)) 682 886 return false; 683 887 } … … 695 899 return false; 696 900 } 901 902 void skipLine(const char *pach, size_t cch, size_t *pcchRead) 903 { 904 while ( *pcchRead < cch 905 && (pach)[*pcchRead] != '\n' 906 && (pach)[*pcchRead] != '\r') 907 ++*pcchRead; 908 while ( *pcchRead < cch 909 && ( (pach)[*pcchRead] == '\n' 910 || (pach)[*pcchRead] == '\r')) 911 ++*pcchRead; 912 } -
trunk/src/VBox/Installer/linux/install_service/init_template.sh
r44086 r44437 58 58 # as possible, but in particular without trying to look perfectly native. 59 59 # 60 # To use this template as an init script, replace the following text sequences 61 # (wrapped in percent characters) with the values you need: 62 # COMMAND: Path to the service binary or script, with all required escaping for 63 # characters which are special in shell scripts. 64 # ARGUMENTS: The arguments to pass to the binary when starting the service, 65 # with all required escaping for characters which are special in shell scripts. 66 # SERVICE_NAME: The name of the service, using ASCII characters 33 to 126 only. 67 # DESCRIPTION: Short description of the service, suitable for use in texts like 68 # "DESCRIPTION successfully started", using Utf-8 characters 32 to 126 and 128 69 # and upwards. 60 # See the inline documentation in the code for generate_service_file for 61 # details of the generation process. 70 62 71 63 ## Time out in seconds when shutting down the service. … … 264 256 test -d "${LOCK_FOLDER}" && touch "${LOCK_FILE}" 265 257 test -n "`pidofproc %COMMAND%`" && exit 0 266 %COMMAND% %ARGUMENTS% >/dev/null 2>&1 & 267 pid="$!" 268 pidfile="`pidfilename %COMMAND%`" 269 echo "${pid}" > "${pidfile}" 258 %HAVE_DAEMON% %COMMAND% %ARGUMENTS% >/dev/null 2>&1 & 259 %HAVE_DAEMON% pid="$!" 260 %HAVE_DAEMON% pidfile="`pidfilename %COMMAND%`" 261 %HAVE_DAEMON% echo "${pid}" > "${pidfile}" 262 %HAVE_ONESHOT% %COMMAND% %ARGUMENTS% >/dev/null 2>&1 || abort "%DESCRIPTION% failed to start!" 270 263 do_success 271 264 } … … 273 266 stop() 274 267 { 275 killproc %COMMAND% || abort "%DESCRIPTION% failed to stop!" 268 %HAVE_STOP_COMMAND% %STOP_COMMAND% %STOP_ARGUMENTS% || abort "%DESCRIPTION% failed to stop!" 269 %HAVE_DAEMON% killproc %COMMAND% || abort "%DESCRIPTION% failed to stop!" 276 270 rm -f "${LOCK_FILE}" 277 271 log_success_msg "%DESCRIPTION% successfully stopped." … … 281 275 status() 282 276 { 283 pid="`pidofproc %COMMAND%`" 284 test -n "${pid}" && 285 { 286 echo "%SERVICE_NAME% running, process ${pid}" 287 exit 0 288 } 289 test -f "`pidfilename %COMMAND%`" && 290 { 291 echo "%SERVICE_NAME% not running but PID-file present." 292 exit 1 293 } 294 test -f "${LOCK_FILE}" && 295 { 296 echo "%SERVICE_NAME% not running but lock file present." 297 exit 2 298 } 299 echo "%SERVICE_NAME% not running." 300 exit 3 277 %HAVE_STATUS_COMMAND% %STATUS_COMMAND% %STATUS_ARGUMENTS% 278 %HAVE_STATUS_COMMAND% exit 279 %NO_STATUS_COMMAND% pid="`pidofproc %COMMAND%`" 280 %NO_STATUS_COMMAND% test -n "${pid}" && 281 %NO_STATUS_COMMAND% { 282 %NO_STATUS_COMMAND% echo "%SERVICE_NAME% running, process ${pid}" 283 %NO_STATUS_COMMAND% exit 0 284 %NO_STATUS_COMMAND% } 285 %NO_STATUS_COMMAND% test -f "`pidfilename %COMMAND%`" && 286 %NO_STATUS_COMMAND% { 287 %NO_STATUS_COMMAND% echo "%SERVICE_NAME% not running but PID-file present." 288 %NO_STATUS_COMMAND% exit 1 289 %NO_STATUS_COMMAND% } 290 %NO_STATUS_COMMAND% test -f "${LOCK_FILE}" && 291 %NO_STATUS_COMMAND% { 292 %NO_STATUS_COMMAND% echo "%SERVICE_NAME% not running but lock file present." 293 %NO_STATUS_COMMAND% exit 2 294 %NO_STATUS_COMMAND% } 295 %NO_STATUS_COMMAND% echo "%SERVICE_NAME% not running." 296 %NO_STATUS_COMMAND% exit 3 301 297 } 302 298 -
trunk/src/VBox/Installer/linux/install_service/install_service.sh
r44119 r44437 33 33 34 34 `basename $0` --help|--enable|--disable|--force-enable|--force-disable 35 |--remove <options> 35 |--remove [--prefix <prefix>] 36 -- <pass-through parameters> 36 37 37 38 Create a system service which runs a command. In order to make it possible to … … 39 40 the command to be run: 40 41 - That it can be started safely even if all its dependencies are not started 41 and will sleep if necessary until it can start work. Ideally it should start 42 accepting input as early as it can, but delay handling it if necessary. 42 and will sleep if necessary until it can start work. Ideally it should 43 start accepting input as early as it can, but delay handling it if 44 necessary, and delay accessing its dependencies until it actually needs 45 them. 43 46 - That it does not background to simplify service process management. 44 47 - That it can be safely shut down using SIGTERM. … … 49 52 50 53 We currently support System V init only. This will probably soon be extended 51 to BSD init, OpenRC, Pardus Comar and systemd, but probably not Upstart which 52 currently requires modifying init files to disable a service. We also try to 53 enable our service (if requested) in all init systems we find, as we do not know 54 which one is in active use. We assume that this will not have any adverse 55 effects. 54 to BSD init, OpenRC and systemd, but probably not Upstart which currently 55 requires modifying init files to disable a service. We also try to enable our 56 service (if requested) in all init systems we find, as we do not know which one 57 is in active use. We assume that this will not have any adverse effects. 56 58 57 59 --help|--usage … … 72 74 with "--enable", "--disable", "--force-enable" or "--force-disable". 73 75 74 Basic options:76 Option: 75 77 76 78 --prefix <prefix> 77 79 Treat all paths as relative to <prefix> rather than /etc. 78 80 79 Required service options: 80 81 Pass-through parameters will be passed through to the "generate_service_file" 82 tool. 81 83 EOF 82 "${script_folder}/../helpers/generate_service_file" --list-options83 84 } 84 85 … … 94 95 ACTION="" 95 96 PREFIX="/etc/" 96 ARGUMENTS=""97 97 SERVICE_NAME="" 98 98 99 99 # Process arguments. 100 ## @todo Pass more through unmodified to generate_service_file to reduce 101 # duplication. Or then again, maybe the hassle of perserving the 102 # positional parameters is not worth it. 103 while test x"${#}" != "x0"; do 100 while test x"${1}" != "x--"; do 104 101 case "${1}" in 105 102 "--help"|"--usage") … … 123 120 PREFIX="${2}" 124 121 shift 2;; 125 "--command")126 test -z "${2}" && abort "${1}: missing argument."127 COMMAND="${2}"128 shift 2;;129 "--arguments")130 test -z "${2}" && abort "${1}: missing argument."131 ARGUMENTS="${2}"132 shift 2;;133 "--description")134 test -z "${2}" && abort "${1}: missing argument."135 DESCRIPTION="${2}"136 shift 2;;137 "--service-name")138 test -z "${2}" && abort "${1}: missing argument."139 SERVICE_NAME="${2}"140 shift 2;;141 122 *) 142 123 abort "Unknown option ${1}.";; 143 124 esac 144 125 done 126 shift 145 127 146 128 # Check required options and set default values for others. 147 129 test -z "${ACTION}" && 148 130 abort "Please supply an install action." 149 if test -n "${INSTALL}"; then 150 test -z "${COMMAND}" && 151 abort "Please supply a start command." 152 test -f "${COMMAND}" && test -x "${COMMAND}" || 153 abort "The start command must be an executable file." 154 case "${COMMAND}" in 155 /*) ;; 156 *) abort "The start command must have an absolute path." ;; 157 esac 158 test -z "${DESCRIPTION}" && 159 abort "Please supply a service description." 160 else 161 test -z "${COMMAND}" && test -z "${SERVICE_NAME}" && 162 abort "Please supply a service name or a start command." 163 fi 164 # Get the service name from the command path if not explicitly 165 # supplied. 131 132 # Get the service name. 133 SERVICE_NAME=`echo "%SERVICE_NAME%" | 134 "${script_folder}/../helpers/generate_service_file" --format shell "${@}"` 166 135 test -z "${SERVICE_NAME}" && 167 SERVICE_NAME="`expr "${COMMAND}" : '.*/\(.*\)\..*'`" 168 test -z "${SERVICE_NAME}" && 169 SERVICE_NAME="`expr "${COMMAND}" : '.*/\(.*\)'`" 136 abort "Please supply a command path." 170 137 171 138 # Keep track of whether we found at least one initialisation system. … … 193 160 test -f "${path}/${SERVICE_NAME}" && update="${UPDATE}" 194 161 if test -n "${INSTALL}"; then 195 "${script_folder}/../helpers/generate_service_file" --format shell --command "${COMMAND}" --arguments "${ARGUMENTS}" --description "${DESCRIPTION}" --service-name "${SERVICE_NAME}" < "${script_folder}/init_template.sh" > "${path}/${SERVICE_NAME}"162 "${script_folder}/../helpers/generate_service_file" --format shell "${@}" < "${script_folder}/init_template.sh" > "${path}/${SERVICE_NAME}" 196 163 chmod a+x "${path}/${SERVICE_NAME}" 197 164 else … … 200 167 # Attempt to install using both system V symlinks and OpenRC, assuming 201 168 # that both will not be in operation simultaneously (but may be 202 # switchable). BSD init expects the user to enable services explicitly. 169 # switchable). BSD init expects the user to enable services 170 # explicitly. 203 171 if test -z "${update}"; then 204 172 # Various known combinations of sysvinit rc directories. -
trunk/src/VBox/Installer/linux/scripts/VBoxHeadlessXOrg.sh
r44112 r44437 297 297 CONFIGURATION_FILE_ESCAPED=$(echo "${CONFIGURATION_FILE}" | sed 's/\([ \%]\)/\\\1/g') 298 298 if [ "x${do_install}" = "xinstall" ]; then 299 ${SCRIPT_FOLDER}install_service -- command "${SCRIPT_FOLDER}"$(basename "${SCRIPT_NAME}") --arguments "--conf-file ${CONFIGURATION_FILE_ESCAPED}" --service-name "${SERVICE_NAME}" --description "${SERVICE_DESCRIPTION}" --enable299 ${SCRIPT_FOLDER}install_service --enable -- --command "${SCRIPT_FOLDER}"$(basename "${SCRIPT_NAME}") --arguments "--conf-file ${CONFIGURATION_FILE_ESCAPED}" --service-name "${SERVICE_NAME}" --description "${SERVICE_DESCRIPTION}" 300 300 else 301 ${SCRIPT_FOLDER}install_service -- service-name "${SERVICE_NAME}" --remove301 ${SCRIPT_FOLDER}install_service --remove -- --service-name "${SERVICE_NAME}" 302 302 fi 303 303 exit 0 -
trunk/src/VBox/Installer/linux/testcase/tstInstallInit.sh
r44119 r44437 68 68 } 69 69 70 # Create a trivial test command in temporary directory $1 with name $2. 71 test_oneshot() 72 { 73 cat > "${1}/${2}" << EOF 74 #!/bin/sh 75 if test "\${1}" = start; then 76 touch "${1}/started" 77 else 78 rm "${1}/started" 79 fi 80 exit 0 81 EOF 82 chmod u+x "${1}/${2}" 83 } 84 70 85 # Test some dodgy input values against generate_service_file. 86 # Make sure there is a substitution pattern at the end too. 71 87 print_line "generation of shell script from template." 72 input='TEST1%DESCRIPTION%%%%SERVICE_NAME% TST2 TEST %ARGUMENTS%%COMMAND%'88 input='TEST1%DESCRIPTION%%%%SERVICE_NAME%%STOP_COMMAND% TST2 TEST %ARGUMENTS%%COMMAND%' 73 89 out=`echo "${input}" | 74 90 helpers/generate_service_file --command '/usr/bin … … 82 98 world'\' 83 99 case "${out}" in ${expected}) 84 echo "SUCCESS";; 100 echo "SUCCESS (1)";; 101 *) 102 cat << EOF 103 FAILED: expected 104 ${expected} 105 but got 106 ${out} 107 EOF 108 esac 109 input='TEST%HAVE_STOP_COMMAND%%SERVICE_NAME%%STOP_COMMAND% TST2 110 TEST %COMMAND%' 111 out=`echo "${input}" | 112 helpers/generate_service_file --command '/usr/bin/hello' --format shell --description ''` 113 expected='TEST TEST '\''/usr/bin/hello'\''' 114 case "${out}" in ${expected}) 115 echo "SUCCESS (2)";; 116 *) 117 cat << EOF 118 FAILED: expected 119 ${expected} 120 but got 121 ${out} 122 EOF 123 esac 124 input='TEST%HAVE_STOP_COMMAND%%SERVICE_NAME%%STOP_COMMAND% %STOP_ARGUMENTS% TST2 125 TEST %COMMAND%' 126 out=`echo "${input}" | 127 helpers/generate_service_file --command '/usr/bin/hello' --format shell --description '' --stop-command /usr/bin/stop --stop-arguments hello` 128 expected='TESThello'\''/usr/bin/stop'\'' '\''hello'\'' TST2 129 TEST '\''/usr/bin/hello'\''' 130 case "${out}" in ${expected}) 131 echo "SUCCESS (3)";; 85 132 *) 86 133 cat << EOF … … 115 162 test_service "${tmpdir}" "service" 116 163 # And install it. 117 scripts/install_service --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" --prefix "${tmpdir}" --enable||164 scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || 118 165 fail_msg "\"scripts/install_service\" failed." 119 166 # Check that the main service file was created as specified. … … 159 206 fi 160 207 208 # Test an one shot init script installation. 209 print_line "installing a one shot init script." 210 failed="" 211 # Create a simulated init system layout. 212 tmpdir="${tmpbase}0" 213 create_simulated_init_tree "${tmpdir}" 214 # Create the command binary. 215 test_oneshot "${tmpdir}" "command" 216 # And install the script. 217 scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/command" --arguments "start" --description "My description" --stop-command "${tmpdir}/command" --stop-arguments "stop" --one-shot || 218 fail_msg "\"scripts/install_service\" failed." 219 # Sanity test. 220 test -f "${tmpdir}/started" && 221 fail_msg "\"${tmpdir}/started\" already exists!" 222 # Try to start the service using the symbolic links which should have been 223 # created. 224 if "${tmpdir}/rc3.d/S20command" --prefix "${tmpdir}" --lsb-functions "" start >/dev/null 2>&1; then 225 test -f "${tmpdir}/started" || 226 fail_msg "\"${tmpdir}/rc3.d/S20command\" did not start correctly." 227 else 228 fail_msg "could not start \"${tmpdir}/rc3.d/S20command\"." 229 fi 230 # Try to stop the service using the symbolic links which should have been 231 # created. 232 if "${tmpdir}/rc.d/rc6.d/K80command" --prefix "${tmpdir}" --lsb-functions "" stop >/dev/null 2>&1; then 233 test -f "${tmpdir}/started" && 234 echo "\"${tmpdir}/rc.d/rc6.d/K80command\" did not stop correctly." 235 else 236 fail_msg "could not stop \"${tmpdir}/rc.d/rc6.d/K80command\"." 237 fi 238 # Final summary. 239 if test -n "${failed}"; then 240 echo "${failed}" 241 else 242 echo SUCCESS 243 fi 244 161 245 # Test an init script removal. 162 246 print_line "removing an init script." … … 168 252 test_service "${tmpdir}" "service" 169 253 # Install it. 170 scripts/install_service -- command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" --prefix "${tmpdir}" --enable||254 scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || 171 255 fail_msg "\"scripts/install_service\" failed." 172 256 # And remove it again. 173 scripts/install_service -- command "${tmpdir}/service" --prefix "${tmpdir}" --remove||257 scripts/install_service --prefix "${tmpdir}" --remove -- --command "${tmpdir}/service" || 174 258 fail_msg "\"scripts/install_service\" failed." 175 259 # After uninstallation this should be the only file left in the init tree. … … 193 277 test_service "${tmpdir}" "service" 194 278 # Install it. 195 scripts/install_service -- command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" --prefix "${tmpdir}" --enable||279 scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || 196 280 fail_msg "\"scripts/install_service\" failed." 197 281 # Install it disabled without forcing. 198 scripts/install_service -- command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" --prefix "${tmpdir}" --disable||282 scripts/install_service --prefix "${tmpdir}" --disable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || 199 283 fail_msg "\"scripts/install_service\" failed." 200 284 test "x`find "${tmpdir}"/rc*.d "${tmpdir}/runlevel" -type l | wc -l`" = "x15" || … … 216 300 test_service "${tmpdir}" "service" 217 301 # Install it. 218 scripts/install_service -- command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" --prefix "${tmpdir}" --disable||302 scripts/install_service --prefix "${tmpdir}" --disable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || 219 303 fail_msg "\"scripts/install_service\" failed." 220 304 # Install it disabled without forcing. 221 scripts/install_service -- command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" --prefix "${tmpdir}" --enable||305 scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || 222 306 fail_msg "\"scripts/install_service\" failed." 223 307 test "x`find "${tmpdir}"/rc*.d "${tmpdir}/runlevel" -type l`" = "x" || … … 239 323 test_service "${tmpdir}" "service" 240 324 # Install it. 241 scripts/install_service -- command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" --prefix "${tmpdir}" --enable||325 scripts/install_service --prefix "${tmpdir}" --enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || 242 326 fail_msg "\"scripts/install_service\" failed." 243 327 # Install it disabled without forcing. 244 scripts/install_service -- command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" --prefix "${tmpdir}" --force-disable||328 scripts/install_service --prefix "${tmpdir}" --force-disable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || 245 329 fail_msg "\"scripts/install_service\" failed." 246 330 test "x`find "${tmpdir}"/rc*.d "${tmpdir}/runlevel" -type l`" = "x" || … … 262 346 test_service "${tmpdir}" "service" 263 347 # Install it. 264 scripts/install_service -- command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" --prefix "${tmpdir}" --disable||348 scripts/install_service --prefix "${tmpdir}" --disable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || 265 349 fail_msg "\"scripts/install_service\" failed." 266 350 # Install it disabled without forcing. 267 scripts/install_service -- command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" --prefix "${tmpdir}" --force-enable||351 scripts/install_service --prefix "${tmpdir}" --force-enable -- --command "${tmpdir}/service" --arguments "test of my\ arguments" --description "My description" || 268 352 fail_msg "\"scripts/install_service\" failed." 269 353 test "x`find "${tmpdir}"/rc*.d "${tmpdir}/runlevel" -type l | wc -l`" = "x15" ||
Note:
See TracChangeset
for help on using the changeset viewer.