File: canonical.c

package info (click to toggle)
cruft 0.9.6-0.3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 648 kB
  • ctags: 34
  • sloc: ansic: 642; sh: 179; makefile: 66; perl: 64
file content (116 lines) | stat: -rw-r--r-- 2,529 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define FALSE 0
#define TRUE 1

int double_buffers( size_t s, char** b1, char** b2, char** b3, char** b4 ) {
    char* n;

    n = realloc( *b1, s*2 );
    if ( n == NULL ) return FALSE;
    else             *b1 = n;

    n = realloc( *b2, s*2 );
    if ( n == NULL ) return FALSE;
    else             *b2 = n;

    n = realloc( *b3, s*2 );
    if ( n == NULL ) return FALSE;
    else             *b3 = n;

    n = realloc( *b4, s*2 );
    if ( n == NULL ) return FALSE;
    else             *b4 = n;

    return TRUE;
}

int main(void) {
    size_t sz_buffs = 4;

    char *buffer = malloc(sz_buffs);   /* user's input */
    char *cwd = malloc(sz_buffs);      /* expanded dirname */
    char *basename = malloc(sz_buffs); /* basename */
    char *last = malloc(sz_buffs);     /* last unexpanded dirname */

    char *pch;

    if ( buffer == NULL )   return EXIT_FAILURE;
    if ( cwd == NULL )      return EXIT_FAILURE;
    if ( basename == NULL ) return EXIT_FAILURE;
    if ( last == NULL )     return EXIT_FAILURE;
  
    strcpy( last, "" );

    for(;;) {
	if ( fgets(buffer, sz_buffs, stdin) == NULL ) break;
	for ( pch = buffer + strlen(buffer) - 1; 
	      *pch != '\n' && pch == buffer + sz_buffs - 2; 
	      pch += strlen(pch) - 1 ) 
	{
	    assert( pch[1] == '\0' );
	    if ( double_buffers( sz_buffs, &buffer, &cwd, 
				 &basename, &last ) ) 
	    {
		sz_buffs *= 2;
	    } else {
		break;
	    }
	    pch = buffer + strlen(buffer) - 1;
	    if ( fgets(pch+1, sz_buffs/2+1, stdin) == NULL ) break;
	}

	if ( *pch == '\n' ) *pch = '\0';

	if ( buffer[0] != '/' ) {
		/* don't even try working with relative paths */
		printf("%s\n", buffer );
		continue;
	}

	for ( ; *pch != '/'; pch-- ) 
	    ;

	strcpy( basename, pch + 1 );
	*(pch+1) = '\0';

	if ( strcmp( last, buffer ) != 0 ) {
	    strcpy( last, buffer );

	    if ( 0 == chdir( buffer ) ) {
		while ( NULL == getcwd( cwd, sz_buffs ) ) {	
		    if ( double_buffers( sz_buffs, &buffer, &cwd,
					 &basename, &last ) ) 
		    {
			sz_buffs *= 2;
		    } else {
			break;
		    }
		}
		pch = cwd + strlen(cwd) - 1;
		if ( *pch != '/' ) {
		    pch[1] = '/'; pch[2] = '\0';
		}
	    } else {
		strcpy( cwd, buffer );
		pch = cwd + strlen(cwd) - 1;
		if ( *pch != '/' ) {
		    pch[1] = '/'; pch[2] = '\0';
		}
	    }
	}	

	printf( "%s%s\n", cwd, basename );
    }	

    free(cwd); 
    free(buffer);
    free(basename);
    free(last);
    
    return 0;
}