Выбрать главу

 43: };

 44:

 45: struct job {

 46:  int jobId;        /* номер задания */

 47:  int numProgs;     /* количество программ в задании */

 48:  int runningProgs; /* количество выполняющихся программ */

 49:  char * text;      /* имя задания */

 50:  char * cmdBuf;    /* буфер, на который ссылаются различные массивы argv */

 51:  pid_t pgrp;       /* идентификатор группы процесса для задания */

 52:  struct childProgram* progs; /* массив программ в задании */

 53:  struct job* next; /* для отслеживания фоновых команд */

 54:  int stoppedProgs; /* количество активных, но приостановленных программ */

 55: };

 56:

 57: void freeJob (struct job * cmd) {

 58:  int i;

 59:

 60:  for (i = 0; i <cmd->numProgs; i++) {

 61:   free(cmd->progs[i].argv);

 62:   if (cmd->progs[i].redirections)

 63:    free(cmd->progs[i].redirections);

 64:   if (cmd->progs[i].freeGlob)

 65:    globfree(&cmd->progs[i].globResult);

 66:  }

 67:  free(cmd->progs);

 68:  if (cmd->text) free(cmd->text);

 69:   free(cmd->cmdBuf);

 70: }

 71:

 72: int getCommand(FILE * source, char * command) {

 73:  if (source == stdin) {

 74:   printf("# ");

 75:   fflush(stdout);

 76:  }

 77:

 78:  if (!fgets(command, MAX_COMMAND_LEN, source)) {

 79:   if (source == stdin) printf("\n");

 80:   return 1;

 81:  }

 82:

 83:  /* удаление хвостового символа новой строки */

 84:  command[strlen(command) - 1] = '\0';

 85:

 86:  return 0;

 87: }

 88:

 89: void globLastArgument(struct childProgram * prog, int * argcPtr,

 90:  int * argcAllocedPtr) {

 91:  int argc = *argcPtr;

 92:  int argcAlloced = *argcAllocedPtr;

 93:  int rc;

 94:  int flags;

 95:  int i;

 96:  char * src, * dst;

 98:  if (argc>1) { /* cmd->globResult уже инициализирован */

 99:   flags = GLOB_APPEND;

100:   i = prog->globResult.gl_pathc;

101:  } else {

102:   prog->freeGlob = 1;

103:   flags = 0;

104:   i = 0;

105:  }

106:

107:  rc = glob(prog->argv[argc - 1], flags, NULL, &prog->globResult);

108:  if (rc == GLOB_NOSPACE) {

109:   fprintf(stderr, "недостаточно пространства для универсализации\n");

110:   return;

111:  } else if (rc == GLOB_NOMATCH ||

112:   (!rc && (prog->globResult.gl_pathc - i) == 1 &&

113:   !strcmp(prog->argv[argc - 1],

114:   prog->globResult.gl_pathv[i]))) {

115:   /* нам нужно удалить все, что до сих пор было заключено между \ */

116:   src = dst = prog->argv[argc - 1];

117:   while (*src) {

118:    if (*src != '\\') *dst++ = *src;

119:    src++;

120:   }

121:   *dst = '\0';

122:  } else if (!rc) {

123:   argcAlloced += (prog->globResult.gl_pathc - i);

124:   prog->argv = realloc(prog->argv,

125:   argcAlloced * sizeof(*prog->argv));

126:   memcpy(prog->argv + (argc - 1),

127:   prog->globResult.gl_pathv + i,

128:   sizeof(*(prog->argv)) *

129:    (prog->globResult.gl_pathc - i));

130:   argc += (prog->globResult.gl_pathc - i - 1);

131:  }

132:

133:  *argcAllocedPtr = argcAlloced;

134:  *argcPtr = argc;

135: }

136:

137: /* Возвращаем cmd->numProgs как 0, если не представлено ни одной команды

138:    (например, пустая строка). Если будет обнаружена допустимая команда,

139:    commandPtr будет ссылаться на начало следующей команды (если исходная

140:    команда была связана с несколькими заданиями) или будет равно NULL,

141:    если больше не представлено ни одной команды. */

142: int parseCommand(char ** commandPtr, struct job * job, int * isBg) {

143:  char * command;

144:  char * returnCommand = NULL;

145:  char * src, * buf, * chptr;

146:  int argc = 0;

147:  int done = 0;

148:  int argvAlloced;

149:  int i;

150:  char quote = '\0';

151:  int count;

152:  struct childProgram * prog;

153:

154:  /* пропускаем первое свободное место (например, пробел) */

155:  while (**commandPtr && isspace(**commandPtr)) (*commandPtr)++;

156:

157:  /* обрабатываем пустые строки и первые символы '#' */

158:  if (!**commandPtr || (**commandPtr=='#')) {

159:   job->numProgs = 0;

160:   *commandPtr = NULL;

161:   return 0;

162:  }

163:

164:  *isBg = 0;

165:  job->numProgs = 1;

166:  job->progs = malloc(sizeof(*job->progs));

167:

168:  /* Мы задаем элементы массива argv для ссылки внутри строки.

169:     Освобождение памяти осуществляется с помощью функции freeJob().

170:

171:     Получив незанятую память, нам не нужно будет использовать завершающие

172:     значения NULL, поэтому оставшаяся часть будет выглядеть аккуратнее

173:     (хотя, честно говоря, менее эффективно). */

174:  job->cmdBuf = command = calloc(1, strlen(*commandPtr) + 1);

175:  job->text = NULL;

176:

177:  prog = job->progs;

178:  prog->numRedirections = 0;

179:  prog->redirections = NULL;

180:  prog->freeGlob = 0;

181:  prog->isStopped = 0;

182:

183:  argvAlloced = 5;