00001 /*! 00002 * @file manifest.c 00003 * 00004 * @brief Read JAR manifest file. 00005 * 00006 * 00007 * @section Control 00008 * 00009 * \$URL: https://svn.apache.org/path/name/manifest.c $ \$Id: manifest.c 0 09/28/2005 dlydick $ 00010 * 00011 * Copyright 2005 The Apache Software Foundation 00012 * or its licensors, as applicable. 00013 * 00014 * Licensed under the Apache License, Version 2.0 ("the License"); 00015 * you may not use this file except in compliance with the License. 00016 * You may obtain a copy of the License at 00017 * 00018 * http://www.apache.org/licenses/LICENSE-2.0 00019 * 00020 * Unless required by applicable law or agreed to in writing, 00021 * software distributed under the License is distributed on an 00022 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 00023 * either express or implied. 00024 * 00025 * See the License for the specific language governing permissions 00026 * and limitations under the License. 00027 * 00028 * @version \$LastChangedRevision: 0 $ 00029 * 00030 * @date \$LastChangedDate: 09/28/2005 $ 00031 * 00032 * @author \$LastChangedBy: dlydick $ 00033 * Original code contributed by Daniel Lydick on 09/28/2005. 00034 * 00035 * @section Reference 00036 * 00037 */ 00038 00039 #include "arch.h" 00040 ARCH_COPYRIGHT_APACHE(manifest, c, "$URL: https://svn.apache.org/path/name/manifest.c $ $Id: manifest.c 0 09/28/2005 dlydick $"); 00041 00042 00043 #include <stdio.h> 00044 #include <ctype.h> 00045 #include <strings.h> 00046 00047 #include "jvmcfg.h" 00048 #include "heap.h" 00049 #include "exit.h" 00050 #include "util.h" 00051 00052 /*! 00053 * @brief Search a JAR manifest file for a main class attribute. 00054 * 00055 * This attribute MUST be all on one line and without any 00056 * line continuations breaking up the class name. Look for 00057 * a line of text like this, where @b | indicates that the 00058 * following character is the first one on the line: 00059 * 00060 * @verbatim 00061 | 00062 |Main-Class: name.of.start.class\n 00063 | 00064 00065 WITHOUT any line continuations, 00066 00067 | 00068 |Main-Class: name.of.sta\n 00069 | rt.class\n 00070 | 00071 00072 @endverbatim 00073 * 00074 * @todo Although such a continuation is supported by the JAR file, 00075 * this implementation does not support it (yet). With this 00076 * restriction, the if only one single space separates the name of 00077 * the attribute and the class name, then since a line may be up 00078 * to 72 characters long (that is JVMCFG_JARFILE_MANIFEST_LINE_MAX 00079 * characters), then the class name may be 61 characters long. 00080 * 00081 * 00082 * @param mnfname JAR manifest file name, /absolute/path/name 00083 * 00084 * 00085 * @returns Heap pointer to null-terminated class name, or 00086 * @link #rnull rnull@endlink if not found. 00087 * Call HEAP_FREE_DATA() when done. 00088 * 00089 */ 00090 rchar *manifest_get_main(rchar *mnfname) 00091 { 00092 FILE *mf = fopen(mnfname, "r"); 00093 00094 if (rnull == mf) 00095 { 00096 return((rchar *) rnull); 00097 } 00098 00099 rchar *mnfdata = HEAP_GET_DATA(JVMCFG_STDIO_BFR, rfalse); 00100 00101 int mclen = strlen(JVMCFG_JARFILE_MANIFEST_MAIN_CLASS); 00102 00103 /* Read until end of file or match located */ 00104 while (mnfdata == (rchar *) fgets(mnfdata, JVMCFG_STDIO_BFR, mf)) 00105 { 00106 /* 00107 * Scan for ^Main-Class: attribute name (text starting 00108 * at beginnin of line) 00109 */ 00110 if (0 != strncmp(mnfdata, 00111 JVMCFG_JARFILE_MANIFEST_MAIN_CLASS, 00112 mclen)) 00113 { 00114 continue; 00115 } 00116 00117 /* 00118 * Attribute name found. 00119 * 00120 * Scan for first non-white character after attribute name. 00121 * This will be the start of the class name. 00122 */ 00123 rint i; 00124 for (i = mclen; i < strlen(mnfdata); i++) 00125 { 00126 /* if <b>white space</b> is rfalse */ 00127 if (0 == isspace((int) mnfdata[i])) 00128 { 00129 break; /* Found first non-white-space character */ 00130 } 00131 } 00132 /* If nothing else, the \n at end of line is white space */ 00133 00134 /* 00135 * Class name found. 00136 * 00137 * Scan for first white character after class name. 00138 * This will be the end of the class name. 00139 */ 00140 rint j; 00141 for (j = i; j < strlen(mnfdata); j++) 00142 { 00143 /* if <b>white space</b> is @link #rtrue rtrue@endlink */ 00144 if (0 != isspace((int) mnfdata[j])) 00145 { 00146 break; /* Found first white-space character */ 00147 } 00148 } 00149 /* If nothing else, the \n at end of line is white space */ 00150 00151 fclose(mf); 00152 00153 /* Allocate space for non-empty class name plus NUL byte */ 00154 rchar *mnfresult; 00155 if (i != j) 00156 { 00157 mnfresult = HEAP_GET_DATA(j - i + sizeof(rchar), rfalse); 00158 00159 /* If failure above, HEAP_FREE_DATA(mnfdata) is never run */ 00160 } 00161 else 00162 { 00163 /* Do not process empty class name, declare error instead */ 00164 HEAP_FREE_DATA(mnfdata); 00165 00166 sysErrMsg("manifest_get_main", 00167 "Missing class name in manifest file %s", 00168 mnfname); 00169 exit_jvm(EXIT_MANIFEST_JAR); 00170 /*NOTREACHED*/ 00171 } 00172 00173 memcpy(mnfresult, &mnfdata[i], j - i); 00174 mnfresult[j - i] = '\0'; 00175 00176 HEAP_FREE_DATA(mnfdata); 00177 return(mnfresult); 00178 } 00179 00180 fclose(mf); 00181 00182 HEAP_FREE_DATA(mnfdata); 00183 00184 return((rchar *) rnull); 00185 00186 } /* END of manifest_get_main() */ 00187 00188 00189 /* EOF */ 00190