Commit | Line | Data |
---|---|---|
461723e7 KM |
1 | /*- |
2 | * Copyright (c) 1980, 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
76797561 DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
461723e7 KM |
9 | char copyright[] = |
10 | "@(#) Copyright (c) 1980, 1991 The Regents of the University of California.\n\ | |
11 | All rights reserved.\n"; | |
12 | #endif /* not lint */ | |
13 | ||
14 | #ifndef lint | |
0289322c | 15 | static char sccsid[] = "@(#)main.c 5.25 (Berkeley) %G%"; |
5c3d7d9e | 16 | #endif /* not lint */ |
76797561 | 17 | |
cdce5e6c | 18 | #include <sys/param.h> |
0289322c KM |
19 | #include <sys/time.h> |
20 | #ifdef sunos | |
21 | #include <sys/vnode.h> | |
22 | ||
23 | #include <ufs/inode.h> | |
25c5efb9 | 24 | #include <ufs/fs.h> |
cdce5e6c | 25 | #else |
3d66b39b | 26 | #include <ufs/ffs/fs.h> |
25c5efb9 | 27 | #include <ufs/ufs/dinode.h> |
13298603 | 28 | #endif |
0289322c KM |
29 | |
30 | #include <protocols/dumprestore.h> | |
31 | ||
32 | #include <errno.h> | |
5c3d7d9e | 33 | #include <fcntl.h> |
13298603 | 34 | #include <fstab.h> |
0289322c | 35 | #include <signal.h> |
13298603 KB |
36 | #include <stdio.h> |
37 | #ifdef __STDC__ | |
13298603 KB |
38 | #include <stdlib.h> |
39 | #include <string.h> | |
0289322c KM |
40 | #include <unistd.h> |
41 | #else | |
42 | extern char *rindex(); | |
43 | extern char *calloc(); | |
13298603 | 44 | #endif |
0289322c | 45 | |
13298603 | 46 | #include "dump.h" |
2e433f8d | 47 | #include "pathnames.h" |
0393c389 BJ |
48 | |
49 | int notify = 0; /* notify operator flag */ | |
50 | int blockswritten = 0; /* number of blocks written on current tape */ | |
51 | int tapeno = 0; /* current tape number */ | |
1ddebffe SL |
52 | int density = 0; /* density in bytes/0.1" */ |
53 | int ntrec = NTREC; /* # tape blocks in each tape record */ | |
54 | int cartridge = 0; /* Assume non-cartridge tape */ | |
ff96014a | 55 | long dev_bsize = 1; /* recalculated below */ |
70c0f96a | 56 | long blocksperfile; /* output blocks per file */ |
ae744076 | 57 | char *host = NULL; /* remote host (if any) */ |
0393c389 | 58 | |
0289322c | 59 | int |
0393c389 | 60 | main(argc, argv) |
6175ef8c | 61 | int argc; |
13298603 | 62 | char **argv; |
0393c389 | 63 | { |
6175ef8c | 64 | register ino_t ino; |
0a008f8c | 65 | register int dirty; |
6175ef8c KM |
66 | register struct dinode *dp; |
67 | register struct fstab *dt; | |
68 | register char *map; | |
69 | register char *cp; | |
25c5efb9 | 70 | int i, anydirskipped, bflag = 0, Tflag = 0; |
6175ef8c KM |
71 | float fetapes; |
72 | ino_t maxino; | |
0393c389 | 73 | |
ae744076 | 74 | spcl.c_date = 0; |
25c5efb9 | 75 | (void) time((time_t *) &(spcl.c_date)); |
0393c389 | 76 | |
1ddebffe | 77 | tsize = 0; /* Default later, based on 'c' option for cart tapes */ |
7abf8d65 | 78 | tape = _PATH_DEFTAPE; |
6175ef8c | 79 | dumpdates = _PATH_DUMPDATES; |
2e433f8d | 80 | temp = _PATH_DTMP; |
5c3d7d9e CT |
81 | if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0) |
82 | quit("TP_BSIZE must be a multiple of DEV_BSIZE\n"); | |
6175ef8c KM |
83 | level = '0'; |
84 | argv++; | |
85 | argc -= 2; | |
86 | for (cp = *argv++; *cp; cp++) { | |
87 | switch (*cp) { | |
88 | case '-': | |
89 | continue; | |
90 | ||
91 | case 'w': | |
92 | lastdump('w'); /* tell us only what has to be done */ | |
0289322c | 93 | exit(0); |
6175ef8c KM |
94 | |
95 | case 'W': /* what to do */ | |
96 | lastdump('W'); /* tell us state of what is done */ | |
0289322c | 97 | exit(0); /* do nothing else */ |
6175ef8c KM |
98 | |
99 | case 'f': /* output file */ | |
100 | if (argc < 1) | |
101 | break; | |
102 | tape = *argv++; | |
0393c389 | 103 | argc--; |
6175ef8c | 104 | continue; |
0393c389 | 105 | |
6175ef8c KM |
106 | case 'd': /* density, in bits per inch */ |
107 | if (argc < 1) | |
108 | break; | |
0393c389 | 109 | density = atoi(*argv) / 10; |
6175ef8c | 110 | if (density < 1) { |
25c5efb9 KM |
111 | (void) fprintf(stderr, "bad density \"%s\"\n", |
112 | *argv); | |
6175ef8c KM |
113 | Exit(X_ABORT); |
114 | } | |
115 | argc--; | |
116 | argv++; | |
a1f8d10b KM |
117 | if (density >= 625 && !bflag) |
118 | ntrec = HIGHDENSITYTREC; | |
6175ef8c | 119 | continue; |
0393c389 | 120 | |
6175ef8c KM |
121 | case 's': /* tape size, feet */ |
122 | if (argc < 1) | |
123 | break; | |
0393c389 | 124 | tsize = atol(*argv); |
6175ef8c | 125 | if (tsize < 1) { |
25c5efb9 KM |
126 | (void) fprintf(stderr, "bad size \"%s\"\n", |
127 | *argv); | |
6175ef8c KM |
128 | Exit(X_ABORT); |
129 | } | |
1ddebffe | 130 | argc--; |
6175ef8c KM |
131 | argv++; |
132 | tsize *= 12 * 10; | |
133 | continue; | |
134 | ||
25c5efb9 KM |
135 | case 'T': /* time of last dump */ |
136 | if (argc < 1) | |
137 | break; | |
138 | spcl.c_ddate = unctime(*argv); | |
139 | if (spcl.c_ddate < 0) { | |
140 | (void) fprintf(stderr, "bad time \"%s\"\n", | |
141 | *argv); | |
142 | Exit(X_ABORT); | |
143 | } | |
144 | Tflag++; | |
145 | lastlevel = '?'; | |
146 | argc--; | |
147 | argv++; | |
148 | continue; | |
149 | ||
6175ef8c KM |
150 | case 'b': /* blocks per tape write */ |
151 | if (argc < 1) | |
152 | break; | |
a1f8d10b | 153 | bflag++; |
0a008f8c | 154 | ntrec = atoi(*argv); |
6175ef8c | 155 | if (ntrec < 1) { |
25c5efb9 | 156 | (void) fprintf(stderr, "%s \"%s\"\n", |
6175ef8c | 157 | "bad number of blocks per write ", *argv); |
70c0f96a KM |
158 | Exit(X_ABORT); |
159 | } | |
70c0f96a | 160 | argc--; |
6175ef8c KM |
161 | argv++; |
162 | continue; | |
163 | ||
164 | case 'B': /* blocks per output file */ | |
165 | if (argc < 1) | |
166 | break; | |
70c0f96a | 167 | blocksperfile = atol(*argv); |
6175ef8c | 168 | if (blocksperfile < 1) { |
25c5efb9 | 169 | (void) fprintf(stderr, "%s \"%s\"\n", |
6175ef8c KM |
170 | "bad number of blocks per file ", *argv); |
171 | Exit(X_ABORT); | |
172 | } | |
173 | argc--; | |
174 | argv++; | |
175 | continue; | |
176 | ||
177 | case 'c': /* Tape is cart. not 9-track */ | |
178 | cartridge++; | |
179 | continue; | |
180 | ||
181 | case '0': /* dump level */ | |
182 | case '1': | |
183 | case '2': | |
184 | case '3': | |
185 | case '4': | |
186 | case '5': | |
187 | case '6': | |
188 | case '7': | |
189 | case '8': | |
190 | case '9': | |
191 | level = *cp; | |
192 | continue; | |
193 | ||
194 | case 'u': /* update /etc/dumpdates */ | |
195 | uflag++; | |
196 | continue; | |
197 | ||
198 | case 'n': /* notify operators */ | |
199 | notify++; | |
200 | continue; | |
201 | ||
202 | default: | |
25c5efb9 | 203 | (void) fprintf(stderr, "bad key '%c'\n", *cp); |
6175ef8c | 204 | Exit(X_ABORT); |
1ddebffe | 205 | } |
25c5efb9 | 206 | (void) fprintf(stderr, "missing argument to '%c'\n", *cp); |
0393c389 BJ |
207 | Exit(X_ABORT); |
208 | } | |
6175ef8c | 209 | if (argc < 1) { |
25c5efb9 | 210 | (void) fprintf(stderr, "Must specify disk or filesystem\n"); |
6175ef8c KM |
211 | Exit(X_ABORT); |
212 | } else { | |
213 | disk = *argv++; | |
0393c389 | 214 | argc--; |
6175ef8c KM |
215 | } |
216 | if (argc >= 1) { | |
25c5efb9 | 217 | (void) fprintf(stderr, "Unknown arguments to dump:"); |
6175ef8c | 218 | while (argc--) |
25c5efb9 KM |
219 | (void) fprintf(stderr, " %s", *argv++); |
220 | (void) fprintf(stderr, "\n"); | |
221 | Exit(X_ABORT); | |
222 | } | |
223 | if (Tflag && uflag) { | |
224 | (void) fprintf(stderr, | |
225 | "You cannot use the T and u flags together.\n"); | |
6175ef8c | 226 | Exit(X_ABORT); |
0393c389 | 227 | } |
a47b7e40 KM |
228 | if (strcmp(tape, "-") == 0) { |
229 | pipeout++; | |
230 | tape = "standard output"; | |
231 | } | |
1ddebffe | 232 | |
70c0f96a KM |
233 | if (blocksperfile) |
234 | blocksperfile = blocksperfile / ntrec * ntrec; /* round down */ | |
235 | else { | |
236 | /* | |
237 | * Determine how to default tape size and density | |
238 | * | |
239 | * density tape size | |
240 | * 9-track 1600 bpi (160 bytes/.1") 2300 ft. | |
241 | * 9-track 6250 bpi (625 bytes/.1") 2300 ft. | |
242 | * cartridge 8000 bpi (100 bytes/.1") 1700 ft. | |
243 | * (450*4 - slop) | |
244 | */ | |
245 | if (density == 0) | |
246 | density = cartridge ? 100 : 160; | |
247 | if (tsize == 0) | |
248 | tsize = cartridge ? 1700L*120L : 2300L*120L; | |
249 | } | |
1ddebffe | 250 | |
ae744076 KM |
251 | if (index(tape, ':')) { |
252 | host = tape; | |
253 | tape = index(host, ':'); | |
254 | *tape++ = 0; | |
c29a1d14 | 255 | #ifdef RDUMP |
ae744076 | 256 | if (rmthost(host) == 0) |
0289322c | 257 | exit(X_ABORT); |
ae744076 | 258 | #else |
25c5efb9 | 259 | (void) fprintf(stderr, "remote dump not enabled\n"); |
0289322c | 260 | exit(X_ABORT); |
ae744076 | 261 | #endif |
c29a1d14 | 262 | } |
25c5efb9 | 263 | (void) setuid(getuid()); /* rmthost() is the only reason to be setuid */ |
ae744076 | 264 | |
70c0f96a | 265 | if (signal(SIGHUP, SIG_IGN) != SIG_IGN) |
71b2d5ef | 266 | signal(SIGHUP, sig); |
70c0f96a | 267 | if (signal(SIGTRAP, SIG_IGN) != SIG_IGN) |
71b2d5ef | 268 | signal(SIGTRAP, sig); |
70c0f96a | 269 | if (signal(SIGFPE, SIG_IGN) != SIG_IGN) |
71b2d5ef | 270 | signal(SIGFPE, sig); |
70c0f96a | 271 | if (signal(SIGBUS, SIG_IGN) != SIG_IGN) |
71b2d5ef | 272 | signal(SIGBUS, sig); |
70c0f96a | 273 | if (signal(SIGSEGV, SIG_IGN) != SIG_IGN) |
71b2d5ef | 274 | signal(SIGSEGV, sig); |
70c0f96a | 275 | if (signal(SIGTERM, SIG_IGN) != SIG_IGN) |
71b2d5ef | 276 | signal(SIGTERM, sig); |
0393c389 BJ |
277 | if (signal(SIGINT, interrupt) == SIG_IGN) |
278 | signal(SIGINT, SIG_IGN); | |
279 | ||
280 | set_operators(); /* /etc/group snarfed */ | |
281 | getfstab(); /* /etc/fstab snarfed */ | |
282 | /* | |
283 | * disk can be either the full special file name, | |
284 | * the suffix of the special file name, | |
285 | * the special name missing the leading '/', | |
286 | * the file system name with or without the leading '/'. | |
287 | */ | |
288 | dt = fstabsearch(disk); | |
b28b78d4 | 289 | if (dt != 0) { |
0393c389 | 290 | disk = rawname(dt->fs_spec); |
25c5efb9 KM |
291 | (void) strncpy(spcl.c_dev, dt->fs_spec, NAMELEN); |
292 | (void) strncpy(spcl.c_filesys, dt->fs_file, NAMELEN); | |
b28b78d4 | 293 | } else { |
25c5efb9 KM |
294 | (void) strncpy(spcl.c_dev, disk, NAMELEN); |
295 | (void) strncpy(spcl.c_filesys, "an unlisted file system", | |
296 | NAMELEN); | |
b28b78d4 | 297 | } |
25c5efb9 KM |
298 | (void) strcpy(spcl.c_label, "none"); |
299 | (void) gethostname(spcl.c_host, NAMELEN); | |
6175ef8c | 300 | spcl.c_level = level - '0'; |
b28b78d4 | 301 | spcl.c_type = TS_TAPE; |
25c5efb9 KM |
302 | if (!Tflag) |
303 | getdumptime(); /* /etc/dumpdates snarfed */ | |
0393c389 | 304 | |
6175ef8c KM |
305 | msg("Date of this level %c dump: %s", level, |
306 | spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); | |
307 | msg("Date of last level %c dump: %s", lastlevel, | |
308 | spcl.c_ddate == 0 ? "the epoch\n" : ctime(&spcl.c_ddate)); | |
0393c389 BJ |
309 | msg("Dumping %s ", disk); |
310 | if (dt != 0) | |
311 | msgtail("(%s) ", dt->fs_file); | |
ae744076 KM |
312 | if (host) |
313 | msgtail("to %s on host %s\n", tape, host); | |
314 | else | |
315 | msgtail("to %s\n", tape); | |
0393c389 | 316 | |
6175ef8c | 317 | if ((diskfd = open(disk, O_RDONLY)) < 0) { |
0393c389 BJ |
318 | msg("Cannot open %s\n", disk); |
319 | Exit(X_ABORT); | |
320 | } | |
b6407c9d | 321 | sync(); |
25c5efb9 KM |
322 | sblock = (struct fs *)sblock_buf; |
323 | bread(SBOFF, (char *) sblock, SBSIZE); | |
5c3d7d9e CT |
324 | if (sblock->fs_magic != FS_MAGIC) |
325 | quit("bad sblock magic number\n"); | |
ff96014a | 326 | dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1); |
5c3d7d9e CT |
327 | dev_bshift = ffs(dev_bsize) - 1; |
328 | if (dev_bsize != (1 << dev_bshift)) | |
329 | quit("dev_bsize (%d) is not a power of 2", dev_bsize); | |
330 | tp_bshift = ffs(TP_BSIZE) - 1; | |
331 | if (TP_BSIZE != (1 << tp_bshift)) | |
332 | quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE); | |
0289322c | 333 | #ifdef FS_44INODEFMT |
1fa5ceca KM |
334 | if (sblock->fs_inodefmt >= FS_44INODEFMT) |
335 | spcl.c_flags |= DR_NEWINODEFMT; | |
0289322c | 336 | #endif |
6175ef8c KM |
337 | maxino = sblock->fs_ipg * sblock->fs_ncg - 1; |
338 | mapsize = roundup(howmany(sblock->fs_ipg * sblock->fs_ncg, NBBY), | |
b6407c9d | 339 | TP_BSIZE); |
25c5efb9 KM |
340 | usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char)); |
341 | dumpdirmap = (char *)calloc((unsigned) mapsize, sizeof(char)); | |
342 | dumpinomap = (char *)calloc((unsigned) mapsize, sizeof(char)); | |
6175ef8c | 343 | tapesize = 3 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); |
0393c389 BJ |
344 | |
345 | msg("mapping (Pass I) [regular files]\n"); | |
6175ef8c | 346 | anydirskipped = mapfiles(maxino, &tapesize); |
0393c389 | 347 | |
6175ef8c KM |
348 | msg("mapping (Pass II) [directories]\n"); |
349 | while (anydirskipped) { | |
350 | anydirskipped = mapdirs(maxino, &tapesize); | |
351 | } | |
0393c389 | 352 | |
70c0f96a | 353 | if (pipeout) |
6175ef8c | 354 | tapesize += 10; /* 10 trailer blocks */ |
70c0f96a KM |
355 | else { |
356 | if (blocksperfile) | |
dd80a182 | 357 | fetapes = (float) tapesize / blocksperfile; |
70c0f96a KM |
358 | else if (cartridge) { |
359 | /* Estimate number of tapes, assuming streaming stops at | |
360 | the end of each block written, and not in mid-block. | |
361 | Assume no erroneous blocks; this can be compensated | |
362 | for with an artificially low tape size. */ | |
363 | fetapes = | |
6175ef8c | 364 | ( tapesize /* blocks */ |
70c0f96a KM |
365 | * TP_BSIZE /* bytes/block */ |
366 | * (1.0/density) /* 0.1" / byte */ | |
367 | + | |
6175ef8c | 368 | tapesize /* blocks */ |
70c0f96a KM |
369 | * (1.0/ntrec) /* streaming-stops per block */ |
370 | * 15.48 /* 0.1" / streaming-stop */ | |
371 | ) * (1.0 / tsize ); /* tape / 0.1" */ | |
372 | } else { | |
373 | /* Estimate number of tapes, for old fashioned 9-track | |
374 | tape */ | |
375 | int tenthsperirg = (density == 625) ? 3 : 7; | |
376 | fetapes = | |
6175ef8c | 377 | ( tapesize /* blocks */ |
70c0f96a KM |
378 | * TP_BSIZE /* bytes / block */ |
379 | * (1.0/density) /* 0.1" / byte */ | |
380 | + | |
6175ef8c | 381 | tapesize /* blocks */ |
70c0f96a KM |
382 | * (1.0/ntrec) /* IRG's / block */ |
383 | * tenthsperirg /* 0.1" / IRG */ | |
384 | ) * (1.0 / tsize ); /* tape / 0.1" */ | |
385 | } | |
386 | etapes = fetapes; /* truncating assignment */ | |
387 | etapes++; | |
6175ef8c KM |
388 | /* count the dumped inodes map on each additional tape */ |
389 | tapesize += (etapes - 1) * | |
390 | (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); | |
391 | tapesize += etapes + 10; /* headers + 10 trailer blks */ | |
1ddebffe | 392 | } |
70c0f96a | 393 | if (pipeout) |
6175ef8c | 394 | msg("estimated %ld tape blocks.\n", tapesize); |
70c0f96a KM |
395 | else |
396 | msg("estimated %ld tape blocks on %3.2f tape(s).\n", | |
6175ef8c | 397 | tapesize, fetapes); |
0393c389 | 398 | |
25c5efb9 KM |
399 | /* |
400 | * Allocate tape buffer | |
401 | */ | |
402 | if (!alloctape()) | |
403 | quit("can't allocate tape buffers - try a smaller blocking factor.\n"); | |
1ddebffe | 404 | |
ae744076 | 405 | startnewtape(1); |
25c5efb9 | 406 | (void) time((time_t *)&(tstart_writing)); |
6175ef8c | 407 | dumpmap(usedinomap, TS_CLRI, maxino); |
0393c389 BJ |
408 | |
409 | msg("dumping (Pass III) [directories]\n"); | |
6175ef8c KM |
410 | for (map = dumpdirmap, ino = 0; ino < maxino; ) { |
411 | if ((ino % NBBY) == 0) | |
0a008f8c | 412 | dirty = *map++; |
6175ef8c | 413 | else |
0a008f8c | 414 | dirty >>= 1; |
6175ef8c | 415 | ino++; |
0a008f8c | 416 | if ((dirty & 1) == 0) |
6175ef8c KM |
417 | continue; |
418 | /* | |
419 | * Skip directory inodes deleted and maybe reallocated | |
420 | */ | |
421 | dp = getino(ino); | |
422 | if ((dp->di_mode & IFMT) != IFDIR) | |
423 | continue; | |
25c5efb9 | 424 | (void) dumpino(dp, ino); |
6175ef8c | 425 | } |
0393c389 BJ |
426 | |
427 | msg("dumping (Pass IV) [regular files]\n"); | |
6175ef8c | 428 | for (map = dumpinomap, ino = 0; ino < maxino; ) { |
0289322c KM |
429 | int mode; |
430 | ||
6175ef8c | 431 | if ((ino % NBBY) == 0) |
0a008f8c | 432 | dirty = *map++; |
6175ef8c | 433 | else |
0a008f8c | 434 | dirty >>= 1; |
6175ef8c | 435 | ino++; |
0a008f8c | 436 | if ((dirty & 1) == 0) |
6175ef8c KM |
437 | continue; |
438 | /* | |
439 | * Skip inodes deleted and reallocated as directories. | |
440 | */ | |
441 | dp = getino(ino); | |
0289322c KM |
442 | mode = dp->di_mode & IFMT; |
443 | if (mode == IFDIR) | |
6175ef8c | 444 | continue; |
25c5efb9 | 445 | (void) dumpino(dp, ino); |
6175ef8c | 446 | } |
0393c389 BJ |
447 | |
448 | spcl.c_type = TS_END; | |
6175ef8c KM |
449 | for (i = 0; i < ntrec; i++) |
450 | writeheader(maxino); | |
70c0f96a KM |
451 | if (pipeout) |
452 | msg("DUMP: %ld tape blocks\n",spcl.c_tapea); | |
453 | else | |
454 | msg("DUMP: %ld tape blocks on %d volumes(s)\n", | |
455 | spcl.c_tapea, spcl.c_volume); | |
6175ef8c | 456 | putdumptime(); |
1db7a225 | 457 | trewind(); |
0393c389 | 458 | broadcast("DUMP IS DONE!\7\7\n"); |
ae744076 | 459 | msg("DUMP IS DONE\n"); |
0393c389 | 460 | Exit(X_FINOK); |
5c3d7d9e | 461 | /* NOTREACHED */ |
0393c389 BJ |
462 | } |
463 | ||
5c3d7d9e | 464 | void |
71b2d5ef KB |
465 | sig(signo) |
466 | int signo; | |
0393c389 | 467 | { |
71b2d5ef KB |
468 | switch(signo) { |
469 | case SIGALRM: | |
470 | case SIGBUS: | |
471 | case SIGFPE: | |
472 | case SIGHUP: | |
473 | case SIGTERM: | |
474 | case SIGTRAP: | |
475 | if (pipeout) | |
476 | quit("Signal on pipe: cannot recover\n"); | |
477 | msg("Rewriting attempted as response to unknown signal.\n"); | |
478 | (void) fflush(stderr); | |
479 | (void) fflush(stdout); | |
480 | close_rewind(); | |
0289322c | 481 | exit(X_REWRITE); |
71b2d5ef KB |
482 | /* NOTREACHED */ |
483 | case SIGSEGV: | |
484 | msg("SIGSEGV: ABORTING!\n"); | |
485 | (void) signal(SIGSEGV, SIG_DFL); | |
486 | (void) kill(0, SIGSEGV); | |
487 | /* NOTREACHED */ | |
488 | } | |
0393c389 BJ |
489 | } |
490 | ||
5c3d7d9e CT |
491 | char * |
492 | rawname(cp) | |
0393c389 BJ |
493 | char *cp; |
494 | { | |
495 | static char rawbuf[32]; | |
496 | char *dp = rindex(cp, '/'); | |
497 | ||
498 | if (dp == 0) | |
499 | return (0); | |
500 | *dp = 0; | |
25c5efb9 | 501 | (void) strcpy(rawbuf, cp); |
0393c389 | 502 | *dp = '/'; |
25c5efb9 KM |
503 | (void) strcat(rawbuf, "/r"); |
504 | (void) strcat(rawbuf, dp+1); | |
0393c389 BJ |
505 | return (rawbuf); |
506 | } | |
cdce5e6c KM |
507 | |
508 | #ifdef sunos | |
509 | char * | |
510 | strerror(errnum) | |
511 | int errnum; | |
512 | { | |
513 | extern int sys_nerr; | |
514 | extern char *sys_errlist[]; | |
515 | ||
516 | if (errnum < sys_nerr) { | |
517 | return(sys_errlist[errnum]); | |
518 | } else { | |
519 | return("bogus errno in strerror"); | |
520 | } | |
521 | } | |
522 | #endif |