|
|
1.1 root 1: /*
2: * domach - install a file on a (single) machine.
3: *
4: * Output from the installation is appended to the
5: * "output" list. The result is a null string on success,
6: * non-null on failure.
7: */
8:
9: #include "decl.h"
10: #include <signal.h>
11: #include <errno.h>
12: #include <ipc.h>
13:
14: extern int alarm (int);
15:
16: static const int bufsize = 4096;
17: static const int timeout = 60*10;
18:
19: static void
20: alarmcatch()
21: {
22: signal (SIGALRM, alarmcatch);
23: }
24:
25: static void
26: pipecatch()
27: {
28: signal (SIGPIPE, pipecatch);
29: }
30:
31: static int
32: twrite (int fd, char* buf, int n)
33: {
34: SIG_TYP pipesave = signal (SIGPIPE, (SIG_ARG_TYP) pipecatch);
35: alarm (timeout);
36: int r = write (fd, buf, n);
37: alarm (0);
38: signal (SIGPIPE, (SIG_ARG_TYP) pipesave);
39: return r;
40: }
41:
42: static int
43: tread (int fd, char* buf, int n)
44: {
45: alarm (timeout);
46: int r = read (fd, buf, n);
47: alarm (0);
48: return r;
49: }
50:
51: String
52: domach (String machname, Path file, String_list& output)
53: {
54: checksum cs;
55: signal (SIGALRM, alarmcatch);
56:
57: /* Open the input file */
58: int infd = open (String(file), 0);
59: if (infd < 0) {
60: output += "cannot open package";
61: return "";
62: }
63:
64: /* Establish a connection to the remote machine */
65: errno = 0;
66: int remfd = ipcopen(ipcpath(charstr(machname),"dk","asd"), "heavy delim");
67: if (remfd < 0) {
68: close (infd);
69:
70: switch (errno) {
71:
72: /* permanent errors */
73: case ENOENT: /* illegal destination name */
74: case EACCES: /* permission denied */
75: if (errstr)
76: output += errstr;
77: return "";
78:
79: default:
80: if (errstr)
81: return errstr;
82: return "cannot connect";
83:
84: case 0:
85: ;
86: }
87: }
88:
89: char buf[bufsize];
90: int n, w;
91:
92: /* verify that we are talking to a dkinstall process */
93: n = tread (remfd, buf, bufsize);
94: if (n != 4 || strncmp (buf, "asd\n", 4) != 0) {
95: close (infd);
96: close (remfd);
97: output += "cannot ship to this destination";
98: output += dec(n) + (": " + String(buf,n>0?n-1:0));
99: return "";
100: }
101:
102: /* copy the file data to the remote system */
103: while ((n = read (infd, buf, bufsize)) > 0) {
104: cs.combine (buf, n);
105: w = twrite (remfd, buf, n);
106: if (w != n) {
107: close (infd);
108: close (remfd);
109: return "error while writing to remote";
110: }
111: }
112:
113: close (infd);
114: if (n != 0) {
115: close (remfd);
116: return "input error";
117: }
118:
119: /* Indicate end of file */
120: if (twrite (remfd, "", 0) != 0) {
121: close (remfd);
122: return "cannot write eof";
123: }
124:
125: /* Send the checksum */
126: SIG_TYP pipesave = signal (SIGPIPE, (SIG_ARG_TYP) pipecatch);
127: alarm (timeout);
128: n = write (remfd, cs);
129: alarm (0);
130: signal (SIGPIPE, (SIG_ARG_TYP) pipesave);
131: if (n != cksize) {
132: close (remfd);
133: return "cannot send checksum";
134: }
135:
136: /*
137: * Read the acknowledgment. If the acknowledgment begins
138: * with a null record, it indicates success or permanent
139: * failure. Otherwise it is a temporary failure.
140: */
141:
142: if ((n = tread (remfd, buf, bufsize)) != 0) {
143: close (remfd);
144: if (n < 0)
145: return "error reading ack";
146: String msg (buf, n);
147: if ((n = msg.strchr('\n')) >= 0)
148: msg = msg (0, n);
149: return msg;
150: }
151:
152: /*
153: * We got here only if we saw a null record from the remote.
154: *
155: * Read and handle the stuff coming in from the remote.
156: * Discard leading null lines, which are probably
157: * keep-alive messages but are good to remove even
158: * even if they aren't.
159: */
160: String remnant;
161: int gotdata = 0;
162: while ((n = tread (remfd, buf, bufsize)) > 0) {
163: register char *p = buf;
164: char *lastp = p, *lim = p + n;
165: while (p < lim) {
166: if (*p == '\n') {
167: String line = remnant +
168: String (lastp, p - lastp);
169: if (gotdata || line.length() != 0) {
170: output += line;
171: gotdata = 1;
172: }
173: remnant = "";
174: lastp = p + 1;
175: }
176: p++;
177: }
178: remnant += String (lastp, p - lastp);
179: }
180:
181: if (remnant.length() != 0)
182: output += remnant;
183:
184: /* remove trailing normal status message */
185: String s;
186: if (output.lastX (s)) {
187: if (s == "return code 0")
188: output.unput();
189: }
190:
191: close (remfd);
192:
193: if (n < 0)
194: return "error reading return status";
195:
196: return "";
197: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.