Commit | Line | Data |
---|---|---|
9d25673b C |
1 | /* utils.c: functions of general utility */ |
2 | ||
3 | #include <errno.h> | |
4 | #include <setjmp.h> | |
5 | #include "rc.h" | |
6 | #include "jbwrap.h" | |
7 | ||
8 | /* print error with line number on noninteractive shells (i.e., scripts) */ | |
9 | ||
10 | extern void pr_error(char *s) { | |
11 | if (s != NULL) { | |
12 | if (interactive) | |
13 | fprint(2, "%s\n", s); | |
14 | else | |
15 | fprint(2, "line %d: %s\n", lineno - 1, s); | |
16 | } | |
17 | } | |
18 | ||
19 | /* our perror */ | |
20 | ||
21 | extern void uerror(char *s) { | |
22 | extern int sys_nerr; | |
23 | extern char *sys_errlist[]; | |
24 | if (errno > sys_nerr) | |
25 | return; | |
26 | if (s != NULL) | |
27 | fprint(2, "%s: %s\n", s, sys_errlist[errno]); | |
28 | else | |
29 | fprint(2, "%s\n", sys_errlist[errno]); | |
30 | } | |
31 | ||
32 | /* Die horribly. This should never get called. Please let me know if it does. */ | |
33 | ||
34 | #define PANICMSG "rc panic: " | |
35 | ||
36 | extern void panic(char *s) { | |
37 | write(2, PANICMSG, conststrlen(PANICMSG)); | |
38 | write(2, s, strlen(s)); | |
39 | write(2, "!\n", 2); | |
40 | exit(1); | |
41 | } | |
42 | ||
43 | /* ascii -> unsigned conversion routines. -1 indicates conversion error. */ | |
44 | ||
45 | extern int n2u(char *s, unsigned int base) { | |
46 | unsigned int i; | |
47 | for (i = 0; *s != '\0'; s++) { | |
48 | unsigned int j = (unsigned int) *s - '0'; | |
49 | if (j >= base) /* small hack with unsigned ints -- one compare for range test */ | |
50 | return -1; | |
51 | i = i * base + j; | |
52 | } | |
53 | return (int) i; | |
54 | } | |
55 | ||
56 | /* The last word in portable ANSI: a strcmp wrapper for qsort */ | |
57 | ||
58 | extern int starstrcmp(const void *s1, const void *s2) { | |
59 | return strcmp(*(char **)s1, *(char **)s2); | |
60 | } | |
61 | ||
62 | /* tests to see if pathname begins with "/", "./", or "../" */ | |
63 | ||
64 | extern bool isabsolute(char *path) { | |
65 | return path[0] == '/' || (path[0] == '.' && (path[1] == '/' || (path[1] == '.' && path[2] == '/'))); | |
66 | } | |
67 | ||
68 | /* signal-safe read and write (for BSD slow devices). writeall also allows partial writes */ | |
69 | ||
70 | extern void writeall(int fd, char *buf, size_t remain) { | |
71 | int i; | |
72 | for (i = 0; remain > 0; buf += i, remain -= i) { | |
73 | interrupt_happened = FALSE; | |
74 | if (!setjmp(slowbuf.j)) { | |
75 | slow = TRUE; | |
76 | if (interrupt_happened) | |
77 | break; | |
78 | else if ((i = write(fd, buf, remain)) <= 0) | |
79 | break; /* abort silently on errors in write() */ | |
80 | } else | |
81 | break; | |
82 | slow = FALSE; | |
83 | } | |
84 | slow = FALSE; | |
85 | SIGCHK; | |
86 | } | |
87 | ||
88 | extern int rc_read(int fd, char *buf, size_t n) { | |
89 | long /*ssize_t*/ r; | |
90 | interrupt_happened = FALSE; | |
91 | if (!setjmp(slowbuf.j)) { | |
92 | slow = TRUE; | |
93 | if (!interrupt_happened) | |
94 | r = read(fd, buf, n); | |
95 | else | |
96 | r = -2; | |
97 | } else | |
98 | r = -2; | |
99 | slow = FALSE; | |
100 | if (r == -2) { | |
101 | errno = EINTR; | |
102 | r = -1; | |
103 | } | |
104 | SIGCHK; | |
105 | return r; | |
106 | } | |
107 | ||
108 | /* clear out z bytes from character string s */ | |
109 | ||
110 | extern char *clear(char *s, size_t z) { | |
111 | while (z != 0) | |
112 | s[--z] = 0; | |
113 | return s; | |
114 | } | |
115 | ||
116 | /* duplicate a fd and close the old one only if necessary */ | |
117 | ||
118 | extern int mvfd(int i, int j) { | |
119 | if (i != j) { | |
120 | int s = dup2(i, j); | |
121 | close(i); | |
122 | return s; | |
123 | } | |
124 | return 0; | |
125 | } |