]> err.no Git - sash/blob - cmd_file.c
Stop stripping during build. Also thanks to Helmut Grohne. Closes: #852771
[sash] / cmd_file.c
1 /*
2  * Copyright (c) 2014 by David I. Bell
3  * Permission is granted to use, distribute, or modify this source,
4  * provided that this copyright notice remains intact.
5  *
6  * The "file" built-in command.
7  */
8
9 #include <ctype.h>
10 #include <errno.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13
14 #include "sash.h"
15
16
17 static const char *     checkFile(const char * name);
18
19
20 int
21 do_file(int argc, const char ** argv)
22 {
23         const char *    name;
24         const char *    info;
25
26         argc--;
27         argv++;
28
29         while (argc-- > 0)
30         {
31                 name = *argv++;
32
33                 info = checkFile(name);
34
35                 if (info == NULL)
36                         info = "No information available";
37
38                 printf("%s: %s\n", name, info);
39         }
40
41         return 0;
42 }
43
44
45 /*
46  * Examine the specified file and return a static string which
47  * describes the file type.  Returns NULL on a failure.
48  */
49 static const char *
50 checkFile(const char * name)
51 {
52         int             mode;
53         int             fd;
54         int             cc;
55         int             i;
56         int             ch;
57         int             badCount;
58         char *          cp;
59         struct  stat    statBuf;
60         char            data[8192];
61         static  char    info[1024];
62
63         cp = info;
64         *cp = '\0';
65
66         if (lstat(name, &statBuf) < 0)
67         {
68                 if (errno == ENOENT)
69                         return "non-existent";
70
71                 sprintf(cp, "stat failed: %s", strerror(errno));
72
73                 return info;
74         }
75
76         /*
77          * Check the file type.
78          */
79         mode = statBuf.st_mode;
80
81         if (S_ISDIR(mode))
82                 return "directory";
83
84         if (S_ISCHR(mode))
85                 return "character device";
86
87         if (S_ISBLK(mode))
88                 return "block device";
89
90         if (S_ISFIFO(mode))
91                 return "named pipe";
92
93 #ifdef  S_ISLNK
94         if (S_ISLNK(mode))
95                 return "symbolic link";
96 #endif
97
98 #ifdef  S_ISSOCK
99         if (S_ISSOCK(mode))
100                 return "socket";
101 #endif
102
103         /*
104          * If the file is not a regular file mention that.
105          */
106         if (!S_ISREG(mode))
107         {
108                 sprintf(cp, "unknown mode 0x%x, \n", mode);
109
110                 cp += strlen(cp);
111         }
112
113         /*
114          * Check for an executable file.
115          */
116         if ((mode & (S_IEXEC | S_IXGRP | S_IXOTH)) != 0)
117         {
118                 strcpy(cp, "executable, ");
119
120                 cp += strlen(cp);
121         }
122
123         /*
124          * The file is a normal file.
125          * Open it if we can and read in the first block.
126          */
127         fd = open(name, O_RDONLY);
128
129         if (fd < 0)
130         {
131                 sprintf(cp, "unreadable: %s", strerror(errno));
132
133                 return info;
134         }
135
136         cc = read(fd, data, sizeof(data));
137
138         if (cc < 0)
139         {
140                 sprintf(cp, "read error: %s", strerror(errno));
141
142                 (void) close(fd);
143
144                 return info;
145         }
146
147         (void) close(fd);
148
149         /*
150          * Check for an empty file.
151          */
152         if (cc == 0)
153         {
154                 strcpy(cp, "empty file");
155
156                 return info;
157         }
158
159         /*
160          * Check for a script file.
161          */
162         if ((cc > 2) && (data[0] == '#') && (data[1] == '!'))
163         {
164                 char *  begin;
165                 char *  end;
166
167                 data[sizeof(data) - 1] = '\0';
168
169                 begin = &data[2];
170
171                 while (*begin == ' ')
172                         begin++;
173
174                 end = begin;
175
176                 while (*end && (*end != ' ') && (*end != '\n'))
177                         end++;
178
179                 *end = '\0';
180
181                 sprintf(cp, "script for \"%s\"", begin);
182
183                 return info;
184         }
185
186         /*
187          * Check for special binary data types.
188          */
189         if ((data[0] == '\037') && (data[1] == '\235'))
190                 return "compressed file";
191
192         if ((data[0] == '\037') && (data[1] == '\213'))
193                 return "GZIP file";
194
195         if ((data[0] == '\177') && (memcmp(&data[1], "ELF", 3) == 0))
196         {
197                 strcpy(cp, "ELF program");
198
199                 return info;
200         }
201
202         /*
203          * Check for binary data.
204          */
205         badCount = 0;
206
207         for (i = 0; i < cc; i++)
208         {
209                 ch = data[i];
210
211                 if ((ch == '\n') || (ch == '\t'))
212                         continue;
213
214                 if (isspace(ch) || isprint(ch))
215                         continue;
216
217                 badCount++;
218         }
219
220         if (badCount != 0)
221         {
222                 strcpy(cp, "binary");
223
224                 return info;
225         }
226
227         /*
228          * It is just a text file.
229          */
230         strcpy(cp, "text file");
231
232         return info;
233 }
234
235 /* END CODE */