diff -Naur old/memstat-0.9/memstat.c memstat-0.9/memstat.c
--- old/memstat-0.9/memstat.c	2012-01-20 14:18:08.444775271 +0100
+++ memstat-0.9/memstat.c	2012-01-25 13:54:55.375731001 +0100
@@ -58,11 +58,34 @@
     maptab_size = maptab_size * 2 + 100;
 }
 
+static char * get_line(FILE *f)
+{
+    char * buf  = NULL;
+    size_t buf_size = 0;
+    size_t last = 0;
+
+    while (!feof(f)) {
+	buf_size = buf_size ? buf_size * 2 : BUFSIZ;
+	buf = realloc(buf, buf_size);
+	if (fgets(buf + last, buf_size - last, f) == NULL) {
+	    free(buf);
+	    return NULL;
+	}
+	last = strlen(buf);
+	if (buf[last-1] == '\n')
+	    return buf;
+    }
+
+    return buf;
+}
+
 static void read_proc(void)
 {
     unsigned int nread, pid;
     unsigned long inode, lo, hi, offs;
-    char *p, major[8], minor[8], buff[PATH_MAX + 300], *path, perm[4];
+    char *p, major[8], minor[8], *path, perm[4];
+    char *buff = NULL;
+    int buff_size = 0;
     DIR *d;
     struct dirent *ent;
     FILE *f;
@@ -85,11 +108,21 @@
 	}
 	if (pid == 0 || (only_pid != 0 && pid != only_pid))
 	    continue;
-	sprintf(buff, "/proc/%d/maps", pid);
-	f = fopen(buff, "r");
+
+#define FORMAT "/proc/%d/maps"
+#define BUFF_SIZE (sizeof(FORMAT) + (sizeof(int) * 3) + 1)
+	char filename[BUFF_SIZE];
+	sprintf(filename, FORMAT, pid);
+#undef FORMAT
+#undef BUFF_SIZE
+
+	f = fopen(filename, "r");
 	if (f == NULL)
 	    continue;
-	while (fgets(buff, sizeof(buff), f)) {
+	while (!feof(f)) {
+	    buff = get_line(f);
+	    if (buff == NULL) 
+		break;
 	    p = strchr(buff, '-');
 	    if (p)
 		*p = ' ';
@@ -97,9 +130,12 @@
 	    if (p)
 		*p = ' ';
 	    path = NULL;
-	    if ((strlen(buff) == 10) && (strcmp(buff, " (deleted)") == 0))
+	    if ((strlen(buff) == 10) && (strcmp(buff, " (deleted)") == 0)) {
+		free(buff);
 		continue;
+	    }
 	    nread = sscanf(buff, "%lx %lx %4s %lx %s %s %lu %as", &lo, &hi, perm, &offs, major, minor, &inode, &path);
+	    free(buff);
 	    if (nread < 7) {
 		fprintf(stderr, "I don't recognize format of /proc/%d/maps. (nread=%d)\n", pid, nread);
 		exit(1);
@@ -128,6 +164,16 @@
 			m->valid = 0;
 		}
 	    } else {
+		buff_size = 4; /* size of the format string without "%x" expressions */
+		buff_size += strlen(major);
+		buff_size += strlen(minor);
+		buff_size += sizeof(int) * 3 + 1; // inode
+		buff_size += 1; // '\0'
+		buff = (char *)malloc(buff_size);
+		if (buff == NULL) {
+		    perror("Cannot allocate memory!");
+		    exit(1);
+		}
 		sprintf(buff, "[%s:%s]:%lu", major, minor, inode);
 		m->path = strdup(buff);
 		needinode = 1;
@@ -251,17 +297,36 @@
     grand = sharedgrand = 0;
     qsort(maptab_data, maptab_fill, sizeof(struct mapping), (qcmp) sort_by_pid);
     for (offs = 0; offs < maptab_fill; offs = scan) {
-	char linkname[PATH_MAX], filename[PATH_MAX];
+	char *linkname = NULL;
+	struct stat sb;
 	ssize_t len;
 	int deleted = 0;
 
 	pid = maptab_data[offs].pid;
-	sprintf(filename, "/proc/%d/exe", pid);
-	if ((len = readlink(filename, linkname, PATH_MAX)) == -1) {
+
+#define FORMAT "/proc/%d/exe"
+#define BUFF_SIZE (sizeof(FORMAT) + (sizeof(int) * 3) + 1)
+	char filename[BUFF_SIZE];
+	sprintf(filename, FORMAT, pid);
+#undef FORMAT
+#undef BUFF_SIZE
+
+	if (lstat(filename, &sb) == -1) {
+	    perror("lstat");
+	    exit(EXIT_FAILURE);
+	}
+	linkname = malloc(sb.st_size + 1);
+	if (linkname == NULL) {
+	    fprintf(stderr, "insufficient memory\n");
+	    exit(EXIT_FAILURE);
+	}
+	len = readlink(filename, linkname, sb.st_size + 1);
+	
+	if (len < 0 || len > sb.st_size) {
 	    fprintf(stderr, "Cannot read link information for %s\n", filename);
 	    deleted = 1;
 	}
-	linkname[len] = '\0';
+	linkname[sb.st_size] = '\0';
 	total = 0;
 	for (scan = offs; scan < maptab_fill; scan++) {
 	    m = maptab_data + scan;
@@ -277,6 +342,7 @@
 		printline(buffer);
 		grand += total;
 	}
+	free(linkname);
     }
 
     qsort(maptab_data, maptab_fill, sizeof(struct mapping), (qcmp) sort_by_inode);
