+ if (stat("/", &rootStat) != 0) {
+ error_msg("could not stat '/'\n");
+ return( FALSE);
+ }
+
+ dir = opendir("/dev");
+ if (!dir) {
+ error_msg("could not open '/dev'\n");
+ return( FALSE);
+ }
+
+ while((entry = readdir(dir)) != NULL) {
+
+ /* Must skip ".." since that is "/", and so we
+ * would get a false positive on ".." */
+ if (strcmp(entry->d_name, "..") == 0)
+ continue;
+
+ snprintf( fileName, strlen(name)+1, "/dev/%s", entry->d_name);
+
+ if (stat(fileName, &statBuf) != 0)
+ continue;
+ /* Some char devices have the same dev_t as block
+ * devices, so make sure this is a block device */
+ if (! S_ISBLK(statBuf.st_mode))
+ continue;
+ if (statBuf.st_rdev == rootStat.st_rdev) {
+ strcpy(name, fileName);
+ return ( TRUE);
+ }
+ }
+
+ return( FALSE);
+}
+#endif
+
+
+/* get_line_from_file() - This function reads an entire line from a text file
+ * up to a newline. It returns a malloc'ed char * which must be stored and
+ * free'ed by the caller. */
+extern char *get_line_from_file(FILE *file)
+{
+ static const int GROWBY = 80; /* how large we will grow strings by */
+
+ int ch;
+ int idx = 0;
+ char *linebuf = NULL;
+ int linebufsz = 0;
+
+ while (1) {
+ ch = fgetc(file);
+ if (ch == EOF)
+ break;
+ /* grow the line buffer as necessary */
+ while (idx > linebufsz-2)
+ linebuf = xrealloc(linebuf, linebufsz += GROWBY);
+ linebuf[idx++] = (char)ch;
+ if ((char)ch == '\n')
+ break;
+ }
+
+ if (idx == 0)
+ return NULL;
+
+ linebuf[idx] = 0;
+ return linebuf;
+}
+
+#if defined BB_CAT
+extern void print_file(FILE *file)
+{
+ int c;
+
+ while ((c = getc(file)) != EOF)
+ putc(c, stdout);
+ fclose(file);
+ fflush(stdout);
+}
+
+extern int print_file_by_name(char *filename)
+{
+ FILE *file;
+ if ((file = wfopen(filename, "r")) == NULL)
+ return FALSE;
+ print_file(file);
+ return TRUE;
+}
+#endif /* BB_CAT */
+
+#if defined BB_ECHO || defined BB_SH || defined BB_TR
+char process_escape_sequence(char **ptr)
+{
+ char c;
+
+ switch (c = *(*ptr)++) {
+ case 'a':
+ c = '\a';
+ break;
+ case 'b':
+ c = '\b';
+ break;
+ case 'f':
+ c = '\f';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case 'v':
+ c = '\v';
+ break;
+ case '\\':
+ c = '\\';
+ break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ c -= '0';
+ if ('0' <= **ptr && **ptr <= '7') {
+ c = c * 8 + (*(*ptr)++ - '0');
+ if ('0' <= **ptr && **ptr <= '7')
+ c = c * 8 + (*(*ptr)++ - '0');
+ }
+ break;
+ default:
+ (*ptr)--;
+ c = '\\';
+ break;
+ }
+ return c;
+}
+#endif
+
+#if defined BB_BASENAME || defined BB_LN || defined BB_SH || defined BB_INIT || defined BB_FEATURE_USE_PROCFS
+char *get_last_path_component(char *path)
+{
+ char *s=path+strlen(path)-1;
+
+ /* strip trailing slashes */
+ while (s && *s == '/') {
+ *s-- = '\0';
+ }
+
+ /* find last component */
+ s = strrchr(path, '/');
+ if (s==NULL) return path;
+ else return s+1;
+}
+#endif
+
+#if defined BB_GREP || defined BB_SED
+void xregcomp(regex_t *preg, const char *regex, int cflags)
+{
+ int ret;
+ if ((ret = regcomp(preg, regex, cflags)) != 0) {
+ int errmsgsz = regerror(ret, preg, NULL, 0);
+ char *errmsg = xmalloc(errmsgsz);
+ regerror(ret, preg, errmsg, errmsgsz);
+ error_msg_and_die("xregcomp: %s\n", errmsg);
+ }
+}
+#endif
+
+#if defined BB_CAT || defined BB_HEAD || defined BB_WC
+FILE *wfopen(const char *path, const char *mode)
+{
+ FILE *fp;
+ if ((fp = fopen(path, mode)) == NULL) {
+ error_msg("%s: %s\n", path, strerror(errno));
+ errno = 0;
+ }
+ return fp;