Esempio n. 1
0
/*
 * Accumulate JSON array of our parent processes:
 *     [
 *         exe-name-parent,
 *         exe-name-grand-parent,
 *         ...
 *     ]
 *
 * Note: we only report the filename of the process executable; the
 *       only way to get its full pathname is to use OpenProcess()
 *       and GetModuleFileNameEx() or QueryfullProcessImageName()
 *       and that seems rather expensive (on top of the cost of
 *       getting the snapshot).
 *
 * Note: we compute the set of parent processes by walking the PPID
 *       link in each visited PROCESSENTRY32 record.  This search
 *       stops when an ancestor process is not found in the snapshot
 *       (because it exited before the current or intermediate parent
 *       process exited).
 *
 *       This search may compute an incorrect result if the PPID link
 *       refers to the PID of an exited parent and that PID has been
 *       recycled and given to a new unrelated process.
 *
 *       Worse, it is possible for a child or descendant of the
 *       current process to be given the recycled PID and cause a
 *       PPID-cycle.  This would cause an infinite loop building our
 *       parent process array.
 *
 * Note: for completeness, the "System Idle" process has PID=0 and
 *       PPID=0 and could cause another PPID-cycle.  We don't expect
 *       Git to be a descendant of the idle process, but because of
 *       PID recycling, it might be possible to get a PPID link value
 *       of 0.  This too would cause an infinite loop.
 *
 * Therefore, we keep an array of the visited PPIDs to guard against
 * cycles.
 *
 * We use a fixed-size array rather than ALLOC_GROW to keep things
 * simple and avoid the alloc/realloc overhead.  It is OK if we
 * truncate the search and return a partial answer.
 */
static void get_processes(struct json_writer *jw, HANDLE hSnapshot)
{
	PROCESSENTRY32 pe32;
	DWORD pid;
	DWORD pid_list[NR_PIDS_LIMIT];
	int k, nr_pids = 0;

	pid = GetCurrentProcessId();
	while (find_pid(pid, hSnapshot, &pe32)) {
		/* Only report parents. Omit self from the JSON output. */
		if (nr_pids)
			jw_array_string(jw, pe32.szExeFile);

		/* Check for cycle in snapshot. (Yes, it happened.) */
		for (k = 0; k < nr_pids; k++)
			if (pid == pid_list[k]) {
				jw_array_string(jw, "(cycle)");
				return;
			}

		if (nr_pids == NR_PIDS_LIMIT) {
			jw_array_string(jw, "(truncated)");
			return;
		}

		pid_list[nr_pids++] = pid;

		pid = pe32.th32ParentProcessID;
	}
}
Esempio n. 2
0
File: jobs.c Progetto: Fusiow/msh
void		fg_bg(t_jobs *jobs, char **tab, int k)
{
	int		pid;
	int		ret;

	ret = 0;
	pid = 0;
	if (jobs == NULL)
	{
		job_error(k);
		return ;
	}
	if (tab[1])
	{
		if (is_digit(tab[1]) == 0)
		{
			pid_error(tab[1]);
			return ;
		}
	}
	else
		pid = find_pid(g_jobs);
	job_continued(jobs->job, jobs->name);
	kill(pid, SIGCONT);
	waitpid(pid, &ret, WUNTRACED);
	check_return(ret, pid);
}
Esempio n. 3
0
/* Spawn a kernel thread.    
 * This is not quite cool, but we have to do some initialization in
 * kernel's address space, the approach in linux0.11 is not quite 
 * ease here for the fact that trap occured in the kernel space do 
 * not refering the esp in TSS.
 *
 * returns a pointer to the newly borned proc, one page size(with the kernel stack).
 * */
struct proc* kspawn(void (*func)()){
    uint nr;
    int fd, n;
    struct file *fp;
    struct proc *p;

    nr = find_pid();
    if (nr == 0) {
        panic("no free pid");
    }

    p = (struct proc *) kmalloc(PAGE);
    if (p==NULL) {
        panic("no free page");
    }
    proc[nr] = p;
    p->p_stat = SSLEEP; // set SRUN later.
    p->p_pid  = nr;
    p->p_ppid = cu->p_pid;
    p->p_pgrp = cu->p_pgrp;
    p->p_flag = cu->p_flag;
    p->p_cpu  = cu->p_cpu;
    p->p_nice = cu->p_nice;
    p->p_pri  = PUSER;
    //
    p->p_euid = cu->p_euid;
    p->p_egid = cu->p_egid;
    p->p_ruid = cu->p_ruid;
    p->p_rgid = cu->p_rgid;
    // increase the reference count of inodes, and dup files
    if (cu->p_wdir != NULL) {
        p->p_wdir = cu->p_wdir;
        p->p_wdir->i_count++;
        p->p_iroot = cu->p_iroot;
        p->p_iroot->i_count++;
    }
    // dup the files, and fdflag
    for (fd=0; fd<NOFILE; fd++){
        fp = cu->p_ofile[fd];
        if (fp != NULL) {
            fp->f_count++;
            fp->f_ino->i_count++;
        }
        p->p_ofile[fd] = fp;
        p->p_fdflag[fd] = cu->p_fdflag[fd];
    }
    // signals
    p->p_sig = cu->p_sig;
    p->p_sigmask = cu->p_sigmask;
    for (n=0; n<NSIG; n++) {
        p->p_sigact[n] = cu->p_sigact[n];
    }
    // clone kernel's address space.
    vm_clone(&p->p_vm);
    p->p_contxt = cu->p_contxt;
    p->p_contxt.eip = (uint)func;
    p->p_contxt.esp = (uint)p+PAGE;
    p->p_stat = SRUN;
    return p;
}
Esempio n. 4
0
int tune(int aid, int sid)
{
	adapter *ad = get_adapter(aid);
	int rv = 0;
	SPid *p;

	if (!ad)
		return -400;

	mutex_lock(&ad->mutex);

	ad->last_sort = getTick();
	if (sid == ad->master_sid && ad->do_tune)
	{
		ad->tp.switch_type = ad->switch_type;
		ad->tp.uslot = ad->uslot;
		ad->tp.ufreq = ad->ufreq;
		ad->tp.pin = ad->pin;

		ad->tp.committed_no = ad->committed_no;
		ad->tp.uncommitted_no = ad->uncommitted_no;

		rv = ad->tune(ad->id, &ad->tp);
		ad->status = 0;
		ad->status_cnt = 0;
		set_socket_pos(ad->sock, 0);	// flush the existing buffer
		ad->rlen = 0;
		if (ad->sid_cnt > 1)	 // the master changed the frequency
		{
			close_streams_for_adapter(aid, sid);
			if (update_pids(aid))
			{
				mutex_unlock(&ad->mutex);
				return -503;
			}
		}
#ifdef TABLES_H
		p = find_pid(aid, 0);
		if (!p || p->flags == 3) // add pid 0 if not explicitly added
		{
			LOG(
					"Adding pid 0 to the list of pids as not explicitly added for adapter %d",
					aid);
			mark_pid_add(-1, aid, 0);
		}
#endif
	}
	else
		LOG("not tuning for SID %d (do_tune=%d, master_sid=%d)", sid,
				ad->do_tune, ad->master_sid);
	if (rv < 0)
		mark_pids_deleted(aid, sid, NULL);
	if (update_pids(aid))
	{
		mutex_unlock(&ad->mutex);
		return -503;
	}
	mutex_unlock(&ad->mutex);
	return rv;
}
Esempio n. 5
0
asmlinkage long sys_setsid(void)
{
	struct pid *pid;
	int err = -EPERM;

	if (!thread_group_leader(current))
		return -EINVAL;

	down(&tty_sem);
	write_lock_irq(&tasklist_lock);

	pid = find_pid(PIDTYPE_PGID, current->pid);
	if (pid)
		goto out;

	current->signal->leader = 1;
	__set_special_pids(current->pid, current->pid);
	current->signal->tty = NULL;
	current->signal->tty_old_pgrp = 0;
	err = process_group(current);
out:
	write_unlock_irq(&tasklist_lock);
	up(&tty_sem);
	return err;
}
Esempio n. 6
0
int mark_pid_add(int sid, int aid, int _pid)
{
	adapter *ad;
	int k, i;
	ad = get_adapter(aid);
	int found = 0;
	SPid *p;
	if (!ad)
		return 1;
	// check if the pid already exists, if yes add the sid
	if ((p = find_pid(aid, _pid)))
	{
		LOG("found already existing pid %d flags %d", _pid, p->flags);
		for (k = 0; k < MAX_STREAMS_PER_PID; k++)
			if (p->sid[k] == -1 || p->sid[k] == sid)
			{
				if (p->flags == 3)
					p->flags = 2;
				p->sid[k] = sid;
				found = 1;
				break;
			}
		if (!found)
		{
			LOG("too many streams for PID %d adapter %d", _pid, aid);
			return -1;

		}
#ifdef TABLES_H	
		tables_pid_add(ad, _pid, 1);
#endif
		return 0;
	}
	// add the new pid in a new position
	for (i = 0; i < MAX_PIDS; i++)
		if (ad->pids[i].flags <= 0)
		{
			ad->pids[i].flags = 2;
			ad->pids[i].pid = _pid;
			ad->pids[i].sid[0] = sid;
			ad->pids[i].filter = ad->pids[i].key = ad->pids[i].ecm_parity = 255;
#ifdef TABLES_H	
			tables_pid_add(ad, _pid, 0);
#endif
			return 0;
		}
	LOG("MAX_PIDS (%d) reached for adapter %d in adding PID: %d", MAX_PIDS, aid,
			_pid);
	dump_pids(aid);
	dump_adapters();
	return -1;

}
Esempio n. 7
0
asmlinkage int sunos_killpg(int pgrp, int sig)
{
	int ret;

	rcu_read_lock();
	ret = -EINVAL;
	if (pgrp > 0)
		ret = kill_pgrp(find_pid(pgrp), sig, 0);
	rcu_read_unlock();

	return ret;
}
/* removes fd from register, returning its filename and status via filename
   and status arguments.
*/
void deregister_fd(int fd)
{
	struct pid_reg **pid_iter = find_pid(getpid());
	if (*pid_iter)
	{
		struct fd_reg **fd_iter = find_fd(*pid_iter, fd);
		if (*fd_iter)
		{
			remove_fd(fd_iter);
			if ((*pid_iter)->fd_head == 0) remove_pid(pid_iter);
		}
	}
}
Esempio n. 9
0
int send_sig(char     *svname,
	     char     *opt,
	     int      all,
	     s_svname *list)
{
  int pid;

  if (all)
    send_to_all(opt, list);
  else
    {
      pid = find_pid(svname, list);
      if (pid)
	which_sig(pid, opt);
    }
}
Esempio n. 10
0
static void parseVM(char*vmname)
{
	xmlDoc *doc = NULL;
	xmlNode *root_element = NULL;
	doc = xmlReadFile(vmname, NULL, 0);

	if (doc == NULL)
	{
	  printf("Could not parse VM metamodel %s\n", vmname);
	  return;
	}

	root_element = xmlDocGetRootElement(doc);
	find_pid(root_element);
    //if (pid>0) printf("Found pid %d\n", pid);
	xmlFreeDoc(doc);
	xmlCleanupParser();
}
Esempio n. 11
0
static void find_pid(xmlNode * a_node)
{
    xmlNode *cur_node = NULL;
    xmlChar *uri;

    for (cur_node = a_node; cur_node; cur_node = cur_node->next) 
    {
      if (cur_node->type == XML_ELEMENT_NODE && !strcmp((char*)cur_node->name, "vcpu"))
        {      
          uri = xmlGetProp(cur_node, (xmlChar*)"pid");
          //printf("uri: %s\n", uri);
          if (!pid)
            pid=atoi((char*)uri);
	      xmlFree(uri);
	    }
      find_pid(cur_node->children); 
    }
}
Esempio n. 12
0
void mark_pid_deleted(int aid, int sid, int _pid, SPid *p)
{
	int j;
	int cnt = 0, sort = 0;
	if (!p)
		p = find_pid(aid, _pid);
	if (!p)
		return;
	if (sid == -1) // delete all sids and the pid
	{
		if (p->flags != 0)
			p->flags = 3;
		for (j = 0; j < MAX_STREAMS_PER_PID; j++)
			if (sid == -1)  // delete all pids if sid = -1
				p->sid[j] = -1;
		return;
	}
	// sid != -1
	for (j = 0; j < MAX_STREAMS_PER_PID; j++)
		if (p->sid[j] == sid)  // delete all pids where .sid == sid
		{
			p->sid[j] = -1;
			if ((j + 1 < MAX_PIDS) && (p->sid[j + 1] >= 0))
				sort = 1;
		}

	for (j = 0; j < MAX_STREAMS_PER_PID; j++)
		if (p->sid[j] >= 0)
			cnt++;
//	if ((cnt == 0) && (p->flags != 0) && (p->type == 0 || didit))
	if ((cnt == 0) && (p->flags != 0) && (p->type == 0))
		p->flags = 3;

	if (sort)
	{
		for (j = 0; j < MAX_STREAMS_PER_PID - 1; j++)
			if (p->sid[j + 1] > p->sid[j])
			{
				unsigned char t = p->sid[j];
				p->sid[j] = p->sid[j + 1];
				p->sid[j + 1] = t;
			}
	}
}
void copy_fds(pid_t parent, pid_t child)
{
	struct pid_reg *pid_iter = *find_pid(parent);
	if (pid_iter)
	{
		struct fd_reg *fd_iter = pid_iter->fd_head;

		add_pid(child);
		struct fd_reg **nextfd = &pid_head->fd_head;

		while (fd_iter)
		{
			*nextfd = malloc(sizeof(struct fd_reg));
			**nextfd = *fd_iter;
			nextfd = &(*nextfd)->next;
			fd_iter = fd_iter->next;
		}
	}
}
Esempio n. 14
0
//*****************************************************
// 1 second timer
//*****************************************************
void firejail_timeout(unsigned long dummy) {
	NsRule *ptr = head.next;
	
	// decrement trace
	if (--trace_cnt < 0)
		trace_cnt = 0;

	spin_lock(&head_lock);
	// walk the rules list and disable rules if no process left in the namespace
	while (ptr) {
		if (ptr->active && find_pid(ptr->sandbox_pid) == NULL) {
			printk(KERN_INFO "firejail[%u]: release sandbox.\n", ptr->sandbox_pid);
			ptr->active = 0;
		}
			
		ptr = ptr->next;
	}
	spin_unlock(&head_lock);
	
	// restart timer
	mod_timer(&rate_timer, jiffies + HZ);
}
void register_fd(int fd, const char *filename, struct status_t *status)
{
	struct pid_reg *pid_iter = *find_pid(getpid());
	if (pid_iter == 0)
	{
		add_pid(getpid());
		pid_iter = pid_head;
	}

	struct fd_reg *fd_iter = *find_fd(pid_iter, fd);
	if (fd_iter == 0)
	{
		add_fd(pid_iter, fd, filename, status);
	} else {
#  if DEBUG == 1
		if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fd %d already registered (is %s, was %s).\n",
			getpid(), fd, filename, fd_iter->filename);
#  endif
		free(fd_iter->filename);
		fd_iter->filename = strdup(filename);
		fd_iter->status = *status;
	}
}
Esempio n. 16
0
void stats_reset()
{
	g_list_free(element_statistics_list);
	element_statistics_list = NULL;

	if (X_pid < 0) {
		X_pid = find_pid("Xorg");
		init_pstat(&pstat_Xserver_base);
		init_pstat(&pstat_Xserver_current);
		strcpy(pstat_Xserver_base.process_stats.name, "Xorg");
		strcpy(pstat_Xserver_current.process_stats.name, "Xorg");
	}

	if (process_pid < 0) {
		process_pid = getpid();
		init_pstat(&pstat_process_base);
		init_pstat(&pstat_process_current);
		strcpy(pstat_process_base.process_stats.name, "gstplay");
		strcpy(pstat_process_current.process_stats.name, "gstplay");
	}
	get_usage(process_pid, &pstat_process_base);
	if (X_pid >= 0)
		get_usage(X_pid, &pstat_Xserver_base);
}
Esempio n. 17
0
int process_pmt(adapter *ad, unsigned char *b)
{
	int pi_len = 0, ver, pmt_len = 0, i, _pid, es_len, len, init_pi_len;
	int program_id = 0;
	int prio = 0;
	int enabled_channels = 0;
	unsigned char *pmt, *pi, tmp_pi[MAX_PI_LEN];
	unsigned char *init_b = b;
	int caid, capid, pid, spid, stype;
	uint16_t pid_list[MAX_PIDS];
	int npl = 0;
	SPid *p, *cp;
	int64_t pid_key = TABLES_ITEM + ((1 + ad->id) << 24) + 0;
	int16_t *pids;
	int opmt, old_key;

	if ((b[0] != 0x47)) // make sure we are dealing with TS
		return 0;

	if ((b[1] & 0x40) && ((b[4] != 0) || (b[5] != 2)))
		return 0;

	pid = (b[1] & 0x1F) * 256 + b[2];
	if (!(p = find_pid(ad->id, pid)))
		return -1;

	if (!p || (p->type & PMT_COMPLETE) || (p->type == 0))
		return 0;

	program_id = b[8] * 256 + b[9];
	ver = b[10] & 0x3F;

	if (((p->type & 0xF) != TYPE_PMT) && p->version == ver
			&& p->csid == program_id) // pmt processed already
		return 0;

	if (!(pmt_len = assemble_packet(&b, ad, 1)))
		return 0;

	pi_len = ((b[10] & 0xF) << 8) + b[11];

	program_id = p->csid = b[3] * 256 + b[4];
	ver = p->version = b[5] & 0x3F;

	LOG("PMT pid: %04X (%d), pmt_len %d, pi_len %d, sid %04X (%d)", pid, pid,
			pmt_len, pi_len, program_id, program_id);
	pi = b + 12;
	pmt = pi + pi_len;

	if (pmt_len > 1500)
		return 0;

	if (pi_len > pmt_len)
		pi_len = 0;

	init_pi_len = pi_len;
	pi_len = 0;

	if (init_pi_len > 0)
		find_pi(pi, init_pi_len, tmp_pi, &pi_len);

	pi = tmp_pi;

	es_len = 0;
	pids = (int16_t *) getItem(pid_key);
	if (!pids)
		return 0;

	p->type |= TYPE_PMT;
	pids[pid] = -TYPE_PMT;

	for (i = 0; i < pmt_len - init_pi_len - 17; i += (es_len) + 5) // reading streams
	{
		es_len = (pmt[i + 3] & 0xF) * 256 + pmt[i + 4];
		stype = pmt[i];
		spid = (pmt[i + 1] & 0x1F) * 256 + pmt[i + 2];
		LOG(
				"PMT pid %d - stream pid %04X (%d), type %d, es_len %d, pos %d, pi_len %d old pmt %d, old pmt for this pid %d",
				pid, spid, spid, stype, es_len, i, pi_len, pids[pid],
				pids[spid]);
		if ((es_len + i > pmt_len) || (init_pi_len + es_len == 0))
			break;
		if (stype != 2 && stype != 3 && stype != 4 && stype != 6 && stype != 27
				&& stype != 36 || spid < 64)
			continue;

		find_pi(pmt + i + 5, es_len, pi, &pi_len);

		if (pi_len == 0)
			continue;

		opmt = pids[spid];
		pids[spid] = pid;
		if ((opmt > 0) && (abs(opmt) != abs(pid))) // this pid is associated with another PMT - link this PMT with the old one (if not linked already)
		{
			if (pids[pid] == -TYPE_PMT)
			{
				pids[pid] = -opmt;
				LOG("Linking PMT pid %d with PMT pid %d for pid %d, adapter %d",
						pid, opmt, spid, ad->id);
			}
		}

		if ((cp = find_pid(ad->id, spid))) // the pid is already requested by the client
		{
			enabled_channels++;
			pid_list[npl++] = spid;
			old_key = cp->key;
		}

	}

	if ((pi_len > 0) && enabled_channels) // PMT contains CA descriptor and there are active pids
	{
		SPMT pmt =
		{ .pmt = b, .pmt_len = pmt_len, .pi = pi, .pi_len = pi_len, .p = p,
				.sid = program_id, .ver = ver, .pid = pid, .old_key = old_key };
		p->enabled_channels = enabled_channels;

		if (program_id > 0)
			run_ca_action(CA_ADD_PMT, ad, &pmt);
		else
			LOG("PMT %d, SID is 0, not running ca_action", pid);

		for (i = 0; i < npl; i++)
		{
			cp = find_pid(ad->id, pid_list[i]);
			if (cp)
				cp->key = p->key;
		}
		p->type |= PMT_COMPLETE;
	}
Esempio n. 18
0
int vnmr_unlock(int argc, char *argv[], int retc, char *retv[] )
{
	char		host_of_lock[ MAXPATHL ], jexpcmd[ 16 ],
			lock_file_name[ MAXPATHL ];
	int		expn, ival, mode_of_lock, pid_of_lock, force;

	expn = check_unlock_args( argc, argv, &force );
        if (expn == expdir_to_expnum(curexpdir))
           RETURN;
	if (expn < 1) ABORT;

	if (get_secondary_lock( expn, SEC_LOCK_COUNT ) != 0) {
		Werrprintf( "%s: cannot obtain secondary lock", argv[ 0 ] );
		ABORT;
	}
	get_primary_lockfile( expn, userdir, &lock_file_name[ 0 ] );
	ival = verify_primary_lock(
		&lock_file_name[ 0 ], &mode_of_lock, &host_of_lock[ 0 ], &pid_of_lock
	);
	remove_secondary_lock( expn );

	if (ival != 0) {
                if (access( &lock_file_name[ 0 ], F_OK ) == 0)
		  unlink( &lock_file_name[ 0 ] );
                sprintf( &jexpcmd[ 0 ], "jexp(%d)\n", expn );
                execString( &jexpcmd[ 0 ] );
                RETURN;
        }

	if (!force && (mode_of_lock == ACQUISITION)) {
		Werrprintf( "%s:  cannot remove acquisition lock", argv[ 0 ] );
		ABORT;
	}

	disp_status( "UNLOCK  " );
	if (!force && (strcmp( &host_of_lock[ 0 ], &HostName[ 0 ] ) != 0)) {
                Werrprintf( "%s:  experiment locked by remote host %s",
                        argv[ 0 ], &host_of_lock[ 0 ]
                );
                disp_status( "        " );
                ABORT;
        }
 
	ival = find_pid( pid_of_lock, argv[ 0 ] );
	if ( ival < 0) {
		disp_status( "        " );
		ABORT;
	}
	else if (!force && (ival > 0)) {
                Werrprintf(
                    "%s:  experiment locked by active process", argv[ 0 ]
                );
                disp_status( "        " );
                ABORT;
        }

	ival = unlink( &lock_file_name[ 0 ] );
	if (ival != 0) {
                Werrprintf( "%s:  unable to remove lock file", argv[ 0 ] );
                disp_status( "        " );
                ABORT;
        }

	Winfoprintf( "experiment %d unlocked", expn );
	disp_status( "        " );
	sprintf( &jexpcmd[ 0 ], "jexp(%d)\n", expn );
	execString( &jexpcmd[ 0 ] );
	RETURN;
}
Esempio n. 19
0
int process_pat(adapter *ad, unsigned char *b)
{
	int pat_len = 0, i, tid = 0, sid, pid, ver, csid = 0;
	int64_t pid_key = TABLES_ITEM + ((1 + ad->id) << 24) + 0;
	int16_t *pids;
	unsigned char *init_b = b;
	SPid *p;

	if (((b[1] & 0x1F) != 0) || (b[2] != 0))
		return 0;

	if (b[0] != 0x47)
		return 0;

	if ((b[1] & 0x40) && ((b[4] != 0) || (b[5] != 0)))
		return 0;

//	p = find_pid(ad->id, 0);
//	if(!p)
//		return 0;

	tid = b[8] * 256 + b[9];
	ver = b[10] & 0x3E;

	if ((ad->transponder_id == tid) && (ad->pat_ver == ver)) //pat already processed
		return 0;

	if (!(pat_len = assemble_packet(&b, ad, 1)))
		return 0;

	tid = b[3] * 256 + b[4];
	ver = b[5] & 0x3E;
	if (((ad->transponder_id != tid) || (ad->pat_ver != ver)) && (pat_len > 0)
			&& (pat_len < 1500))
	{
		ad->pat_processed = 0;
	}

	if (ad->pat_processed)
		return 0;

	ad->pat_ver = ver;
	ad->transponder_id = tid;
#ifndef DISABLE_DVBAPI
	dvbapi_delete_keys_for_adapter(ad->id);
#endif
//	LOG("tid %d pat_len %d: %02X %02X %02X %02X %02X %02X %02X %02X", tid, pat_len, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
	setItem(pid_key, b, 1, 0);
	setItemSize(pid_key, 8192 * sizeof(*pids));
	pids = (int16_t *) getItem(pid_key);
	memset(pids, 0, 8192 * sizeof(*pids));
	pat_len -= 9;
	b += 8;
	LOGL(2, "PAT Adapter %d, Transponder ID %d, len %d, version %d", ad->id,
			tid, pat_len, ad->pat_ver);
	if (pat_len > 1500)
		return 0;

	for (i = 0; i < pat_len; i += 4)
	{
		sid = b[i] * 256 + b[i + 1];
		pid = (b[i + 2] & 0x1F) * 256 + b[i + 3];
		LOGL(2, "Adapter %d, PMT sid %d (%04X), pid %d", ad->id, sid, sid, pid);
		if (sid > 0)
		{
			pids[pid] = -TYPE_PMT;
			p = find_pid(ad->id, pid);
			if (!p)
				mark_pid_add(-1, ad->id, pid);
			if ((p = find_pid(ad->id, pid)))
			{
				p->type = TYPE_PMT;
				csid = pid;
				if (p->flags == 3)
					p->flags = 1;
			}
		}
	}
	update_pids(ad->id);
	ad->pat_processed = 1;
	return csid;
}