📄 toast.c
字号:
/*
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
*/
/* $Header: /home/kbs/jutta/src/gsm/gsm-1.0/src/RCS/toast.c,v 1.1 1992/10/28 00:15:50 jutta Exp $ */
#include "toast.h"
/* toast -- lossy sound compression using the gsm library.
*/
char * progname;
int f_decode = 0; /* decode rather than encode (-d) */
int f_cat = 0; /* write to stdout, not foo.gsm (-c) */
int f_force = 0; /* force deletion (-f) */
int f_precious = 0; /* avoid deletion (-p) */
int f_fast = 0; /* use faster fpt algorithm (-F) */
int f_verbose = 0; /* debugging (-V) */
struct stat instat; /* stat (inname) */
FILE *in, *out;
char *inname, *outname;
/*
* The function (*output)() writes a frame of 160 samples given as
* 160 signed 16 bit values (gsm_signals) to <out>.
* The function (*input)() reads one such frame from <in>.
* The function (*init_output)() begins output (e.g. writes a header).,
* The function (*init_input)() begins input (e.g. skips a header).
*
* There are different versions of input, output, init_input and init_output
* for different formats understood by toast; which ones are used
* depends on the command line arguments and, in their absence, the
* filename; the fallback is #defined in toast.h
*
* The specific implementations of input, output, init_input and init_output
* for a format `foo' live in toast_foo.c.
*/
int (*output ) P((gsm_signal *)),
(*input ) P((gsm_signal *));
int (*init_input) P(()),
(*init_output) P(());
static int generic_init P0() { return 0; } /* NOP */
extern int audio_init_input(), audio_init_output();
extern int ulaw_input P((gsm_signal*)), ulaw_output P((gsm_signal *));
extern int alaw_input P((gsm_signal*)), alaw_output P((gsm_signal *));
extern int linear_input P((gsm_signal*)), linear_output P((gsm_signal *));
struct fmtdesc {
char * name, * longname, * suffix;
int (* init_input ) P(()),
(* init_output) P(());
int (* input ) P((gsm_signal * )),
(* output) P((gsm_signal * ));
} f_audio = {
"audio",
"8 kHz, 8 bit u-law encoding with Sun audio header", ".au",
audio_init_input,
audio_init_output,
ulaw_input,
ulaw_output
}, f_ulaw = {
"u-law", "plain 8 kHz, 8 bit u-law encoding", ".u",
generic_init,
generic_init,
ulaw_input,
ulaw_output
}, f_alaw = {
"A-law", "8 kHz, 8 bit A-law encoding", ".A",
generic_init,
generic_init,
alaw_input,
alaw_output
}, f_linear = {
"linear",
"16 bit (13 significant) signed 8 kHz signal", ".l",
generic_init,
generic_init,
linear_input,
linear_output
};
struct fmtdesc * alldescs[] = {
&f_audio,
&f_alaw,
&f_ulaw,
&f_linear,
(struct fmtdesc *)NULL
};
#define DEFAULT_FORMAT f_ulaw /* default audio format, others */
/* are: f_alaw,f_audio,f_linear */
struct fmtdesc * f_format = 0;
/*
* basename + suffix of a pathname
*/
char * endname P1((name), char * name)
{
if (name) {
char * s = strrchr(name, '/');
if (s && s[1]) name = s + 1;
}
return name;
}
/*
* Try to figure out what we're supposed to do from the argv[0], if
* any, and set the parameters accordingly.
*/
static void parse_argv0 P1((av0), char * av0 )
{
char * c;
int l;
progname = av0 = endname(av0 ? av0 : "toast");
/* If the name starts with `un', we want to decode, not code.
* If the name ends in `cat', we want to write to stdout,
* and decode as well.
*/
if (!strncmp(av0, "un", 2)) f_decode = 1;
if ( (l = strlen(av0)) >= 3 /* strlen("cat") */
&& !strcmp( av0 + l - 3, "cat" )) f_cat = f_decode = 1;
}
/*
* Check whether the name (possibly generated by appending
* .gsm to something else) is short enough for this system.
*/
int length_okay P1((name), char * name)
{
long max_filename_length = 0;
char * end, * s, tmp;
/* If our _pathname_ is too long, we'll usually not be
* able to open the file at all -- don't worry about that.
*
* But if the _filename_ is too long, there is danger of
* silent truncation on some systems, which results
* in the target replacing the source!
*/
if (!name) return 0;
end = endname(name);
#ifdef NAME_MAX
max_filename_length = NAME_MAX;
#else
#ifdef _PC_NAME_MAX
/* s = dirname(name)
*/
if ((s = end) > name) {
if (s > name + 1) s--;
tmp = s;
*s = 0;
}
errno = 0;
max_filename_length = pathconf(s > name ? name : ".", _PC_NAME_MAX);
if (max_filename_length == -1 && errno) {
perror( s > name ? name : "." );
fprintf(stderr,
"%s: cannot get dynamic filename length limit for %s.\n",
progname, s > name ? name : ".");
return 0;
}
if (s > name) *s = tmp;
#endif /* _PC_NAME_MAX */
#endif /* !NAME_MAX */
if (max_filename_length > 0 && strlen(end) > max_filename_length) {
fprintf(stderr,
"%s: filename \"%s\" is too long (maximum is %ld)\n",
progname, endname(name), max_filename_length );
return 0;
}
return 1;
}
/*
* Return a pointer the suffix of a string, if any.
* A suffix alone has no suffix, an empty suffix can not be had.
*/
static char * suffix P2((name, suf), char *name, char * suf)
{
int nlen = strlen(name);
int slen = strlen(suf);
if (!slen || nlen <= slen) return (char *)0;
name += nlen - slen;
return memcmp(name, suf, slen) ? (char *)0 : name;
}
void catch_signals P1((fun), SIGHANDLER_T (*fun)())
{
#ifdef SIGHUP
signal( SIGHUP, fun );
#endif
#ifdef SIGINT
signal( SIGINT, fun );
#endif
#ifdef SIGPIPE
signal( SIGPIPE, fun );
#endif
#ifdef SIGTERM
signal( SIGTERM, fun );
#endif
#ifdef SIGXFSZ
signal( SIGXFSZ, fun );
#endif
}
static SIGHANDLER_T onintr P0()
{
char * tmp = outname;
#ifdef HAS_SYSV_SIGNALS
catch_signals( SIG_IGN );
#endif
outname = (char *)0;
if (tmp) (void)unlink(tmp);
exit(1);
}
/*
* Allocate some memory and complain if it fails.
*/
static char * emalloc P1((len), int len)
{
char * s;
if (!(s = malloc(len))) {
fprintf(stderr, "%s: failed to malloc %d bytes -- abort\n",
progname, len);
onintr();
exit(1);
}
return s;
}
static char* normalname P3((name, want, cut), char *name, char *want,char *cut)
{
int maxlen;
char * s, * p;
p = (char *)0;
if (!name) return p;
maxlen = strlen(name) + 1 + strlen(want) + strlen(cut);
p = strcpy(emalloc(maxlen), name);
if (s = suffix(p, cut)) strcpy(s, want);
else if (*want && !suffix(p, want)) strcat(p, want);
return p;
}
/*
* Generate a `plain' (non-encoded) name from a given name.
*/
char * plainname P1((name), char *name)
{
return normalname(name, "", SUFFIX_TOASTED );
}
/*
* Generate a `code' name (foo.Z) from a given name.
*/
char * codename P1((name), char *name)
{
return normalname( name, SUFFIX_TOASTED, "" );
}
/*
* If we're supposed to ask (fileno (stderr) is a tty, and f_force not
* set), ask the user whether to overwrite a file or not.
*/
static int ok_to_replace P1(( name ), char * name)
{
int reply, c;
if (f_force) return 1; /* YES, do replace */
if (!isatty(fileno(stderr))) return 0; /* NO, don't replace */
fprintf(stderr,
"%s already exists; do you wish to overwrite %s (y or n)? ",
name, name);
fflush(stderr);
for (c = reply = getchar(); c != '\n' && c != EOF; c = getchar()) ;
if (reply == 'y') return 1;
fprintf(stderr, "\tnot overwritten\n");
return 0;
}
void update_mode P0()
{
if (!instat.st_nlink) return; /* couldn't stat in */
#ifdef HAS_FCHMOD
if (fchmod(fileno(out), instat.st_mode & 07777)) {
perror(outname);
fprintf(stderr, "%s: could not change file mode of \"%s\"\n",
progname, outname);
}
#else
if (outname && chmod(outname, instat.st_mode & 07777)) {
perror(outname);
fprintf(stderr, "%s: could not change file mode of \"%s\"\n",
progname, outname);
}
#endif /* HAS_FCHMOD */
}
void update_own P0()
{
if (!instat.st_nlink) return; /* couldn't stat in */
#ifdef HAS_FCHOWN
(void)fchown(fileno(out), instat.st_gid, instat.st_uid);
#else
(void)chown(outname, instat.st_gid, instat.st_uid);
#endif /* HAS_FCHOWN */
}
void update_times P0()
{
if (!instat.st_nlink) return; /* couldn't stat in */
#ifdef HAS_UTIMES
if (outname) {
struct timeval tv[2];
tv[0].tv_sec = instat.st_atime;
tv[1].tv_sec = instat.st_mtime;
tv[0].tv_usec = tv[1].tv_usec = 0;
(void) utimes(outname, tv);
}
#else
#ifdef HAS_UTIME
if (outname) {
#ifdef HAS_UTIMBUF
struct utimbuf ut;
ut.actime = instat.st_atime;
ut.modtime = instat.st_mtime;
# ifdef HAS_UTIMEUSEC
ut.acusec = instat.st_ausec;
ut.modusec = instat.st_musec;
# endif HAS_UTIMEUSEC
(void) utime(outname, &ut);
#else /* UTIMBUF */
time_t ut[2];
ut[0] = instat.st_atime;
ut[1] = instat.st_mtime;
(void) utime(outname, ut);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -