Пример #1
0
void
freejobs()
{
	struct job *jp;

	collectjobs(WNOHANG);

	if (jobnote) {
		int savefd = setb(2);
		for (jp = joblst; jp; jp = jp->j_nxtp) {
			if (jp->j_flag & J_NOTIFY) {
				if (jp->j_jid)
					printjob(jp, PR_DFL);
				else if (jp->j_flag & J_FOREGND)
					printjob(jp, PR_STAT);
				else
					printjob(jp, PR_STAT|PR_PGID);
			}
		}
		(void) setb(savefd);
	}

	if (jobdone) {
		for (jp = joblst; jp; jp = jp->j_nxtp) {
			if (jp->j_flag & J_DONE)
				freejob(jp);
		}
	}
}
Пример #2
0
recvjob()
{
	struct stat stb;
	char *bp = pbuf;
	int status;

	/*
	 * Perform lookup for printer name or abbreviation
	 */
	if ((status = pgetent(line, printer)) < 0)
		fatal("cannot open printer description file");
	else if (status == 0)
		fatal("unknown printer");
	if ((LF = pgetstr("lf", &bp)) == NULL)
		LF = DEFLOGF;
	if ((SD = pgetstr("sd", &bp)) == NULL)
		SD = DEFSPOOL;
	if ((LO = pgetstr("lo", &bp)) == NULL)
		LO = DEFLOCK;

	(void) close(2);
	(void) open(LF, O_WRONLY|O_APPEND);
	if (chdir(SD) < 0)
		fatal("cannot chdir to %s", SD);
	if (stat(LO, &stb) == 0 && (stb.st_mode & 010)) {
		/* queue is disabled */
		putchar('\1');		/* return error code */
		exit(1);
	}

	if (readjob())
		printjob();
}
Пример #3
0
/* 
 * eval - Evaluate the command line that the user has just typed in
 * 
 * If the user has requested a built-in command (quit, jobs, bg or fg)
 * then execute it immediately. Otherwise, fork a child process and
 * run the job in the context of the child. If the job is running in
 * the foreground, wait for it to terminate and then return.  Note:
 * each child process must have a unique process group ID so that our
 * background children don't receive SIGINT (SIGTSTP) from the kernel
 * when we type ctrl-c (ctrl-z) at the keyboard.  
*/
void eval(char *cmdline) 
{
    char *argv[MAXARGS];
    int isBG = parseline(cmdline, argv);
    if (argv[0] == NULL) return;
    if (builtin_cmd(argv)) return;

    sigset_t allset;
    sigfillset(&allset);

    sigprocmask(SIG_BLOCK, &allset, NULL);
    pid_t childpid = fork();
    if (childpid == -1) unix_error("fork failed");
    if (childpid == 0) {
        sigprocmask(SIG_UNBLOCK, &allset, NULL);
        if (setpgid(0, 0) == -1)  unix_error("setpgrp failed");
        if (execv(argv[0], argv) == -1) unix_error("execv failed");
    } 

    if (isBG) {
        addjob(jobs, childpid, BG, cmdline);
        printjob(jobs, childpid);
        sigprocmask(SIG_UNBLOCK, &allset, NULL);
    } else {
        addjob(jobs, childpid, FG, cmdline);
        sigprocmask(SIG_UNBLOCK, &allset, NULL);
        waitfg(childpid);
    }

    return;
}
Пример #4
0
/* listjobs - Print the job list */
void listjobs(struct job_t *jobs) 
{
    int i;
    
    for (i = 0; i < MAXJOBS; i++) {
        printjob(jobs, jobs[i].pid);
    }
}
Пример #5
0
void
recvjob(void)
{
	struct stat stb;
	int status;

	/*
	 * Perform lookup for printer name or abbreviation
	 */
	if ((status = cgetent(&bp, printcapdb, printer)) == -2)
		frecverr("cannot open printer description file");
	else if (status == -1)
		frecverr("unknown printer %s", printer);
	else if (status == -3)
		fatal("potential reference loop detected in printcap file");
	
	if (cgetstr(bp, "lf", &LF) == -1)
		LF = _PATH_CONSOLE;
	if (cgetstr(bp, "sd", &SD) == -1)
		SD = _PATH_DEFSPOOL;
	if (cgetstr(bp, "lo", &LO) == -1)
		LO = DEFLOCK;

	(void)close(2);			/* set up log file */
	PRIV_START;
	if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
		syslog(LOG_ERR, "%s: %m", LF);
		(void)open(_PATH_DEVNULL, O_WRONLY);
	}
	PRIV_END;

	if (chdir(SD) < 0)
		frecverr("%s: %s: %m", printer, SD);
	if (stat(LO, &stb) == 0) {
		if (stb.st_mode & 010) {
			/* queue is disabled */
			putchar('\1');		/* return error code */
			exit(1);
		}
	} else if (stat(SD, &stb) < 0)
		frecverr("%s: %s: %m", printer, SD);

	minfree = 2 * read_number("minfree");	/* scale KB to 512 blocks */
	signal(SIGTERM, rcleanup);
	signal(SIGPIPE, rcleanup);

	if (readjob())
		printjob();
}
Пример #6
0
recvjob()
{
	struct stat stb;
	char *bp = pbuf;
	int status, rcleanup();

	/*
	 * Perform lookup for printer name or abbreviation
	 */
	if ((status = pgetent(line, printer)) < 0)
		frecverr("cannot open printer description file");
	else if (status == 0)
		frecverr("unknown printer %s", printer);
	if ((LF = pgetstr("lf", &bp)) == NULL)
		LF = DEFLOGF;
	if ((SD = pgetstr("sd", &bp)) == NULL)
		SD = DEFSPOOL;
	if ((LO = pgetstr("lo", &bp)) == NULL)
		LO = DEFLOCK;

	(void) close(2);			/* set up log file */
	if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
		syslog(LOG_ERR, "%s: %m", LF);
		(void) open("/dev/null", O_WRONLY);
	}

	if (chdir(SD) < 0)
		frecverr("%s: %s: %m", printer, SD);
	if (stat(LO, &stb) == 0) {
		if (stb.st_mode & 010) {
			/* queue is disabled */
			putchar('\1');		/* return error code */
			exit(1);
		}
	} else if (stat(SD, &stb) < 0)
		frecverr("%s: %s: %m", printer, SD);
	minfree = read_number("minfree");
	ddev = find_dev(stb.st_dev, S_IFBLK);
	if ((dfd = open(ddev, O_RDONLY)) < 0)
		syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
	signal(SIGTERM, rcleanup);
	signal(SIGPIPE, rcleanup);

	if (readjob())
		printjob();
}
Пример #7
0
void printallbanks()
{
    printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
    int num = 0;
    jobqueue *j;
    j = (jobqueue *)malloc(sizeof(jobqueue));
    for(num; num<4; num++)
    {
        int jnum = row[num].jsize;
        int a=0;
        printf("-------------bank %d-----------\n", num);
        {
            int k = &row[num];
            printf(" current rowbuffer : %s \n", row[num].rowbuffer);
            printf(" current jobqueue size : %d \n ", row[num].jsize);
            if(row[num].busy==1)
            {
                printf(" Row is busy \n");
            }
            else
            {
                printf(" Row is idle \n");
            }
            printf(" current job : \n");
            j = row[num].rq;
            for(a; a<jnum; a++)
            {
                printf(" %d job \n", a);
                printjob(j);
                printf("\n");
                j = j->before;

            }

        }

    }
    printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n\n");

}
Пример #8
0
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.  
 */
void sigchld_handler(int sig) 
{
    for (;;) {
        int status;
        pid_t childpid = waitpid(-1, &status, WNOHANG | WUNTRACED | WCONTINUED);
        if (childpid == -1) break; //unix_error("waitpid failed");
        if (childpid == 0) break;
        if (WIFEXITED(status)) {
            deletejob(jobs, childpid);
            // TODO: print exit code, WEXITSTATUS
        } else if (WIFSIGNALED(status)){
            deletejob(jobs, childpid);
            printf("Job [1] (%d) terminated by signal %d\n", childpid, WTERMSIG(status));
        } else if (WIFSTOPPED(status)) {
            getjobpid(jobs, childpid)->state = ST;
            printjob(jobs, childpid);
        } else if (WIFCONTINUED(status)) {
            int *state = &getjobpid(jobs, childpid)->state;
            if (*state == ST) *state = BG;
        }
    }
    return;
}
Пример #9
0
/*
 * Make a pass through the printcap database and start printing any
 * files left from the last time the machine went down.
 */
static void
startup(void)
{
	int pid, status, more;
	struct printer myprinter, *pp = &myprinter;

	more = firstprinter(pp, &status);
	if (status)
		goto errloop;
	while (more) {
		if (ckqueue(pp) <= 0) {
			goto next;
		}
		if (lflag)
			syslog(LOG_INFO, "lpd startup: work for %s",
			    pp->printer);
		if ((pid = fork()) < 0) {
			syslog(LOG_WARNING, "lpd startup: cannot fork for %s",
			    pp->printer);
			mcleanup(0);
		}
		if (pid == 0) {
			lastprinter();
			printjob(pp);
			/* NOTREACHED */
		}
		do {
next:
			more = nextprinter(pp, &status);
errloop:
			if (status)
				syslog(LOG_WARNING, 
				    "lpd startup: printcap entry for %s has errors, skipping",
				    pp->printer ? pp->printer : "<noname?>");
		} while (more && status);
	}
}
Пример #10
0
int
main(void)
{
  static char buf[100];
  int fd;
  //int status;
  
  // Assumes three file descriptors open.
  while((fd = open("console", O_RDWR)) >= 0){
    if(fd >= 3){
      close(fd);
      break;
    }
  }
  
  // Read and run input commands.
  int jobcntr = 0;
  jlist = malloc(sizeof(*jlist));
  jlist->first = 0;
  jlist->last = 0;
  jlist->fgJob = 0;
  
  int waitStatus;
  int bPrintDollar = 1;
  int cmdLen = 0;
  while((cmdLen = getcmd(buf, sizeof(buf), bPrintDollar)) >= 0){

      clearFinishedJobs(jlist);
	
      // Check if there's a forground job running. 
      // If so - the shell should not function, but only transfer the data received from the console to the job's pipe
      if (jlist->fgJob != 0) {
	  bPrintDollar = 0;
	  write(jlist->fgJob->fd, buf, cmdLen);
	  continue;
      }
      bPrintDollar = 1;
      
      if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' ') {
	// Clumsy but will have to do for now.
	// Chdir has no effect on the parent if run in the child.
	buf[strlen(buf)-1] = 0;  // chop \n
	if(chdir(buf+3) < 0)
	  printf(2, "cannot cd %s\n", buf+3);
	continue;
      }

      if(buf[0] == 'j' && buf[1] == 'o' && buf[2] == 'b' && buf[3] == 's' && (buf[4] == '\n' || buf[4] == ' ')) {
	  struct job* job = jlist->first;
	  while (job != 0) {
	      printjob(job->jid);
	      job = job->next;
	  }
	  if (!jlist->first)
		  printf(1, "There are no jobs.\n");
	  continue;
      }

      if(buf[0] == 'f' && buf[1] == 'g' && (buf[2] == '\n' || buf[2] == ' ')) {
	  char* c = &buf[3];

	  int jid = atoi(c);

	  struct job* j = jlist->first;
	  while ( j->jid != jid && j != 0) {
	      j = j->next;
	  }
	  jlist->fgJob = j;
	  //fg(jid);
	  continue;
      }

      // 0x0A - new line
      if (buf[0] != 0x0A ) { 
	
	  // create a pipe so the the shell sends the input to jobs_pipe[1] and the new process gets it in jobs_pipe[0]
	  if (pipe(jobs_pipe) == -1) {
	      panic("pipe");
	  }	  
	  
	  struct job* job;
	  job = malloc(sizeof(*job));
	  memset(job, 0, sizeof(*job));
	  job->jid = ++jobcntr;
	  job->fd = jobs_pipe[1];
	  
	  //char* s = job->cmd;
	  //char* t = buf;
	  //int i = sizeof(buf);
	  //while(--i > 0 && *t != '\n' && (*s++ = *t++) != 0) ;
	  //*s = 0;

	  

	  struct cmd* command = parsecmd(buf);
	  int childPid = fork1();
	  if(childPid == 0) {	    
	      close(0);	      
	      dup(jobs_pipe[0]);
	      close(jobs_pipe[1]);
	      if(fork1() == 0)
		  runcmd(command);
	      exit(0);
	  }
	  close(jobs_pipe[0]); // The shell doesn't need the READ end.
	  
	  attachjob(childPid, job); // Attach proc to job (Sys call)
		      
	  // shell writes the input to job_buffer ONLY IF the cmd isn't a backgraound job
	  if (command->type != BACK) {
	      jlist->fgJob = job;
	      bPrintDollar = 0;
	  }
	  
	  addJobToList(jlist, job);
	  
	  wait(&waitStatus);
      }
    }
    exit(0);
}
Пример #11
0
/* 
 * eval - Evaluate the command line that the user has just typed in
 * 
 * If the user has requested a built-in command (quit, jobs, bg or fg)
 * then execute it immediately. Otherwise, fork a child process and
 * run the job in the context of the child. If the job is running in
 * the foreground, wait for it to terminate and then return.  Note:
 * each child process must have a unique process group ID so that our
 * background children don't receive SIGINT (SIGTSTP) from the kernel
 * when we type ctrl-c (ctrl-z) at the keyboard.  
 */
void 
eval(char *cmdline) 
{
    int bg;              /* should the job run in bg or fg? */
    int job_state;      /* initial value of job BG or FG based on bg */
    int status;
    int check;
    struct cmdline_tokens tok;
    pid_t pid = -255;  // Initialzing to
    int jid = -255;   //  dummy values 
    sigset_t mask;      
    sigset_t mask2;      
    int flag = 0; //Used while processing "fg" built in command
    int infile_fd ; //file descriptor to be used for infile if specified in job 
    int outfile_fd ; //file descriptor to be used for outfile if specified in job

    //Get shell pid
    tsh_pid = getpid();

    //Intialize mask for blocked signal
    //Block SIGCHLD SIGINT SIGTSTP signals
    Sigemptyset(&mask);
    Sigemptyset(&mask2);
    Sigaddset(&mask,SIGCHLD);
    Sigaddset(&mask,SIGINT);
    Sigaddset(&mask2,SIGINT);
    Sigaddset(&mask,SIGTSTP);
    Sigaddset(&mask2,SIGTSTP);
    Sigprocmask(SIG_BLOCK,&mask,NULL);

    /* Parse command line */
    bg = parseline(cmdline, &tok); 

    if (bg == -1) return;               /* parsing error */
    if (tok.argv[0] == NULL)  return;   /* ignore empty lines */

    /* If tok is a BUILTIN shell command */
    if (tok.builtins != BUILTIN_NONE) {
        
       switch(tok.builtins) {                           

                           //Built in command quit :
                           //Send SIGKILL to all processes in shell
       case BUILTIN_QUIT : tsh_pid = getpid();
                           kill(-tsh_pid,SIGKILL);
                           break;

                           //List out all jobs when "jobs" called
                           //Also open output file if redirection specified and 
                           //redirect jobs output to the new file's descriptor

       case BUILTIN_JOBS :  if (tok.outfile != NULL) {
				    outfile_fd = open(tok.outfile , O_WRONLY);
				    listjobs(job_list,outfile_fd);
				    break;
			    }

			    else
				    listjobs(job_list,STDOUT_FILENO);
			    break;


			    // Parse job id or pid given with bg command
			    // Change state from ST to BG in job_list
			    // Send SIGCONT signal to job

       case BUILTIN_FG :   if(*(char *)(tok.argv[1]) == '%' ) {
				   jid = atoi( (((char *)(tok.argv[1])) + 1) ); 
				   pid = jid2pid(jid);
			   }
			   else {
				   pid = atoi(tok.argv[1]);
				   jid = pid2jid(pid);
			   }
			   change_job_state(job_list,pid,FG);
			   flag = 1;                            //flag set because we want to jump into else clause below 
			   // to process resumed job as a foreground job
			   Kill(-pid,SIGCONT);  
			   break;

			   //Parse job id or pid given with bg command
			   // Change state from ST to BG in job_list
			   // Send SIGCONT signal to job
       case BUILTIN_BG :   if(*(char *)(tok.argv[1]) == '%' ) {
				   jid = atoi( (((char *)(tok.argv[1])) + 1) ); 
				   pid = jid2pid(jid);
			   }
			   else {
				   pid = atoi(tok.argv[1]);
				   jid = pid2jid(pid);
			   }
			   printjob(pid,STDOUT_FILENO);
			   change_job_state(job_list,pid,BG);
			   Kill(-pid,SIGCONT);
			   break;
       case BUILTIN_NONE : break;
       default : break;

       }

    }


    //If tok is a external program to be run by shell 
    else if ((tok.builtins == BUILTIN_NONE) || (flag == 1)) {

	    if (flag == 1) 
		    bg = 0;

	    if(!bg)
		    job_state = FG;
	    else
		    job_state = BG;




	    //Child process   
	    if ((pid = Fork()) == 0) {

		    setpgid(0,0);  //Start process in new group     
		    Signal(SIGINT,  SIG_DFL);   /* ctrl-c from child handled by parent's sigchld */

		    addjob(job_list,getpid(),job_state,cmdline); 

		    // If input/output redirection specified open given file and point STDIN/STDOUT descriptor
		    // to new file's file descriptor
		    if (tok.infile != NULL) {
			    infile_fd = open(tok.infile , O_RDONLY);
			    dup2(infile_fd,STDIN_FILENO);   
		    }

		    if (tok.outfile != NULL) {
			    outfile_fd = open(tok.outfile , O_WRONLY);
			    dup2(outfile_fd,STDOUT_FILENO);   
		    }

		    //Unblock masks inherited from parent process
		    //and execute program using exec
		    Sigprocmask(SIG_UNBLOCK,&mask,NULL);
		    Execve(tok.argv[0],tok.argv,environ); 

	    }


	    //Parent process
	    //Add child to job list and unblock signal,also set fg_pid if job is foreground job	    
	    addjob(job_list,pid,job_state,cmdline); 
	    if(!bg)
		    fg_pid = pid;
	    Sigprocmask(SIG_UNBLOCK,&mask2,NULL); 

	    //Until foreground process terminates SIGCHLD functionality is done here , SIGINT and SIGTSTP are handled by handlers 
	    if(!bg) {

		    check = waitpid(pid,&status,WUNTRACED);
		    if ((check<0) && (errno!=ECHILD)) 
			    unix_error("waitfg : wait pid error\n");

		    if ((check == pid) && WIFSTOPPED(status)){
			    print_sigtstp_job(job_list,pid,SIGTSTP,STDOUT_FILENO);          //Print message that job was stopped by SIGSTP signal 

			    //Change stopped job state in list to ST (stopped) 
			    change_job_state(job_list,pid,ST);
			    return;
		    }

		    if ((check == pid) && (WIFSIGNALED(status)))
			    print_sigint_job(job_list,pid,WTERMSIG(status),STDOUT_FILENO);       //Print message that job/pid was terminated by a signal 


		    deletejob(job_list,pid);
		    Sigprocmask(SIG_UNBLOCK,&mask,NULL); 

	    }

	    else {
		    Sigprocmask(SIG_UNBLOCK,&mask,NULL); 
		    printjob(pid,STDOUT_FILENO);
	    }



    }

    return;
}