|
|
1.1 root 1: #include <sys/types.h>
2: #include <stdio.h>
3: #include <errno.h>
4: #include <sys/wait.h>
5: #include "dsh.h"
6:
7: int errno; /* global error location */
8:
9: /* options */
10: bool fflg = FALSE; /* if TRUE fanout stdin */
11: bool hflg = FALSE; /* if TRUE use specified host */
12: bool vflg = FALSE; /* tell hosts */
13: bool nflg = FALSE; /* same as for rsh */
14: bool aflg = FALSE; /* true if all nodes to be used */
15: bool sflg = FALSE; /* like -n for make */
16:
17: /* files to be rcp'd for input or output */
18: struct rcpfile {
19: char *r_name; /* name of the file */
20: struct rcpfile *r_next;
21: };
22: struct rcpfile *rcpin = 0; /* list of files to copy to */
23: struct rcpfile *rcpout = 0; /* list of files to copy from */
24:
25: char *av[100]; /* the command */
26: union wait pstatus; /* the return status of the job */
27: struct hostdef *thehost; /* the hosts */
28: char *spechost; /* the specified host */
29:
30: /* external routines */
31: int error();
32: struct hostdef *highest();
33: int getbids();
34: double atof();
35: bool aresynonyms();
36:
37: main(argc, argv)
38: int argc;
39: char *argv[];
40: {
41: int inda, indc, ind;
42: struct rcpfile *lin, *lout, *next;
43: struct hostdef *hp;
44:
45: /* now worry about the commands */
46: for (inda = 1; inda < argc; inda++) {
47:
48: /* process an opton */
49: if (argv[inda][0] == '-') {
50: ind = inda;
51: for (indc = 1; argv[ind][indc] != NULL; indc++) {
52: switch (argv[ind][indc]) {
53:
54: /* all nodes are specified */
55: case 'a':
56: aflg = TRUE;
57: break;
58:
59: case 's':
60: sflg = TRUE;
61: break;
62:
63: /* fanout input */
64: case 'f':
65: fflg = TRUE;
66: break;
67:
68: /* specify hosts */
69: case 'h':
70: inda++;
71: if (inda < argc) {
72: hflg = TRUE;
73: spechost = argv[inda];
74: } else {
75: fprintf (stderr, "%s: no host after -h\n", argv[0]);
76: exit (-1);
77: }
78: break;
79:
80: /* specify input files */
81: case 'i':
82: inda++;
83: if (inda < argc) {
84: next = new (struct rcpfile);
85: if (rcpin == 0) {
86: rcpin = next;
87: } else {
88: lin->r_next = next;
89: }
90: lin = next;
91: lin->r_next = 0;
92: lin->r_name = argv[inda];
93: } else {
94: fprintf (stderr, "%s: no input file after -i\n", argv[0]);
95: exit (-1);
96: }
97: break;
98:
99: /* specify output files */
100: case 'o':
101: inda++;
102: if (inda < argc) {
103: next = new (struct rcpfile);
104: if (rcpout == 0) {
105: rcpout = next;
106: } else {
107: lout->r_next = next;
108: }
109: lout = next;
110: lout->r_next = 0;
111: lout->r_name = argv[inda];
112: } else {
113: fprintf (stderr, "%s: no output file after -o\n", argv[0]);
114: exit (-1);
115: }
116: break;
117:
118: /* pipe from /dev/null */
119: case 'n':
120: nflg = TRUE;
121: break;
122:
123: /* tell which machine we're using */
124: case 'v':
125: vflg = TRUE;
126: break;
127:
128: default:
129: fprintf (stderr, "usage: %s [-anv][-io file] <command>\n", argv[0]);
130: exit (-1);
131: }
132: }
133: } else {
134: break;
135: }
136: }
137:
138: /* pick up the command */
139: for (ind = 0; inda < argc; inda++, ind++) {
140: av[ind] = argv[inda];
141: }
142: av[ind] = 0;
143:
144: /* process the defaults file */
145: getnodes();
146:
147: /* see if anyone wants to bid */
148: getbids(av, thehost);
149:
150: /* execute the command */
151: hp = highest ();
152: if (hp == 0) {
153: error ("no machine bid for the command");
154: }
155: if (aflg) {
156: do {
157: rexecute (hp);
158: hp = highest ();
159: } while (hp != 0);
160: } else {
161: rexecute (hp);
162: }
163:
164: if (pstatus.w_T.w_Termsig != 0) {
165: fprintf (stderr, "(signal %d)", pstatus.w_T.w_Termsig);
166: pstatus.w_T.w_Retcode = 0;
167: }
168: if (pstatus.w_T.w_Coredump == 1) {
169: fprintf (stderr, "(core dumped)\n");
170: pstatus.w_T.w_Retcode = 0;
171: }
172:
173: exit (pstatus.w_T.w_Retcode);
174: }
175:
176: /*
177: * find out which nodes to use
178: */
179: char *
180: skipgrey(p)
181: char *p;
182: {
183: while (*p == ' ' || *p == '\t' || *p == ',' || *p == ')' || *p == '*')
184: p++;
185: return (p);
186: }
187:
188: char *
189: token (to, sp)
190: char *to;
191: char *sp;
192: {
193: while (*sp != ' ' && *sp != '\t' && *sp != ',' && *sp !=')' && *sp != 0) {
194: *to++ = *sp++;
195: }
196: return (sp);
197: }
198:
199: getnodes()
200: {
201: char *sp;
202: struct hostdef *last, *next;
203: bool account;
204: double weight;
205: char buf[132];
206: int rv;
207:
208: thehost = 0;
209: rv = getstringrc (".dshrc", "hosts", buf);
210: if (rv < 0) {
211: rv = getstringrc ("/usr/lib/dshrc", "hosts", buf);
212: if (rv < 0) {
213: error ("dsh: no hosts in rc files");
214: }
215: }
216:
217: /* convert to reasonable format */
218: sp = buf;
219: while (*sp != 0) {
220: sp = skipgrey (sp);
221:
222: /* get the multiplier */
223: weight = 1.0;
224: if ((*sp >= '0' && *sp <= '9') || *sp == '.') {
225: weight = atof (sp);
226: for (;*sp != '*' && *sp != 0; sp++);
227: sp = skipgrey (sp);
228: }
229:
230: if (*sp != 0) {
231:
232: /* allocate some space and chain it in */
233: next = new (struct hostdef);
234: if (thehost == 0) {
235: thehost = next;
236: } else {
237: last->h_next = next;
238: }
239: last = next;
240: last->h_next = 0;
241: last->h_weight = weight;
242:
243: /* pick up the entry */
244: if (*sp == '(') {
245: sp++;
246: sp = skipgrey (sp);
247: account = TRUE;
248: } else {
249: account = FALSE;
250: }
251: sp = token (last->h_name, sp);
252: if (account) {
253: sp = skipgrey (sp);
254: sp = token (last->h_user, sp);
255: } else {
256: *(last->h_user) = 0;
257: }
258: }
259: }
260: }
261:
262: /*
263: * execute a command
264: */
265: execute (argv, block, justtell, ignore)
266: char *argv[]; /* the command */
267: bool block; /* if true, block till the command is done */
268: bool justtell; /* true if we shouldn't execute when debuging */
269: bool ignore; /* ignore output */
270: {
271: int argc;
272: int pid, rv;
273: int status, fd;
274:
275: if (sflg) {
276:
277: /* just say what we'll do */
278: for (argc = 0;argv[argc] != 0; argc++) {
279: printf ("%s ", argv[argc]);
280: }
281: printf ("\n");
282: }
283: if (!(justtell && sflg)) {
284:
285: /* really do it */
286: if (pid = fork()) {
287: if (block) {
288: do {
289: rv = wait (&status);
290: } while (rv != -1 && rv != pid);
291: }
292: } else {
293: if (ignore) {
294: fd = open ("/dev/null", 2);
295: dup2 (fd, 1);
296: dup2 (fd, 2);
297: }
298: execvp (argv[0], argv);
299: _exit (0);
300: }
301: }
302: }
303:
304: /*
305: * remotely execute the command
306: */
307: rexecute (hp)
308: struct hostdef *hp; /* the host to execute on */
309: {
310: struct rcpfile *fp;
311: int rv;
312: int argc, ac;
313: char *argv[200];
314: char mydir[PATHSIZE];
315: bool local;
316:
317: if (vflg || aflg) {
318: fprintf (stderr, ">>%s<<\n", hp->h_name);
319: }
320: argc = 0;
321: local = aresynonyms (hp->h_name, myhostname());
322: if (!local) {
323: /* get our directory if we're going to copy files */
324: if (rcpin != 0 || rcpout != 0) {
325: getwd (mydir);
326: }
327:
328: /* make the directory we're going to use */
329: argv[argc++] = "(";
330: argv[argc++] = "mkdir";
331: argv[argc++] = hp->h_dir;
332: argv[argc++] = ";";
333:
334: /* and hop to it */
335: argv[argc++] = "cd";
336: argv[argc++] = hp->h_dir;
337: argv[argc++] = ";";
338:
339: /* copy over any files */
340: if (rcpin != 0) {
341: argv[argc++] = "rcp";
342: for (fp = rcpin; fp != 0; fp = fp->r_next) {
343: argv[argc] = (char *) malloc (HOSTNAMESIZE+2*PATHSIZE);
344: if (fp->r_name[0] == '/' || fp->r_name[0] == '~') {
345: sprintf (argv[argc++], "%s:%s", myhostname(), fp->r_name);
346: } else {
347: sprintf (argv[argc++], "%s:%s/%s", myhostname(),
348: mydir, fp->r_name);
349: }
350: }
351: argv[argc++] = ".";
352: argv[argc++] = ";";
353: }
354: }
355:
356: /* execute the command */
357: for (ac = 0; av[ac] != 0; ac++) {
358: argv[argc++] = av[ac];
359: }
360: argv[argc++] = ";";
361:
362: if (!local) {
363:
364: /* copy back any files */
365: if (rcpout != 0) {
366: argv[argc++] = "rcp";
367: for (fp = rcpout; fp != 0; fp = fp->r_next) {
368: argv[argc++] = fp->r_name;
369: }
370: argv[argc] = (char *) malloc (HOSTNAMESIZE+2*PATHSIZE);
371: sprintf (argv[argc++], "%s:%s", myhostname(), mydir);
372: argv[argc++] = ";";
373: }
374:
375: /* clean up the directory */
376: argv[argc++] = "cd";
377: argv[argc++] = "..";
378: argv[argc++] = ";";
379: argv[argc++] = "/bin/rm";
380: argv[argc++] = "-fr";
381: argv[argc++] = hp->h_dir;
382: argv[argc++] = ")";
383: }
384: argv[argc] = 0;
385:
386: rshell (hp, argv, TRUE, nflg, TRUE, FALSE);
387: }
388:
389: rshell (hp, av, block, usenflg, justtell, ignore)
390: struct hostdef *hp; /* all about the host */
391: char *av[]; /* the command */
392: bool block; /* true if we should block */
393: bool usenflg; /* true if we should use the n flag */
394: bool justtell; /* true if we shouldn't execute when debuging */
395: bool ignore; /* ignore the output from the command */
396: {
397: int rv;
398: int argc, ac;
399: char *argv[100];
400: char command[256];
401: char *p, *p1;
402: bool local;
403:
404: argc = 0;
405: local = aresynonyms (hp->h_name, myhostname());
406: if (local) {
407: argv[argc++] = "csh";
408: argv[argc++] = "-c";
409: argv[argc++] = command;
410: p = command;
411: for (ac = 0; av[ac] != 0; ac++) {
412: *p++ = ' ';
413: for (p1 = av[ac]; *p1 != 0;){
414: *p++ = *p1++;
415: }
416: }
417: *p = 0;
418: } else {
419: argv[argc++] = "rsh";
420: argv[argc++] = hp->h_name;
421: if (usenflg) {
422: argv[argc++] = "-n";
423: }
424: if (*(hp->h_user) != 0) {
425: argv[argc++] = "-l";
426: argv[argc++] = hp->h_user;
427: }
428: for (ac = 0; av[ac] != 0; ac++) {
429: argv[argc++] = av[ac];
430: }
431: }
432: argv[argc] = 0;
433: execute (argv, block, justtell, ignore);
434: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.