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