krx51300.c
来自「answer of the c programming language sec」· C语言 代码 · 共 808 行 · 第 1/2 页
C
808 行
void version(void)
{
puts( "tail - output the last part of files" );
puts( "Version 1.0" );
puts( "Written by Gregory Pietsch" );
}
/* allocate memory, die on error */
void *xmalloc(size_t n)
{
void *p = malloc(n);
if (p == NULL) {
fprintf(stderr, "%s: out of memory\n", program_name);
exit(EXIT_FAILURE);
}
return p;
}
/* reallocate memory, die on error */
void *xrealloc(void *p, size_t n)
{
void *s;
if (n == 0) {
if (p != NULL)
free(p);
return NULL;
}
if (p == NULL)
return xmalloc(n);
s = realloc(p, n);
if (s == NULL) {
fprintf(stderr, "%s: out of memory\n", program_name);
exit(EXIT_FAILURE);
}
return s;
}
/* get string duplicate */
char *xstrdup(char *s)
{
char *p = xmalloc(strlen(s) + 1);
strcpy(p, s);
return p;
}
/* queue stuff - get fresh queue */
LINE_QUEUE_T *lq_create(void)
{
LINE_QUEUE_T *lq = xmalloc(sizeof LINE_QUEUE_T);
lq->first = NULL;
lq->last = NULL;
lq->num_elements = 0;
return lq;
}
/* put an item onto the queue */
void lq_enq(LINE_QUEUE_T * lq, char *s)
{
LINE_QUEUE_EL_T *lq_el = xmalloc(sizeof LINE_QUEUE_EL_T);
lq_el->s = xstrdup(s);
lq_el->next = NULL;
if (lq->first == NULL && lq->last == NULL) {
/* first element */
lq->first = lq->last = lq_el;
lq->num_elements = 1;
}
else {
/* tack onto end */
lq->last->next = lq_el;
lq->last = lq_el;
lq->num_elements++;
}
}
/* take an item off the queue */
char *lq_deq(LINE_QUEUE_T * lq)
{
char *s;
LINE_QUEUE_EL_T *lq_el;
if (lq->first == NULL)
return NULL;
lq_el = lq->first;
s = lq_el->s;
if (lq->first == lq->last)
lq->first = lq->last = NULL;
else
lq->first = lq->first->next;
free(lq_el);
lq->num_elements--;
return s;
}
/* output number lines -- this function is tough because I can only
* use fseek() to rewind a text stream (See ISO C 7.9.9.2 if you don't
* believe me).
*/
void tail_lines(FILE * f)
{
char buffer[TAIL_BUFFER_SIZE];
size_t num_read;
int last_is_nl = 0;
unsigned long num_skipped = 0;
int c;
LINE_QUEUE_T *lq = NULL;
char *s;
size_t s_size = 0;
size_t s_allocked = 0;
char *p;
if (flag_skip) {
/* skip a bunch of lines, output everything else */
while ((c = getc(f)) != EOF && num_skipped < number) {
if (c == '\n')
num_skipped++;
}
while ((num_read = fread(buffer, 1, TAIL_BUFFER_SIZE, f)) != 0)
{
fwrite(buffer, 1, num_read, stdout);
last_is_nl = (buffer[num_read - 1] == '\n');
}
if (!last_is_nl)
fputc('\n', stdout);
}
else {
lq = lq_create();
s = xmalloc(TAIL_STRING_BUFFER_SIZE);
s_allocked = TAIL_STRING_BUFFER_SIZE;
while ((c = getc(f)) != EOF) {
/* add to s, if not at eof or end of line */
if (c != '\n') {
if (s_size == s_allocked - 1) {
s_allocked += TAIL_STRING_BUFFER_SIZE;
s = xrealloc(s, s_allocked);
}
s[s_size++] = c;
}
else {
/* enqueue s, possibly dequeueing if we don't need a
line */
s[s_size] = '\0';
lq_enq(lq, s);
if (lq->num_elements > number)
free(lq_deq(lq));
s_size = 0;
}
}
while (lq->num_elements != 0) {
/* print out strings */
p = lq_deq(lq);
puts(p);
free(p);
}
free(s);
free(lq);
}
}
/* output number characters, or skip over number characters */
void tail_chars(FILE * f)
{
char buffer[TAIL_BUFFER_SIZE];
size_t num_read;
int last_is_nl = 0;
long lnum = number;
if (flag_skip)
fseek(f, lnum, SEEK_SET);
else
fseek(f, -lnum, SEEK_END);
while ((num_read = fread(buffer, 1, TAIL_BUFFER_SIZE, f)) != 0) {
fwrite(buffer, 1, num_read, stdout);
last_is_nl = (buffer[num_read - 1] == '\n');
}
if (!last_is_nl)
fputc('\n', stdout);
}
void parse_args(int argc, char **argv)
{
int opt;
char *p;
int flag_found_number = 0;
int verbosity_changed = 0;
do {
switch ((opt = getopt_long(argc, argv, shortopts, longopts, NULL))) {
case 'c': /* print bytes */
if (flag_found_number) {
fprintf(stderr, "%s: invalid arguments\s", program_name);
abort();
}
flag_bytes = 1;
p = optarg;
if (*p == '+') {
flag_skip = 1;
p++;
}
for (number = 0;
isdigit(*p);
number = number * 10 + (*p++ - '0'));
switch (*p) {
case 'b': /* 512-byte blocks */
number *= 512;
break;
case 'k': /* kilobyte blocks */
number *= 1024;
break;
case 'm': /* megabyte blocks */
number *= 1048576;
break;
default:
break;
}
flag_found_number = 1;
break;
case 'l':
case 'n': /* lines */
if (flag_found_number) {
fprintf(stderr, "%s: invalid arguments\s", program_name);
abort();
}
flag_bytes = 0;
p = optarg;
if (*p == '+') {
flag_skip = 1;
p++;
}
number = strtoul(p, NULL, 10);
flag_found_number = 1;
break;
case 'q': /* quiet */
if (verbosity_changed) {
fprintf(stderr, "%s: invalid arguments\s", program_name);
abort();
}
verbosity_changed = 1;
flag_verbosity = NEVER;
break;
case 'v': /* verbose */
if (verbosity_changed) {
fprintf(stderr, "%s: invalid arguments\s", program_name);
abort();
}
verbosity_changed = 1;
flag_verbosity = ALWAYS;
break;
case '?': /* invalid option */
fprintf(stderr, "For help, type:\n\t%s --help\n", program_name);
exit(EXIT_FAILURE);
case 1:
case 0:
if (show_help || show_version) {
if (show_help)
help();
if (show_version)
version();
exit(EXIT_SUCCESS);
}
break;
default:
break;
}
} while (opt != EOF);
if (flag_found_number == 0 || number == 0) {
/* didn't find anything, so set default */
flag_bytes = 0;
number = 10;
}
}
int main(int argc, char **argv)
{
int i;
int j;
unsigned long ul;
char **new_argv = xmalloc((argc + 1) * (sizeof(char *)));
char *allocked_argvs = xmalloc(argc + 1);
char *p;
char *s;
char *t;
FILE *f;
int flag_plus = 0;
memset(allocked_argvs, 0, argc + 1);
new_argv[0] = program_name = argv[0];
/* deal with silly old-format arguments */
for (i = 1, j = 1; i < argc; i++) {
p = argv[i];
flag_plus = 0;
/* handle options first */
if (*p == '-' || *p == '+') {
if (isdigit(p[1]) || p[1] == '+' || *p == '+') {
/* rearrange p */
s = xmalloc(strlen(p) + 3);
t = s;
*t++ = '-';
if (*p == '-')
p++;
ul = 0;
if (*p == '+') {
flag_plus = 1;
p++;
}
while (isdigit(*p)) {
ul = ul * 10 + (*p - '0');
p++;
}
if (strchr(p, 'q') != NULL)
*t++ = 'q';
if (strchr(p, 'v') != NULL)
*t++ = 'v';
if (strpbrk(p, "cbkm") != NULL)
*t++ = 'c';
if (strchr(p, 'l') != NULL)
*t++ = 'l';
if (strchr(p, 'n') != NULL || t[-1] == '-')
*t++ = 'n';
if (flag_plus)
*t++ = '+';
sprintf(t, "%lu", ul);
t += strlen(t);
if (strchr(p, 'b') != NULL)
*t++ = 'b';
if (strchr(p, 'k') != NULL)
*t++ = 'k';
if (strchr(p, 'm') != NULL)
*t++ = 'm';
*t = '\0';
new_argv[j] = s;
allocked_argvs[j++] = 1;
}
else
new_argv[j++] = argv[i];
}
}
for (i = 1; i < argc; i++) {
/* handle file names */
p = argv[i];
if (*p != '-')
new_argv[j++] = p;
}
new_argv[argc] = NULL;
parse_args(argc, new_argv);
if (optind == argc
|| (optind == argc - 1 && strcmp(argv[optind], "-") == 0)) {
/* no more argv-elements, tail stdin */
if (flag_verbosity == ALWAYS)
puts("==> standard input <==");
flag_bytes ? tail_chars(stdin) : tail_lines(stdin);
}
else if (optind == argc - 1) {
/* one file */
f = fopen(new_argv[optind], flag_bytes ? "rb" : "r");
if (f == NULL) {
fprintf(stderr, "%s: Can't open file %s\n",
program_name, new_argv[optind]);
abort();
}
if (flag_verbosity == ALWAYS)
printf("==> %s <==\n", new_argv[optind]);
flag_bytes ? tail_chars(f) : tail_lines(f);
fclose(f);
}
else {
/* multiple files */
for (i = optind; i < argc; i++) {
if (strcmp(new_argv[i], "-") == 0) {
f = stdin;
if (flag_verbosity != NEVER)
puts("==> standard input <==");
}
else {
f = fopen(new_argv[i], flag_bytes ? "rb" : "r");
if (f == NULL) {
fprintf(stderr, "%s: can't open %s\n",
argv[0], argv[i]);
abort();
}
if (flag_verbosity != NEVER)
printf("==> %s <==\n", new_argv[i]);
}
flag_bytes ? tail_chars(f) : tail_lines(f);
if (f != stdin)
fclose(f);
}
}
/* free all we can */
for (i = 1; i <= argc; i++)
if (allocked_argvs[i])
free(new_argv[i]);
free(allocked_argvs);
return EXIT_SUCCESS;
}
/* END OF FILE tail.c */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?