1 /*  mp3asm: an mp3 frameeditor.
2  *
3  *  parse.c : parses the command line input.
4  *
5  *  Copyright (C) 2001  Luc Verhaegen (_Death_@Undernet(IRC))
6  *                                    <dw_death_@hotmail.com>
7  *  Copyright (C) 1996-1997 Olli Fromme <olli@fromme.com>
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include <unistd.h>
25 #include "mp3asm.h"
26 #include "parse.h"
27 #include "utils.h"
28 
29 /* mp3asm.c */
30 extern void new_input (void);
31 
32 /* utils.c */
33 extern void *tmalloc (size_t size);
34 extern void print_std (int verb);
35 
36 /*
37  * implementing callbacks!
38  *
39  */
40 static void usage (void);
41 
42 static void
bad_flag(char * string,int i)43 bad_flag (char *string, int i)
44 {
45   if (!i)
46     sprintf (mp3asm_log.buf, "%s: Bad flag specified: \"%s\"\n", me, string);
47   else
48     sprintf (mp3asm_log.buf, "%s: Bad flag specified: \"%s\" from \"%s\"\n", me, string+i, string);
49   print_std (-1);
50   exit (EX_USAGE);
51 }
52 
53 static void
arg_needed(char flag)54 arg_needed (char flag)
55 {
56   sprintf (mp3asm_log.buf, "%s: No argument specified for flag %c\n", me, flag);
57   print_std (-1);
58   exit (EX_USAGE);
59 }
60 
61 static void
double_flag(char flag)62 double_flag (char flag)
63 {
64   sprintf (mp3asm_log.buf, "%s: Flag specified twice: \"%c\"\n", me, flag);
65   print_std (-1);
66   exit (EX_USAGE);
67 }
68 
69 static void
bad_arg(char * string)70 bad_arg (char *string)
71 {
72   sprintf (mp3asm_log.buf, "%s: Bad argument given: \"%s\"\n", me, string);
73   print_std (-1);
74   exit (EX_USAGE);
75 }
76 
77 static int
incr_verbosity(char * arg)78 incr_verbosity (char *arg)
79 {
80   verbosity++;
81   return (0);
82 }
83 
84 static int
start_frame(char * arg)85 start_frame (char *arg)
86 {
87   if (input[inputs - 1]->startframe)
88     return (1);
89   if ((input[inputs - 1]->startframe = atol (arg)))
90     return (0);
91   return (2);
92 }
93 
94 static int
end_frame(char * arg)95 end_frame (char *arg)
96 {
97   if (input[inputs - 1]->endframe || input[inputs - 1]->readframes)
98     return (1);
99   if ((input[inputs - 1]->endframe = atol (arg)))
100     return (0);
101   return (2);
102 }
103 
104 static int
read_frames(char * arg)105 read_frames (char *arg)
106 {
107   if (input[inputs - 1]->readframes || input[inputs - 1]->endframe)
108     return (1);
109   if ((input[inputs - 1]->readframes = atol (arg)))
110     return (0);
111   return (2);
112 }
113 
114 static int
use_tag(char * arg)115 use_tag  (char *arg)
116 {
117   int i = inputs;
118   while (i)
119     {
120       i--;
121       if (input[inputs - 1]->use_id3)
122 	return (1);
123     }
124   input[inputs - 1]->use_id3++;
125   return (0);
126 }
127 
128 static int
set_output(char * arg)129 set_output (char *arg)
130 {
131   if (output->name)
132     return (1);
133   output->name = strcpy (tmalloc (strlen (arg) + 1), arg);
134   return (0);
135 }
136 
137 static int
report(char * arg)138 report (char *arg)
139 {
140   char *name = tmalloc (1024 * sizeof (char));
141   if (!gethostname (name, 1024))
142     sprintf (mp3asm_log.buf, "Sending notification to the authorities; Illegal use of copyrighted material on %s\n", name);
143   free (name);
144   return (0);
145 }
146 
147 static int
use_log(char * arg)148 use_log (char *arg)
149 {
150   if (mp3asm_log.name)
151     return (1);
152   mp3asm_log.name = strcpy (tmalloc (strlen (arg) + 1), arg);
153   return (0);
154 }
155 
156 static int
print_help(char * arg)157 print_help (char *arg)
158 {
159   usage ();
160   return (0);
161 }
162 
163 #define NO_ARG 0
164 #define NEEDS_ARG 1
165 
166 struct parse_flags
167 {
168   char flag;
169   char *help;
170   int (*handler) (char *arg);
171   int args;
172 };
173 
174 struct parse_flags parse[] =
175 {
176   {'v', "Increase verbosity.", incr_verbosity, NO_ARG},
177   {'s', "Set the starting frame.", start_frame, NEEDS_ARG},
178   {'e', "Set the ending frame.", end_frame, NEEDS_ARG},
179   {'r', "Set the number of frames to read (conflicts with 'e')", read_frames, NEEDS_ARG},
180   {'t', "Use id3-tag of the file. (should be used only once!)", use_tag, NO_ARG},
181   {'o', "Name of the file to output to. (default = changed input filename)", set_output, NEEDS_ARG},
182   {'N', "Not reporting illegal copyrighte material to the authorities.", report, NO_ARG},
183   {'l', "Log to file.", use_log, NEEDS_ARG},
184   {'h', "Print this help.", print_help, NO_ARG},
185   { 0, NULL, NULL, NO_ARG}
186 };
187 
188 static void
usage(void)189 usage (void)
190 {
191   int k = 0;
192 
193   sprintf (mp3asm_log.buf, "Usage: %s [options] inputfile.mp3 [...]\n", me);
194   print_std (0);
195   while (parse[k].flag)
196     {
197       sprintf (mp3asm_log.buf, "   -%c     %s\n", parse[k].flag, parse[k].help);
198       print_std (0);
199       k++;
200     }
201 
202   exit (EX_USAGE);
203 }
204 
205 /*
206  * Parses an individual argument.
207  *
208  */
209 
210 void
parse_argument(int argc,char * argv[])211 parse_argument (int argc, char *argv[])
212 {
213   int strlength, i, j, k, temp;
214 
215   for (i = 1; i < argc; ++i)
216     {
217       if (argv[i][0] == '-') /* flag */
218 	{
219 	  strlength = strlen ((char *)argv[i]);
220 	  for (j = 1 ; j < strlength; ++j)
221 	    {
222 	      k = 0;
223 	      while (parse[k].flag != argv[i][j])
224 		{
225 		  if (parse[k].flag == 0)
226 		    bad_flag (argv[i], j);
227 		  k++;
228 		}
229 	      if (parse[k].args == NEEDS_ARG)
230 		{
231 		  if (++j < strlength) /* this is not the last char */
232 		    {
233 		      if ((temp = parse[k].handler (argv[i] + j)) == 1)
234 			double_flag (argv[i][j - 1]);
235 		      else if (temp == 2)
236 			bad_arg (argv[i] + j);
237 		    }
238 		  else if (argv[++i][0] != '-')
239 		    {
240 		      if ((temp = parse[k].handler (argv[i])) == 1)
241 			double_flag (argv[i - 1][j - 1]);
242 		      else if (temp == 2)
243 			bad_arg (argv[i]);
244 
245 		    }
246 		  else
247 		    arg_needed (parse[k].flag);
248 		  j = strlength;
249 		}
250 	      else
251 		{
252 		  if (parse[k].handler (NULL) == 1)
253 		    double_flag (argv[i][j] );
254 		}
255 	    }
256 	}
257       else /* input file */
258 	{
259 
260 	  input[inputs - 1]->name = tmalloc (strlen (argv[i]) + 1);
261 	   strcpy (input[inputs - 1]->name, argv[i]);
262 	   /*sprintf (mp3asm_log.buf, "%d input: %s\n", inputs - 1, input[inputs - 1]->name);
263 	     print_std (5);*/
264 	  new_input ();
265 	}
266     }
267 }
268 
269 /*
270  * Check if the options r useable.
271  *
272  */
273 
274 static void
check_options()275 check_options ()
276 {
277   int id3=0, i;
278 
279   for (i = 0; i < inputs; ++i)
280     {
281       if (input[i]->readframes)
282 	input[i]->endframe = input[i]->startframe + input[i]->readframes;
283       else if (input[i]->endframe)
284 	input[i]->readframes = input[i]->endframe - input[i]->startframe;
285 
286       if ((input[i]->endframe && (input[i]->startframe > input[i]->endframe)) || (input[i]->startframe && (input[i]->startframe == input[i]->endframe)))
287 	{
288 	 sprintf (mp3asm_log.buf, "%s: Invalid options given. The number of frames to skip should be smaller than the number of the last frame to read for \"%s\".\n", me, input[i]->name);
289 	 print_std (-1);
290  	exit (EX_USAGE);
291        }
292 
293       if (input[i]->use_id3) {
294 	if (id3)
295 	  {
296 	    sprintf (mp3asm_log.buf, "%s: Invalid options given. More than one id3 tag specified for use.\n", me);
297 	    print_std (-1);
298 	    exit (EX_USAGE);
299 	  }
300 	else
301 	  ++id3;
302       }
303     }
304   if (input[inputs - 1]->name == NULL)
305     {
306       if (input[inputs -1]->startframe ||input[inputs -1]->endframe || input[inputs -1]->readframes || input[inputs -1]->use_id3)
307 	{
308 	  sprintf (mp3asm_log.buf, "%s: Flags specified for input file, but no input file has been given.\n", me);
309 	  print_std (-1);
310 	  exit(EX_USAGE);
311 	}
312       free (input[inputs - 1]);
313       inputs--;
314     }
315   if (!inputs)
316     {
317       sprintf (mp3asm_log.buf, "%s: No input files specified.\n", me);
318       print_std (-1);
319       exit (EX_USAGE);
320     }
321   /* else
322     {
323       sprintf (mp3asm_log.buf, "inputs: %d\n", inputs);
324       print_std (5);
325       }*/
326 
327   if (!info)
328     {
329       sprintf (mp3asm_log.buf, "%s: Program from Olli Fromme & _Death_.\n", me);
330       print_std (-1);
331 
332       if (!output->name)
333 	sprintf (mp3asm_log.buf, "%s: Checking the following mp3 files for header errors:\n", me);
334       else
335 	sprintf(mp3asm_log.buf, "%s: Taking input from:\n", me);
336       print_std (1);
337 
338       for (i = 0; i < inputs; ++i)
339 	{
340 	  sprintf (mp3asm_log.buf, "%s: input %d: %s from frame %ld to %ld [%ld].\n", me, i, input[i]->name, input[i]->startframe, input[i]->endframe, input[i]->readframes);
341 	  print_std (2);
342 	}
343 
344       if (!output->name)
345 	sprintf (mp3asm_log.buf, "%s: No output file specified.\n", me);
346       else
347 	sprintf (mp3asm_log.buf, "%s: Outputting to %s.\n", me, output->name);
348       print_std (1);
349     }
350 }
351 
352 /*
353  * Parses the arguments.
354  *
355  */
356 
357 void
parse_args(int argc,char * argv[])358 parse_args (int argc, char *argv[])
359 {
360   if (argc < 2)
361     usage();
362 
363   parse_argument(argc, argv) ;
364   check_options();
365 }
366 
367 /* EOF */
368