1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
/* $Id: custom.c,v 1.2 1999/07/01 01:39:58 fraserm Exp $
$Log: custom.c,v $
Revision 1.2 1999/07/01 01:39:58 fraserm
word 0
Revision 1.1 1999/05/26 23:51:20 fraserm
Initial revision
*/
/* custom fields - i.e. incorporate external commands */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include "limo.h"
/* execute the command in cmdfmt with the file fname; assumes fname is a valid
filename from current location */
char *get_custom(int argc, char *argv[], struct custcmd *cmdfmt, char *fname)
{
char cmdbuf[CMDMAX];
char output[CMDOUTMAX];
char *retbuf = NULL;
int p[2]; /* pipe file descriptors */
FILE *f; /* the stdio'd version of the read side (p[0]) of the pipe */
pid_t child;
int status; /* status return of the child process */
char *my_argv[4];
int ch;
int i, curr;
/* ssize_t rv; */
/* make the command */
if (snprintf(cmdbuf, CMDMAX, cmdfmt->cmd, fname) == -1) {
retbuf = "Bad-Command";
}
else { /* made command ok */
/* create a pipe */
if (pipe(p) == -1) {
fprintf(stderr, "%s: pipe: %s\n", argv[0], strerror(errno));
retbuf = "Pipe Error";
}
else { /* made pipe ok */
/* printf("Pipe fds %d & %d\n", p[0], p[1]); */
/* split into two processes */
if ((child = fork()) == -1) {
fprintf(stderr, "%s: fork: %s\n", argv[0], strerror(errno));
}
else { /* forked ok */
if (child == 0) { /* in the child, dup() all the fds and run the
command */
/* make the writing end of the pipe the standard out and err for
this process */
if (dup2(p[1], 1) == -1 || dup2(p[1], 2) == -1) {
fprintf(stderr, "%s: dup2: %s\n", argv[0], strerror(errno));
close(p[1]);
exit(0); /* just exits the sub-process, mind! */
}
/* execute the command */
my_argv[0] = "sh";
my_argv[1] = "-c";
my_argv[2] = cmdbuf;
my_argv[3] = NULL;
execv("/bin/sh", my_argv);
exit(127);
}
else { /* in the parent, read the child's output */
/* let's make it into a standard IO object to make things simpler */
if ((f = fdopen(p[0], "r")) == NULL) {
fprintf(stderr, "%s: fdopen: %s\n", argv[0], strerror(errno));
retbuf = "Bad-Pipe-Read";
}
else { /* fdopened ok */
/* skip lines as required */
ch = fgetc(f);
for (curr = 1; curr < cmdfmt->linenum; ++curr) {
while (ch != EOF && ch != '\n') {
ch = fgetc(f);
}
}
if (ch == EOF) {
retbuf = "Not-Enough-Lines";
}
else {
/* right, skip whitespace first */
while (ch != EOF
&& (ch == ' ' || ch == '\r' || ch == '\t')) {
ch = fgetc(f);
}
if (ch == EOF || ch == '\n') {
retbuf = "Not-Enough-Lines";
}
else {
if (cmdfmt->wordnum != 0) { /* 0 means the whole line */
/* skip enough words */
for (curr = 1; curr < cmdfmt->wordnum; ++curr) {
/* skip a word */
while (ch != EOF
&& ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n') {
ch = fgetc(f);
}
if (ch == EOF || ch == '\n') {
break; /* EOF or end-of-line is game over */
}
/* skip the whitespace following it */
while (ch != EOF &&
(ch == ' ' || ch == '\r' || ch == '\t')) {
ch = fgetc(f);
}
if (ch == EOF || ch == '\n') {
break;
}
}
}
if (ch == EOF || ch == '\n') { /* must have hit something we
don't want */
retbuf = "Not-Enough-Words";
}
else {
if (ch != EOF) {
ungetc(ch, f); /* push the last one back */
/* read into the output buffer until we get a whitespace
or run out of buffer, or if wordnum is 0, until the
end of the line */
for (i = 0;
i < CMDOUTMAX-1 && (ch = fgetc(f)) != EOF;
++i) {
if (ch == '\n' || ch == '\r'
|| (cmdfmt->wordnum > 0
&& (ch == ' ' || ch == '\t'))) {
break;
}
output[i] = ch;
}
output[i] = '\0'; /* terminate the string properly */
}
}
}
}
/* close this end of the pipe */
fclose(f);
/* wait for the process to terminate */
if (waitpid(child, &status, 0) != child) {
fprintf(stderr, "%s: waitpid: %s\n", argv[0], strerror(errno));
}
/* did command succeed? */
if (WEXITSTATUS(status) != 0) {
retbuf = "-";
}
else {
if (retbuf == NULL) {
/* get a char buffer to return the output in */
if ((retbuf = (char *) malloc(i+1)) == NULL) {
fprintf(stderr, "%s: malloc: %s\n", argv[0],
strerror(errno));
retbuf = "Bad-malloc";
}
else { /* malloced ok */
strcpy(retbuf, output);
}
}
}
}
}
}
close(p[0]); /* the reading side */
close(p[1]); /* the writing side */
}
}
return retbuf;
}
|